source: LMDZ6/branches/Amaury_dev/libf/dyn3d/vlsplt.F90 @ 5186

Last change on this file since 5186 was 5182, checked in by abarral, 2 months ago

(WIP) Replace REPROBUS CPP KEY by logical
properly name modules

  • 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: 25.0 KB
Line 
1
2! $Id: vlsplt.F90 5182 2024-09-10 14:25:29Z abarral $
3!
4
5SUBROUTINE vlsplt(q, pente_max, masse, w, pbaru, pbarv, pdt, iq)
6  USE lmdz_infotrac, ONLY: nqtot, tracers
7  USE lmdz_ssum_scopy, ONLY: scopy
8
9  ! Auteurs:   P.Le Van, F.Hourdin, F.Forget
10
11  !    ********************************************************************
12  ! Shema  d'advection " pseudo amont " .
13  !    ********************************************************************
14  ! q,pbaru,pbarv,w sont des arguments d'entree  pour le s-pg ....
15
16  !   pente_max facteur de limitation des pentes: 2 en general
17  !                                           0 pour un schema amont
18  !   pbaru,pbarv,w flux de masse en u ,v ,w
19  !   pdt pas de temps
20
21  !   --------------------------------------------------------------------
22USE lmdz_dimensions, ONLY: iim, jjm, llm, ndm
23  USE lmdz_paramet
24  IMPLICIT NONE
25  !
26
27
28
29
30  !   Arguments:
31  !   ----------
32  REAL :: masse(ip1jmp1, llm), pente_max
33  REAL :: pbaru(ip1jmp1, llm), pbarv(ip1jm, llm)
34  REAL :: q(ip1jmp1, llm, nqtot)
35  REAL :: w(ip1jmp1, llm), pdt
36  INTEGER :: iq ! CRisi
37
38  !  Local
39  !   ---------
40
41  INTEGER :: ij, l
42
43  REAL :: zm(ip1jmp1, llm, nqtot)
44  REAL :: mu(ip1jmp1, llm)
45  REAL :: mv(ip1jm, llm)
46  REAL :: mw(ip1jmp1, llm + 1)
47  REAL :: zq(ip1jmp1, llm, nqtot)
48  REAL :: zzpbar, zzw
49  INTEGER :: ifils, iq2 ! CRisi
50
51  REAL :: qmin, qmax
52  DATA qmin, qmax/0., 1.e33/
53
54  zzpbar = 0.5 * pdt
55  zzw = pdt
56  DO l = 1, llm
57    DO ij = iip2, ip1jm
58      mu(ij, l) = pbaru(ij, l) * zzpbar
59    ENDDO
60    DO ij = 1, ip1jm
61      mv(ij, l) = pbarv(ij, l) * zzpbar
62    ENDDO
63    DO ij = 1, ip1jmp1
64      mw(ij, l) = w(ij, l) * zzw
65    ENDDO
66  ENDDO
67
68  DO ij = 1, ip1jmp1
69    mw(ij, llm + 1) = 0.
70  ENDDO
71
72  CALL SCOPY(ijp1llm, q(1, 1, iq), 1, zq(1, 1, iq), 1)
73  CALL SCOPY(ijp1llm, masse, 1, zm(1, 1, iq), 1)
74
75  DO ifils = 1, tracers(iq)%nqDescen
76    iq2 = tracers(iq)%iqDescen(ifils)
77    CALL SCOPY(ijp1llm, q(1, 1, iq2), 1, zq(1, 1, iq2), 1)
78  enddo
79
80  CALL vlx(zq, pente_max, zm, mu, iq)
81  CALL vly(zq, pente_max, zm, mv, iq)
82  CALL vlz(zq, pente_max, zm, mw, iq)
83  CALL vly(zq, pente_max, zm, mv, iq)
84  CALL vlx(zq, pente_max, zm, mu, iq)
85
86  DO l = 1, llm
87    DO ij = 1, ip1jmp1
88      q(ij, l, iq) = zq(ij, l, iq)
89    ENDDO
90    DO ij = 1, ip1jm + 1, iip1
91      q(ij + iim, l, iq) = q(ij, l, iq)
92    ENDDO
93  ENDDO
94  ! CRisi: aussi pour les fils
95  DO ifils = 1, tracers(iq)%nqDescen
96    iq2 = tracers(iq)%iqDescen(ifils)
97    DO l = 1, llm
98      DO ij = 1, ip1jmp1
99        q(ij, l, iq2) = zq(ij, l, iq2)
100      ENDDO
101      DO ij = 1, ip1jm + 1, iip1
102        q(ij + iim, l, iq2) = q(ij, l, iq2)
103      ENDDO
104    ENDDO
105  enddo
106
107END SUBROUTINE vlsplt
108RECURSIVE SUBROUTINE vlx(q, pente_max, masse, u_m, iq)
109  USE lmdz_infotrac, ONLY: nqtot, tracers, & ! CRisi
110          min_qParent, min_qMass, min_ratio ! MVals et CRisi
111  USE lmdz_iniprint, ONLY: lunout, prt_level
112
113  ! Auteurs:   P.Le Van, F.Hourdin, F.Forget
114
115  !    ********************************************************************
116  ! Shema  d'advection " pseudo amont " .
117  !    ********************************************************************
118  ! nq,iq,q,pbaru,pbarv,w sont des arguments d'entree  pour le s-pg ....
119
120
121  !   --------------------------------------------------------------------
122USE lmdz_dimensions, ONLY: iim, jjm, llm, ndm
123  USE lmdz_paramet
124  IMPLICIT NONE
125  !
126
127
128
129
130  !   Arguments:
131  !   ----------
132  REAL :: masse(ip1jmp1, llm, nqtot), pente_max
133  REAL :: u_m(ip1jmp1, llm)
134  REAL :: q(ip1jmp1, llm, nqtot)
135  INTEGER :: iq ! CRisi
136
137  !  Local
138  !   ---------
139
140  INTEGER :: ij, l, j, i, iju, ijq, indu(ip1jmp1), niju
141  INTEGER :: n0, iadvplus(ip1jmp1, llm), nl(llm)
142
143  REAL :: new_m, zu_m, zdum(ip1jmp1, llm)
144  REAL :: dxq(ip1jmp1, llm), dxqu(ip1jmp1)
145  REAL :: zz(ip1jmp1)
146  REAL :: adxqu(ip1jmp1), dxqmax(ip1jmp1, llm)
147  REAL :: u_mq(ip1jmp1, llm)
148
149  ! CRisi
150  REAL :: masseq(ip1jmp1, llm, nqtot), Ratio(ip1jmp1, llm, nqtot)
151  INTEGER :: ifils, iq2 ! CRisi
152
153  LOGICAL, SAVE :: first
154  DATA first/.TRUE./
155
156  !   calcul de la pente a droite et a gauche de la maille
157
158  IF (pente_max>-1.e-5) THEN
159    ! IF (pente_max.gt.10) THEN
160
161    !   calcul des pentes avec limitation, Van Leer scheme I:
162    !   -----------------------------------------------------
163
164    !   calcul de la pente aux points u
165    DO l = 1, llm
166      DO ij = iip2, ip1jm - 1
167        dxqu(ij) = q(ij + 1, l, iq) - q(ij, l, iq)
168      ENDDO
169      DO ij = iip1 + iip1, ip1jm, iip1
170        dxqu(ij) = dxqu(ij - iim)
171        ! sigu(ij)=sigu(ij-iim)
172      ENDDO
173
174      DO ij = iip2, ip1jm
175        adxqu(ij) = abs(dxqu(ij))
176      ENDDO
177
178      !   calcul de la pente maximum dans la maille en valeur absolue
179
180      DO ij = iip2 + 1, ip1jm
181        dxqmax(ij, l) = pente_max * &
182                min(adxqu(ij - 1), adxqu(ij))
183        ! limitation subtile
184        !    ,      min(adxqu(ij-1)/sigu(ij-1),adxqu(ij)/(1.-sigu(ij)))
185
186      ENDDO
187
188      DO ij = iip1 + iip1, ip1jm, iip1
189        dxqmax(ij - iim, l) = dxqmax(ij, l)
190      ENDDO
191
192      DO ij = iip2 + 1, ip1jm
193        IF(dxqu(ij - 1) * dxqu(ij)>0) THEN
194          dxq(ij, l) = dxqu(ij - 1) + dxqu(ij)
195        ELSE
196          !   extremum local
197          dxq(ij, l) = 0.
198        ENDIF
199        dxq(ij, l) = 0.5 * dxq(ij, l)
200        dxq(ij, l) = &
201                sign(min(abs(dxq(ij, l)), dxqmax(ij, l)), dxq(ij, l))
202      ENDDO
203
204    ENDDO ! l=1,llm
205    !print*,'Ok calcul des pentes'
206
207  ELSE ! (pente_max.lt.-1.e-5)
208
209    !   Pentes produits:
210    !   ----------------
211
212    DO l = 1, llm
213      DO ij = iip2, ip1jm - 1
214        dxqu(ij) = q(ij + 1, l, iq) - q(ij, l, iq)
215      ENDDO
216      DO ij = iip1 + iip1, ip1jm, iip1
217        dxqu(ij) = dxqu(ij - iim)
218      ENDDO
219
220      DO ij = iip2 + 1, ip1jm
221        zz(ij) = dxqu(ij - 1) * dxqu(ij)
222        zz(ij) = zz(ij) + zz(ij)
223        IF(zz(ij)>0) THEN
224          dxq(ij, l) = zz(ij) / (dxqu(ij - 1) + dxqu(ij))
225        ELSE
226          !   extremum local
227          dxq(ij, l) = 0.
228        ENDIF
229      ENDDO
230
231    ENDDO
232
233  ENDIF ! (pente_max.lt.-1.e-5)
234
235  !   bouclage de la pente en iip1:
236  !   -----------------------------
237
238  DO l = 1, llm
239    DO ij = iip1 + iip1, ip1jm, iip1
240      dxq(ij - iim, l) = dxq(ij, l)
241    ENDDO
242    DO ij = 1, ip1jmp1
243      iadvplus(ij, l) = 0
244    ENDDO
245
246  ENDDO
247  !   calcul des flux a gauche et a droite
248
249  !   on cumule le flux correspondant a toutes les mailles dont la masse
250  !   au travers de la paroi pENDant le pas de temps.
251  DO l = 1, llm
252    DO ij = iip2, ip1jm - 1
253      IF (u_m(ij, l)>0.) THEN
254        zdum(ij, l) = 1. - u_m(ij, l) / masse(ij, l, iq)
255        u_mq(ij, l) = u_m(ij, l) * (q(ij, l, iq) + 0.5 * zdum(ij, l) * dxq(ij, l))
256      ELSE
257        zdum(ij, l) = 1. + u_m(ij, l) / masse(ij + 1, l, iq)
258        u_mq(ij, l) = u_m(ij, l) * (q(ij + 1, l, iq) &
259                - 0.5 * zdum(ij, l) * dxq(ij + 1, l))
260      ENDIF
261    ENDDO
262  ENDDO
263
264  !   detection des points ou on advecte plus que la masse de la
265  !   maille
266  DO l = 1, llm
267    DO ij = iip2, ip1jm - 1
268      IF(zdum(ij, l)<0) THEN
269        iadvplus(ij, l) = 1
270        u_mq(ij, l) = 0.
271      ENDIF
272    ENDDO
273  ENDDO
274  DO l = 1, llm
275    DO ij = iip1 + iip1, ip1jm, iip1
276      iadvplus(ij, l) = iadvplus(ij - iim, l)
277    ENDDO
278  ENDDO
279
280
281  !   traitement special pour le cas ou on advecte en longitude plus que le
282  !   contenu de la maille.
283  !   cette partie est mal vectorisee.
284
285  !  calcul du nombre de maille sur lequel on advecte plus que la maille.
286
287  n0 = 0
288  DO l = 1, llm
289    nl(l) = 0
290    DO ij = iip2, ip1jm
291      nl(l) = nl(l) + iadvplus(ij, l)
292    ENDDO
293    n0 = n0 + nl(l)
294  ENDDO
295
296  IF(n0>0) THEN
297    IF (prt_level > 2) PRINT *, &
298            'Nombre de points pour lesquels on advect plus que le' &
299            , 'contenu de la maille : ', n0
300
301    DO l = 1, llm
302      IF(nl(l)>0) THEN
303        iju = 0
304        !   indicage des mailles concernees par le traitement special
305        DO ij = iip2, ip1jm
306          IF(iadvplus(ij, l)==1.AND.mod(ij, iip1)/=0) THEN
307            iju = iju + 1
308            indu(iju) = ij
309          ENDIF
310        ENDDO
311        niju = iju
312
313        !  traitement des mailles
314        DO iju = 1, niju
315          ij = indu(iju)
316          j = (ij - 1) / iip1 + 1
317          zu_m = u_m(ij, l)
318          u_mq(ij, l) = 0.
319          IF(zu_m>0.) THEN
320            ijq = ij
321            i = ijq - (j - 1) * iip1
322            !   accumulation pour les mailles completements advectees
323            DO while(zu_m>masse(ijq, l, iq))
324              u_mq(ij, l) = u_mq(ij, l) + q(ijq, l, iq) &
325                      * masse(ijq, l, iq)
326              zu_m = zu_m - masse(ijq, l, iq)
327              i = mod(i - 2 + iim, iim) + 1
328              ijq = (j - 1) * iip1 + i
329            ENDDO
330            !   ajout de la maille non completement advectee
331            u_mq(ij, l) = u_mq(ij, l) + zu_m * &
332                    (q(ijq, l, iq) + 0.5 * (1. - zu_m / masse(ijq, l, iq)) &
333                            * dxq(ijq, l))
334          ELSE
335            ijq = ij + 1
336            i = ijq - (j - 1) * iip1
337            !   accumulation pour les mailles completements advectees
338            DO while(-zu_m>masse(ijq, l, iq))
339              u_mq(ij, l) = u_mq(ij, l) - q(ijq, l, iq) &
340                      * masse(ijq, l, iq)
341              zu_m = zu_m + masse(ijq, l, iq)
342              i = mod(i, iim) + 1
343              ijq = (j - 1) * iip1 + i
344            ENDDO
345            !   ajout de la maille non completement advectee
346            u_mq(ij, l) = u_mq(ij, l) + zu_m * (q(ijq, l, iq) - &
347                    0.5 * (1. + zu_m / masse(ijq, l, iq)) * dxq(ijq, l))
348          ENDIF
349        ENDDO
350      ENDIF
351    ENDDO
352  ENDIF  ! n0.gt.0
353
354
355  !   bouclage en latitude
356  !print*,'cvant bouclage en latitude'
357  DO l = 1, llm
358    DO ij = iip1 + iip1, ip1jm, iip1
359      u_mq(ij, l) = u_mq(ij - iim, l)
360    ENDDO
361  ENDDO
362
363  ! CRisi: appel récursif de l'advection sur les fils.
364  ! Il faut faire ça avant d'avoir mis à jour q et masse
365  !WRITE(*,*) 'vlsplt 326: iq,nqDesc(iq)=',iq,tracers(iq)%nqDescen
366
367  DO ifils = 1, tracers(iq)%nqDescen
368    iq2 = tracers(iq)%iqDescen(ifils)
369    DO l = 1, llm
370      DO ij = iip2, ip1jm
371        ! On a besoin de q et masse seulement entre iip2 et ip1jm
372        !masseq(ij,l,iq2)=masse(ij,l,iq)*q(ij,l,iq)
373        !           !Ratio(ij,l,iq2)=q(ij,l,iq2)/q(ij,l,iq)
374        !Mvals: veiller a ce qu'on n'ait pas de denominateur nul
375        masseq(ij, l, iq2) = max(masse(ij, l, iq) * q(ij, l, iq), min_qMass)
376        IF (q(ij, l, iq)>min_qParent) THEN
377          Ratio(ij, l, iq2) = q(ij, l, iq2) / q(ij, l, iq)
378        else
379          Ratio(ij, l, iq2) = min_ratio
380        endif
381      enddo
382    enddo
383  enddo
384  DO ifils = 1, tracers(iq)%nqChildren
385    iq2 = tracers(iq)%iqDescen(ifils)
386    CALL vlx(Ratio, pente_max, masseq, u_mq, iq2)
387  enddo
388  ! end CRisi
389
390
391  !   calcul des tENDances
392
393  DO l = 1, llm
394    DO ij = iip2 + 1, ip1jm
395      !MVals: veiller a ce qu'on ait pas de denominateur nul
396      new_m = max(masse(ij, l, iq) + u_m(ij - 1, l) - u_m(ij, l), min_qMass)
397      q(ij, l, iq) = (q(ij, l, iq) * masse(ij, l, iq) + &
398              u_mq(ij - 1, l) - u_mq(ij, l)) &
399              / new_m
400      masse(ij, l, iq) = new_m
401    ENDDO
402    DO ij = iip1 + iip1, ip1jm, iip1
403      q(ij - iim, l, iq) = q(ij, l, iq)
404      masse(ij - iim, l, iq) = masse(ij, l, iq)
405    ENDDO
406  ENDDO
407
408  ! retablir les fils en rapport de melange par rapport a l'air:
409  ! On calcule q entre iip2+1,ip1jm -> on fait pareil pour ratio
410  ! puis on boucle en longitude
411  DO ifils = 1, tracers(iq)%nqDescen
412    iq2 = tracers(iq)%iqDescen(ifils)
413    DO l = 1, llm
414      DO ij = iip2 + 1, ip1jm
415        q(ij, l, iq2) = q(ij, l, iq) * Ratio(ij, l, iq2)
416      enddo
417      DO ij = iip1 + iip1, ip1jm, iip1
418        q(ij - iim, l, iq2) = q(ij, l, iq2)
419      enddo ! DO ij=ijb+iip1-1,ije,iip1
420    enddo !DO l=1,llm
421  enddo
422
423END SUBROUTINE vlx
424RECURSIVE SUBROUTINE vly(q, pente_max, masse, masse_adv_v, iq)
425  USE lmdz_infotrac, ONLY: nqtot, tracers, & ! CRisi
426          min_qParent, min_qMass, min_ratio ! MVals et CRisi
427  USE lmdz_ssum_scopy, ONLY: ssum
428  USE lmdz_comgeom
429
430
431  ! Auteurs:   P.Le Van, F.Hourdin, F.Forget
432
433  !    ********************************************************************
434  ! Shema  d'advection " pseudo amont " .
435  !    ********************************************************************
436  ! q,masse_adv_v,w sont des arguments d'entree  pour le s-pg ....
437  ! dq            sont des arguments de sortie pour le s-pg ....
438
439
440  !   --------------------------------------------------------------------
441  USE comconst_mod, ONLY: pi
442USE lmdz_dimensions, ONLY: iim, jjm, llm, ndm
443  USE lmdz_paramet
444  IMPLICIT NONE
445  !
446
447
448
449
450  !   Arguments:
451  !   ----------
452  REAL :: masse(ip1jmp1, llm, nqtot), pente_max
453  REAL :: masse_adv_v(ip1jm, llm)
454  REAL :: q(ip1jmp1, llm, nqtot)
455  INTEGER :: iq ! CRisi
456
457  !  Local
458  !   ---------
459
460  INTEGER :: i, ij, l
461
462  REAL :: airej2, airejjm, airescb(iim), airesch(iim)
463  REAL :: dyq(ip1jmp1, llm), dyqv(ip1jm)
464  REAL :: adyqv(ip1jm), dyqmax(ip1jmp1)
465  REAL :: qbyv(ip1jm, llm)
466
467  REAL :: qpns, qpsn, dyn1, dys1, dyn2, dys2, newmasse, fn, fs
468  LOGICAL, SAVE :: first
469
470  REAL :: convpn, convps, convmpn, convmps
471  REAL :: massepn, masseps, qpn, qps
472  REAL :: sinlon(iip1), sinlondlon(iip1)
473  REAL :: coslon(iip1), coslondlon(iip1)
474  SAVE sinlon, coslon, sinlondlon, coslondlon
475  SAVE airej2, airejjm
476
477  REAL :: masseq(ip1jmp1, llm, nqtot), Ratio(ip1jmp1, llm, nqtot) ! CRisi
478  INTEGER :: ifils, iq2 ! CRisi
479
480  DATA first/.TRUE./
481
482  ! !WRITE(*,*) 'vly 578: entree, iq=',iq
483
484  IF(first) THEN
485    PRINT*, 'Shema  Amont nouveau  appele dans  Vanleer   '
486    first = .FALSE.
487    DO i = 2, iip1
488      coslon(i) = cos(rlonv(i))
489      sinlon(i) = sin(rlonv(i))
490      coslondlon(i) = coslon(i) * (rlonu(i) - rlonu(i - 1)) / pi
491      sinlondlon(i) = sinlon(i) * (rlonu(i) - rlonu(i - 1)) / pi
492    ENDDO
493    coslon(1) = coslon(iip1)
494    coslondlon(1) = coslondlon(iip1)
495    sinlon(1) = sinlon(iip1)
496    sinlondlon(1) = sinlondlon(iip1)
497    airej2 = SSUM(iim, aire(iip2), 1)
498    airejjm = SSUM(iim, aire(ip1jm - iim), 1)
499  ENDIF
500
501
502  !PRINT*,'CALCUL EN LATITUDE'
503
504  DO l = 1, llm
505
506    !   --------------------------------
507    !  CALCUL EN LATITUDE
508    !   --------------------------------
509
510    !   On commence par calculer la valeur du traceur moyenne sur le premier cercle
511    !   de latitude autour du pole (qpns pour le pole nord et qpsn pour
512    !    le pole nord) qui sera utilisee pour evaluer les pentes au pole.
513
514    DO i = 1, iim
515      airescb(i) = aire(i + iip1) * q(i + iip1, l, iq)
516      airesch(i) = aire(i + ip1jm - iip1) * q(i + ip1jm - iip1, l, iq)
517    ENDDO
518    qpns = SSUM(iim, airescb, 1) / airej2
519    qpsn = SSUM(iim, airesch, 1) / airejjm
520
521    !   calcul des pentes aux points v
522
523    DO ij = 1, ip1jm
524      dyqv(ij) = q(ij, l, iq) - q(ij + iip1, l, iq)
525      adyqv(ij) = abs(dyqv(ij))
526    ENDDO
527
528    !   calcul des pentes aux points scalaires
529
530    DO ij = iip2, ip1jm
531      dyq(ij, l) = .5 * (dyqv(ij - iip1) + dyqv(ij))
532      dyqmax(ij) = min(adyqv(ij - iip1), adyqv(ij))
533      dyqmax(ij) = pente_max * dyqmax(ij)
534    ENDDO
535
536    !   calcul des pentes aux poles
537
538    DO ij = 1, iip1
539      dyq(ij, l) = qpns - q(ij + iip1, l, iq)
540      dyq(ip1jm + ij, l) = q(ip1jm + ij - iip1, l, iq) - qpsn
541    ENDDO
542
543    !   filtrage de la derivee
544    dyn1 = 0.
545    dys1 = 0.
546    dyn2 = 0.
547    dys2 = 0.
548    DO ij = 1, iim
549      dyn1 = dyn1 + sinlondlon(ij) * dyq(ij, l)
550      dys1 = dys1 + sinlondlon(ij) * dyq(ip1jm + ij, l)
551      dyn2 = dyn2 + coslondlon(ij) * dyq(ij, l)
552      dys2 = dys2 + coslondlon(ij) * dyq(ip1jm + ij, l)
553    ENDDO
554    DO ij = 1, iip1
555      dyq(ij, l) = dyn1 * sinlon(ij) + dyn2 * coslon(ij)
556      dyq(ip1jm + ij, l) = dys1 * sinlon(ij) + dys2 * coslon(ij)
557    ENDDO
558
559    !   calcul des pentes limites aux poles
560
561    goto 8888
562    fn = 1.
563    fs = 1.
564    DO ij = 1, iim
565      IF(pente_max * adyqv(ij)<abs(dyq(ij, l))) THEN
566        fn = min(pente_max * adyqv(ij) / abs(dyq(ij, l)), fn)
567      ENDIF
568      IF(pente_max * adyqv(ij + ip1jm - iip1)<abs(dyq(ij + ip1jm, l))) THEN
569        fs = min(pente_max * adyqv(ij + ip1jm - iip1) / abs(dyq(ij + ip1jm, l)), fs)
570      ENDIF
571    ENDDO
572    DO ij = 1, iip1
573      dyq(ij, l) = fn * dyq(ij, l)
574      dyq(ip1jm + ij, l) = fs * dyq(ip1jm + ij, l)
575    ENDDO
576    8888   continue
577    DO ij = 1, iip1
578      dyq(ij, l) = 0.
579      dyq(ip1jm + ij, l) = 0.
580    ENDDO
581
582    !CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
583    !  En memoire de dIFferents tests sur la
584    !  limitation des pentes aux poles.
585    !CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
586    ! PRINT*,dyq(1)
587    ! PRINT*,dyqv(iip1+1)
588    ! appn=abs(dyq(1)/dyqv(iip1+1))
589    ! PRINT*,dyq(ip1jm+1)
590    ! PRINT*,dyqv(ip1jm-iip1+1)
591    ! apps=abs(dyq(ip1jm+1)/dyqv(ip1jm-iip1+1))
592    ! DO ij=2,iim
593    !    appn=amax1(abs(dyq(ij)/dyqv(ij)),appn)
594    !    apps=amax1(abs(dyq(ip1jm+ij)/dyqv(ip1jm-iip1+ij)),apps)
595    ! ENDDO
596    ! appn=min(pente_max/appn,1.)
597    ! apps=min(pente_max/apps,1.)
598
599
600    !   cas ou on a un extremum au pole
601
602    ! IF(dyqv(ismin(iim,dyqv,1))*dyqv(ismax(iim,dyqv,1)).le.0.)
603    !    &   appn=0.
604    ! IF(dyqv(ismax(iim,dyqv(ip1jm-iip1+1),1)+ip1jm-iip1+1)*
605    !    &   dyqv(ismin(iim,dyqv(ip1jm-iip1+1),1)+ip1jm-iip1+1).le.0.)
606    !    &   apps=0.
607
608    !   limitation des pentes aux poles
609    ! DO ij=1,iip1
610    !    dyq(ij)=appn*dyq(ij)
611    !    dyq(ip1jm+ij)=apps*dyq(ip1jm+ij)
612    ! ENDDO
613
614    !   test
615    !  DO ij=1,iip1
616    !     dyq(iip1+ij)=0.
617    !     dyq(ip1jm+ij-iip1)=0.
618    !  ENDDO
619    !  DO ij=1,ip1jmp1
620    !     dyq(ij)=dyq(ij)*cos(rlatu((ij-1)/iip1+1))
621    !  ENDDO
622
623    ! changement 10 07 96
624    ! IF(dyqv(ismin(iim,dyqv,1))*dyqv(ismax(iim,dyqv,1)).le.0.)
625    !    &   THEN
626    !    DO ij=1,iip1
627    !       dyqmax(ij)=0.
628    !    ENDDO
629    ! ELSE
630    !    DO ij=1,iip1
631    !       dyqmax(ij)=pente_max*abs(dyqv(ij))
632    !    ENDDO
633    ! ENDIF
634
635    ! IF(dyqv(ismax(iim,dyqv(ip1jm-iip1+1),1)+ip1jm-iip1+1)*
636    !    & dyqv(ismin(iim,dyqv(ip1jm-iip1+1),1)+ip1jm-iip1+1).le.0.)
637    !    &THEN
638    !    DO ij=ip1jm+1,ip1jmp1
639    !       dyqmax(ij)=0.
640    !    ENDDO
641    ! ELSE
642    !    DO ij=ip1jm+1,ip1jmp1
643    !       dyqmax(ij)=pente_max*abs(dyqv(ij-iip1))
644    !    ENDDO
645    ! ENDIF
646    !   fin changement 10 07 96
647    !CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
648
649    !   calcul des pentes limitees
650
651    DO ij = iip2, ip1jm
652      IF(dyqv(ij) * dyqv(ij - iip1)>0.) THEN
653        dyq(ij, l) = sign(min(abs(dyq(ij, l)), dyqmax(ij)), dyq(ij, l))
654      ELSE
655        dyq(ij, l) = 0.
656      ENDIF
657    ENDDO
658
659  ENDDO
660
661  ! !WRITE(*,*) 'vly 756'
662  DO l = 1, llm
663    DO ij = 1, ip1jm
664      IF(masse_adv_v(ij, l)>0) THEN
665        qbyv(ij, l) = q(ij + iip1, l, iq) + dyq(ij + iip1, l) * &
666                0.5 * (1. - masse_adv_v(ij, l) &
667                / masse(ij + iip1, l, iq))
668      ELSE
669        qbyv(ij, l) = q(ij, l, iq) - dyq(ij, l) * &
670                0.5 * (1. + masse_adv_v(ij, l) &
671                / masse(ij, l, iq))
672      ENDIF
673      qbyv(ij, l) = masse_adv_v(ij, l) * qbyv(ij, l)
674    ENDDO
675  ENDDO
676
677  ! CRisi: appel récursif de l'advection sur les fils.
678  ! Il faut faire ça avant d'avoir mis à jour q et masse
679  ! WRITE(*,*) 'vly 689: iq,nqDesc(iq)=',iq,tracers(iq)%nqDescen
680
681  DO ifils = 1, tracers(iq)%nqDescen
682    iq2 = tracers(iq)%iqDescen(ifils)
683    DO l = 1, llm
684      DO ij = 1, ip1jmp1
685        ! ! attention, chaque fils doit avoir son masseq, sinon, le 1er
686        ! ! fils ecrase le masseq de ses freres.
687        ! !masseq(ij,l,iq2)=masse(ij,l,iq)*q(ij,l,iq)
688        !           !Ratio(ij,l,iq2)=q(ij,l,iq2)/q(ij,l,iq)
689        ! !MVals: veiller a ce qu'on n'ait pas de denominateur nul
690        masseq(ij, l, iq2) = max(masse(ij, l, iq) * q(ij, l, iq), min_qMass)
691        IF (q(ij, l, iq)>min_qParent) THEN
692          Ratio(ij, l, iq2) = q(ij, l, iq2) / q(ij, l, iq)
693        else
694          Ratio(ij, l, iq2) = min_ratio
695        endif
696      enddo
697    enddo
698  enddo
699
700  DO ifils = 1, tracers(iq)%nqDescen
701    iq2 = tracers(iq)%iqDescen(ifils)
702    CALL vly(Ratio, pente_max, masseq, qbyv, iq2)
703  enddo
704
705  DO l = 1, llm
706    DO ij = iip2, ip1jm
707      newmasse = masse(ij, l, iq) &
708              + masse_adv_v(ij, l) - masse_adv_v(ij - iip1, l)
709      q(ij, l, iq) = (q(ij, l, iq) * masse(ij, l, iq) + qbyv(ij, l) &
710              - qbyv(ij - iip1, l)) / newmasse
711      masse(ij, l, iq) = newmasse
712    ENDDO
713    convpn = SSUM(iim, qbyv(1, l), 1)
714    convmpn = ssum(iim, masse_adv_v(1, l), 1)
715    massepn = ssum(iim, masse(1, l, iq), 1)
716    qpn = 0.
717    DO ij = 1, iim
718      qpn = qpn + masse(ij, l, iq) * q(ij, l, iq)
719    enddo
720    qpn = (qpn + convpn) / (massepn + convmpn)
721    DO ij = 1, iip1
722      q(ij, l, iq) = qpn
723    enddo
724    convps = -SSUM(iim, qbyv(ip1jm - iim, l), 1)
725    convmps = -ssum(iim, masse_adv_v(ip1jm - iim, l), 1)
726    masseps = ssum(iim, masse(ip1jm + 1, l, iq), 1)
727    qps = 0.
728    DO ij = ip1jm + 1, ip1jmp1 - 1
729      qps = qps + masse(ij, l, iq) * q(ij, l, iq)
730    enddo
731    qps = (qps + convps) / (masseps + convmps)
732    DO ij = ip1jm + 1, ip1jmp1
733      q(ij, l, iq) = qps
734    enddo
735  ENDDO
736
737  ! retablir les fils en rapport de melange par rapport a l'air:
738  DO ifils = 1, tracers(iq)%nqDescen
739    iq2 = tracers(iq)%iqDescen(ifils)
740    DO l = 1, llm
741      DO ij = 1, ip1jmp1
742        q(ij, l, iq2) = q(ij, l, iq) * Ratio(ij, l, iq2)
743      enddo
744    enddo
745  enddo
746
747  ! !WRITE(*,*) 'vly 853: sortie'
748
749END SUBROUTINE vly
750RECURSIVE SUBROUTINE vlz(q, pente_max, masse, w, iq)
751  USE lmdz_infotrac, ONLY: nqtot, tracers, & ! CRisi
752          min_qParent, min_qMass, min_ratio ! MVals et CRisi
753
754  ! Auteurs:   P.Le Van, F.Hourdin, F.Forget
755
756  !    ********************************************************************
757  ! Shema  d'advection " pseudo amont " .
758  !    ********************************************************************
759  !    q,pbaru,pbarv,w sont des arguments d'entree  pour le s-pg ....
760  ! dq            sont des arguments de sortie pour le s-pg ....
761  !   --------------------------------------------------------------------
762USE lmdz_dimensions, ONLY: iim, jjm, llm, ndm
763  USE lmdz_paramet
764  IMPLICIT NONE
765  !
766
767
768
769
770  !   Arguments:
771  !   ----------
772  REAL :: masse(ip1jmp1, llm, nqtot), pente_max
773  REAL :: q(ip1jmp1, llm, nqtot)
774  REAL :: w(ip1jmp1, llm + 1)
775  INTEGER :: iq
776
777  !  Local
778  !   ---------
779
780  INTEGER :: ij, l
781
782  REAL :: wq(ip1jmp1, llm + 1), newmasse
783
784  REAL :: dzq(ip1jmp1, llm), dzqw(ip1jmp1, llm), adzqw(ip1jmp1, llm), dzqmax
785  REAL :: sigw
786
787  REAL :: masseq(ip1jmp1, llm, nqtot), Ratio(ip1jmp1, llm, nqtot) ! CRisi
788  INTEGER :: ifils, iq2 ! CRisi
789
790#ifdef BIDON
791  REAL :: temps0,temps1,second
792  SAVE temps0,temps1
793
794  DATA temps0,temps1/0.,0./
795#endif
796
797  !    On oriente tout dans le sens de la pression c'est a dire dans le
798  !    sens de W
799  DO l = 2, llm
800    DO ij = 1, ip1jmp1
801      dzqw(ij, l) = q(ij, l - 1, iq) - q(ij, l, iq)
802      adzqw(ij, l) = abs(dzqw(ij, l))
803    ENDDO
804  ENDDO
805
806  DO l = 2, llm - 1
807    DO ij = 1, ip1jmp1
808      IF(dzqw(ij, l) * dzqw(ij, l + 1)>0.) THEN
809        dzq(ij, l) = 0.5 * (dzqw(ij, l) + dzqw(ij, l + 1))
810      ELSE
811        dzq(ij, l) = 0.
812      ENDIF
813      dzqmax = pente_max * min(adzqw(ij, l), adzqw(ij, l + 1))
814      dzq(ij, l) = sign(min(abs(dzq(ij, l)), dzqmax), dzq(ij, l))
815    ENDDO
816  ENDDO
817
818  ! !WRITE(*,*) 'vlz 954'
819  DO ij = 1, ip1jmp1
820    dzq(ij, 1) = 0.
821    dzq(ij, llm) = 0.
822  ENDDO
823
824  ! ---------------------------------------------------------------
825  !   .... calcul des termes d'advection verticale  .......
826  ! ---------------------------------------------------------------
827
828  ! calcul de  - d( q   * w )/ d(sigma)    qu'on ajoute a  dq pour calculer dq
829
830  DO l = 1, llm - 1
831    DO  ij = 1, ip1jmp1
832      IF(w(ij, l + 1)>0.) THEN
833        sigw = w(ij, l + 1) / masse(ij, l + 1, iq)
834        wq(ij, l + 1) = w(ij, l + 1) * (q(ij, l + 1, iq) &
835                + 0.5 * (1. - sigw) * dzq(ij, l + 1))
836      ELSE
837        sigw = w(ij, l + 1) / masse(ij, l, iq)
838        wq(ij, l + 1) = w(ij, l + 1) * (q(ij, l, iq) - 0.5 * (1. + sigw) * dzq(ij, l))
839      ENDIF
840    ENDDO
841  ENDDO
842
843  DO ij = 1, ip1jmp1
844    wq(ij, llm + 1) = 0.
845    wq(ij, 1) = 0.
846  ENDDO
847
848  ! CRisi: appel récursif de l'advection sur les fils.
849  ! Il faut faire ça avant d'avoir mis à jour q et masse
850  ! !WRITE(*,*) 'vlsplt 942: iq,nqChildren(iq)=',iq,nqChildren(iq)
851  DO ifils = 1, tracers(iq)%nqDescen
852    iq2 = tracers(iq)%iqDescen(ifils)
853    DO l = 1, llm
854      DO ij = 1, ip1jmp1
855        ! !masseq(ij,l,iq2)=masse(ij,l,iq)*q(ij,l,iq)
856        !           !Ratio(ij,l,iq2)=q(ij,l,iq2)/q(ij,l,iq)
857        ! !MVals: veiller a ce qu'on n'ait pas de denominateur nul
858        masseq(ij, l, iq2) = max(masse(ij, l, iq) * q(ij, l, iq), min_qMass)
859        IF (q(ij, l, iq)>min_qParent) THEN
860          Ratio(ij, l, iq2) = q(ij, l, iq2) / q(ij, l, iq)
861        else
862          Ratio(ij, l, iq2) = min_ratio
863        endif
864      enddo
865    enddo
866  enddo
867
868  DO ifils = 1, tracers(iq)%nqChildren
869    iq2 = tracers(iq)%iqDescen(ifils)
870    CALL vlz(Ratio, pente_max, masseq, wq, iq2)
871  enddo
872  ! end CRisi
873
874  DO l = 1, llm
875    DO ij = 1, ip1jmp1
876      newmasse = masse(ij, l, iq) + w(ij, l + 1) - w(ij, l)
877      q(ij, l, iq) = (q(ij, l, iq) * masse(ij, l, iq) + wq(ij, l + 1) - wq(ij, l)) &
878              / newmasse
879      masse(ij, l, iq) = newmasse
880    ENDDO
881  ENDDO
882
883  ! retablir les fils en rapport de melange par rapport a l'air:
884  DO ifils = 1, tracers(iq)%nqDescen
885    iq2 = tracers(iq)%iqDescen(ifils)
886    DO l = 1, llm
887      DO ij = 1, ip1jmp1
888        q(ij, l, iq2) = q(ij, l, iq) * Ratio(ij, l, iq2)
889      enddo
890    enddo
891  enddo
892
893END SUBROUTINE vlz
894
895SUBROUTINE minmaxq(zq, qmin, qmax, comment)
896  USE lmdz_dimensions, ONLY: iim, jjm, llm, ndm
897  USE lmdz_paramet
898
899  CHARACTER(LEN = 20) :: comment
900  REAL :: qmin, qmax
901  REAL :: zq(ip1jmp1, llm)
902  REAL :: zzq(iip1, jjp1, llm)
903
904END SUBROUTINE  minmaxq
905
906
907
Note: See TracBrowser for help on using the repository browser.