source: LMDZ6/trunk/libf/dyn3d/vlsplt.F90 @ 5299

Last change on this file since 5299 was 5285, checked in by abarral, 6 weeks ago

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