1 |
SUBROUTINE vlx(q,pente_max,masse,u_m) |
module vlx_m |
2 |
|
|
3 |
! Auteurs: P.Le Van, F.Hourdin, F.Forget |
IMPLICIT NONE |
4 |
! |
|
5 |
! ******************************************************* |
contains |
6 |
! Shema d'advection " pseudo amont " . |
|
7 |
! ************************************************************ |
SUBROUTINE vlx(q, pente_max, masse, u_m) |
8 |
! nq,iq,q,pbaru,pbarv,w sont des arguments d'entree pour le |
|
9 |
! s-pg .... |
! Authors: P. Le Van, F. Hourdin, F. Forget |
10 |
! |
|
11 |
! |
! Sch\'ema d'advection "pseudo-amont". |
12 |
! -------------------------------------------------------------- |
|
13 |
use dimens_m |
use dimens_m, only: iim, llm |
14 |
use paramet_m |
use paramet_m, only: ip1jmp1, iip1, iip2, ip1jm |
15 |
use comconst |
|
16 |
use disvert_m |
REAL, intent(inout):: q(ip1jmp1, llm) |
17 |
use conf_gcm_m |
REAL, intent(in):: pente_max |
18 |
IMPLICIT NONE |
real, intent(inout):: masse(ip1jmp1, llm) |
19 |
! |
REAL, intent(in):: u_m(ip1jmp1, llm) |
20 |
! |
|
21 |
! |
! Local: |
22 |
! Arguments: |
|
23 |
! ---------- |
INTEGER ij, l, j, i, iju, ijq, indu(ip1jmp1), niju |
24 |
REAL masse(ip1jmp1,llm),pente_max |
INTEGER n0, iadvplus(ip1jmp1, llm), nl(llm) |
25 |
REAL u_m( ip1jmp1,llm ),pbarv( iip1,jjm,llm) |
REAL new_m, zu_m, zdum(ip1jmp1, llm) |
26 |
REAL q(ip1jmp1,llm) |
REAL dxq(ip1jmp1, llm), dxqu(iip2:ip1jm) |
27 |
REAL w(ip1jmp1,llm) |
REAL zz(ip1jmp1) |
28 |
! |
REAL adxqu(iip2:ip1jm), dxqmax(ip1jmp1, llm) |
29 |
! Local |
REAL u_mq(ip1jmp1, llm) |
30 |
! --------- |
|
31 |
! |
!----------------------------------------------------- |
32 |
INTEGER ij,l,j,i,iju,ijq,indu(ip1jmp1),niju |
|
33 |
INTEGER n0,iadvplus(ip1jmp1,llm),nl(llm) |
! calcul de la pente a droite et a gauche de la maille |
34 |
! |
|
35 |
REAL new_m,zu_m,zdum(ip1jmp1,llm) |
IF (pente_max > - 1e-5) THEN |
36 |
REAL sigu(ip1jmp1),dxq(ip1jmp1,llm),dxqu(ip1jmp1) |
! calcul des pentes avec limitation, Van Leer scheme I: |
37 |
REAL zz(ip1jmp1) |
|
38 |
REAL adxqu(ip1jmp1),dxqmax(ip1jmp1,llm) |
! calcul de la pente aux points u |
39 |
REAL u_mq(ip1jmp1,llm) |
DO l = 1, llm |
40 |
|
DO ij = iip2, ip1jm - 1 |
41 |
Logical extremum,first,testcpu |
dxqu(ij) = q(ij + 1, l) - q(ij, l) |
42 |
SAVE first,testcpu |
ENDDO |
43 |
|
DO ij = iip1 + iip1, ip1jm, iip1 |
44 |
REAL SSUM |
dxqu(ij) = dxqu(ij - iim) |
45 |
REAL temps0,temps1,temps2,temps3,temps4,temps5,second |
ENDDO |
46 |
SAVE temps0,temps1,temps2,temps3,temps4,temps5 |
|
47 |
|
DO ij = iip2, ip1jm |
48 |
REAL z1,z2,z3 |
adxqu(ij) = abs(dxqu(ij)) |
49 |
|
ENDDO |
50 |
DATA first,testcpu/.true.,.false./ |
|
51 |
|
! calcul de la pente maximum dans la maille en valeur absolue |
52 |
IF(first) THEN |
|
53 |
temps1=0. |
DO ij = iip2 + 1, ip1jm |
54 |
temps2=0. |
dxqmax(ij, l) = pente_max * min(adxqu(ij - 1), adxqu(ij)) |
55 |
temps3=0. |
ENDDO |
56 |
temps4=0. |
|
57 |
temps5=0. |
DO ij = iip1 + iip1, ip1jm, iip1 |
58 |
first=.false. |
dxqmax(ij - iim, l) = dxqmax(ij, l) |
59 |
ENDIF |
ENDDO |
60 |
|
|
61 |
! calcul de la pente a droite et a gauche de la maille |
DO ij = iip2 + 1, ip1jm |
62 |
|
IF (dxqu(ij - 1) * dxqu(ij) > 0.) THEN |
63 |
|
dxq(ij, l) = dxqu(ij - 1) + dxqu(ij) |
64 |
IF (pente_max.gt.-1.e-5) THEN |
ELSE |
65 |
! IF (pente_max.gt.10) THEN |
! extremum local |
66 |
|
dxq(ij, l) = 0. |
67 |
! calcul des pentes avec limitation, Van Leer scheme I: |
ENDIF |
68 |
! ----------------------------------------------------- |
dxq(ij, l) = 0.5 * dxq(ij, l) |
69 |
|
dxq(ij, l) = sign(min(abs(dxq(ij, l)), dxqmax(ij, l)), dxq(ij, l)) |
70 |
! calcul de la pente aux points u |
ENDDO |
71 |
DO l = 1, llm |
ENDDO |
72 |
DO ij=iip2,ip1jm-1 |
ELSE |
73 |
dxqu(ij)=q(ij+1,l)-q(ij,l) |
! Pentes produits: |
74 |
! IF(u_m(ij,l).lt.0.) stop'limx n admet pas les U<0' |
|
75 |
! sigu(ij)=u_m(ij,l)/masse(ij,l) |
DO l = 1, llm |
76 |
ENDDO |
DO ij = iip2, ip1jm - 1 |
77 |
DO ij=iip1+iip1,ip1jm,iip1 |
dxqu(ij) = q(ij + 1, l) - q(ij, l) |
78 |
dxqu(ij)=dxqu(ij-iim) |
ENDDO |
79 |
! sigu(ij)=sigu(ij-iim) |
DO ij = iip1 + iip1, ip1jm, iip1 |
80 |
ENDDO |
dxqu(ij) = dxqu(ij - iim) |
81 |
|
ENDDO |
82 |
DO ij=iip2,ip1jm |
|
83 |
adxqu(ij)=abs(dxqu(ij)) |
DO ij = iip2 + 1, ip1jm |
84 |
ENDDO |
zz(ij) = dxqu(ij - 1) * dxqu(ij) |
85 |
|
zz(ij) = zz(ij) + zz(ij) |
86 |
! calcul de la pente maximum dans la maille en valeur absolue |
IF (zz(ij) > 0) THEN |
87 |
|
dxq(ij, l) = zz(ij) / (dxqu(ij - 1) + dxqu(ij)) |
88 |
DO ij=iip2+1,ip1jm |
ELSE |
89 |
dxqmax(ij,l)=pente_max* & |
! extremum local |
90 |
& min(adxqu(ij-1),adxqu(ij)) |
dxq(ij, l) = 0. |
91 |
! limitation subtile |
ENDIF |
92 |
! , min(adxqu(ij-1)/sigu(ij-1),adxqu(ij)/(1.-sigu(ij))) |
ENDDO |
93 |
|
ENDDO |
94 |
|
ENDIF |
95 |
ENDDO |
|
96 |
|
! bouclage de la pente en iip1: |
97 |
DO ij=iip1+iip1,ip1jm,iip1 |
|
98 |
dxqmax(ij-iim,l)=dxqmax(ij,l) |
DO l = 1, llm |
99 |
ENDDO |
DO ij = iip1 + iip1, ip1jm, iip1 |
100 |
|
dxq(ij - iim, l) = dxq(ij, l) |
101 |
DO ij=iip2+1,ip1jm |
ENDDO |
102 |
IF(dxqu(ij-1)*dxqu(ij).gt.0) THEN |
DO ij = 1, ip1jmp1 |
103 |
dxq(ij,l)=dxqu(ij-1)+dxqu(ij) |
iadvplus(ij, l) = 0 |
104 |
ELSE |
ENDDO |
105 |
! extremum local |
ENDDO |
106 |
dxq(ij,l)=0. |
|
107 |
ENDIF |
! calcul des flux a gauche et a droite |
108 |
dxq(ij,l)=0.5*dxq(ij,l) |
|
109 |
dxq(ij,l)= & |
! on cumule le flux correspondant a toutes les mailles dont la masse |
110 |
& sign(min(abs(dxq(ij,l)),dxqmax(ij,l)),dxq(ij,l)) |
! au travers de la paroi pENDant le pas de temps. |
111 |
ENDDO |
|
112 |
|
DO l = 1, llm |
113 |
! l=1,llm |
DO ij = iip2, ip1jm - 1 |
114 |
ENDDO |
IF (u_m(ij, l) > 0.) THEN |
115 |
! (pente_max.lt.-1.e-5) |
zdum(ij, l) = 1. - u_m(ij, l) / masse(ij, l) |
116 |
ELSE |
u_mq(ij, l) = u_m(ij, l) & |
117 |
|
* (q(ij, l) + 0.5 * zdum(ij, l) * dxq(ij, l)) |
|
! Pentes produits: |
|
|
! ---------------- |
|
|
|
|
|
DO l = 1, llm |
|
|
DO ij=iip2,ip1jm-1 |
|
|
dxqu(ij)=q(ij+1,l)-q(ij,l) |
|
|
ENDDO |
|
|
DO ij=iip1+iip1,ip1jm,iip1 |
|
|
dxqu(ij)=dxqu(ij-iim) |
|
|
ENDDO |
|
|
|
|
|
DO ij=iip2+1,ip1jm |
|
|
zz(ij)=dxqu(ij-1)*dxqu(ij) |
|
|
zz(ij)=zz(ij)+zz(ij) |
|
|
IF(zz(ij).gt.0) THEN |
|
|
dxq(ij,l)=zz(ij)/(dxqu(ij-1)+dxqu(ij)) |
|
|
ELSE |
|
|
! extremum local |
|
|
dxq(ij,l)=0. |
|
|
ENDIF |
|
|
ENDDO |
|
|
|
|
|
ENDDO |
|
|
|
|
|
! (pente_max.lt.-1.e-5) |
|
|
ENDIF |
|
|
|
|
|
! bouclage de la pente en iip1: |
|
|
! ----------------------------- |
|
|
|
|
|
DO l=1,llm |
|
|
DO ij=iip1+iip1,ip1jm,iip1 |
|
|
dxq(ij-iim,l)=dxq(ij,l) |
|
|
ENDDO |
|
|
DO ij=1,ip1jmp1 |
|
|
iadvplus(ij,l)=0 |
|
|
ENDDO |
|
|
|
|
|
ENDDO |
|
|
|
|
|
! calcul des flux a gauche et a droite |
|
|
|
|
|
! on cumule le flux correspondant a toutes les mailles dont la masse |
|
|
! au travers de la paroi pENDant le pas de temps. |
|
|
!print*,'Cumule ....' |
|
|
|
|
|
DO l=1,llm |
|
|
DO ij=iip2,ip1jm-1 |
|
|
! print*,'masse(',ij,')=',masse(ij,l) |
|
|
IF (u_m(ij,l).gt.0.) THEN |
|
|
zdum(ij,l)=1.-u_m(ij,l)/masse(ij,l) |
|
|
u_mq(ij,l)=u_m(ij,l)*(q(ij,l)+0.5*zdum(ij,l)*dxq(ij,l)) |
|
118 |
ELSE |
ELSE |
119 |
zdum(ij,l)=1.+u_m(ij,l)/masse(ij+1,l) |
zdum(ij, l) = 1. + u_m(ij, l) / masse(ij + 1, l) |
120 |
u_mq(ij,l)=u_m(ij,l) & |
u_mq(ij, l) = u_m(ij, l) & |
121 |
& *(q(ij+1,l)-0.5*zdum(ij,l)*dxq(ij+1,l)) |
* (q(ij + 1, l) - 0.5 * zdum(ij, l) * dxq(ij + 1, l)) |
122 |
|
ENDIF |
123 |
|
ENDDO |
124 |
|
ENDDO |
125 |
|
|
126 |
|
! detection des points ou on advecte plus que la masse de la |
127 |
|
! maille |
128 |
|
DO l = 1, llm |
129 |
|
DO ij = iip2, ip1jm - 1 |
130 |
|
IF (zdum(ij, l) < 0) THEN |
131 |
|
iadvplus(ij, l) = 1 |
132 |
|
u_mq(ij, l) = 0. |
133 |
|
ENDIF |
134 |
|
ENDDO |
135 |
|
ENDDO |
136 |
|
|
137 |
|
DO l = 1, llm |
138 |
|
DO ij = iip1 + iip1, ip1jm, iip1 |
139 |
|
iadvplus(ij, l) = iadvplus(ij - iim, l) |
140 |
|
ENDDO |
141 |
|
ENDDO |
142 |
|
|
143 |
|
! traitement special pour le cas ou on advecte en longitude plus |
144 |
|
! que le contenu de la maille. cette partie est mal vectorisee. |
145 |
|
|
146 |
|
! calcul du nombre de maille sur lequel on advecte plus que la maille. |
147 |
|
|
148 |
|
n0 = 0 |
149 |
|
DO l = 1, llm |
150 |
|
nl(l) = 0 |
151 |
|
DO ij = iip2, ip1jm |
152 |
|
nl(l) = nl(l) + iadvplus(ij, l) |
153 |
|
ENDDO |
154 |
|
n0 = n0 + nl(l) |
155 |
|
ENDDO |
156 |
|
|
157 |
|
IF (n0 > 0) THEN |
158 |
|
DO l = 1, llm |
159 |
|
IF (nl(l) > 0) THEN |
160 |
|
iju = 0 |
161 |
|
! indicage des mailles concernees par le traitement special |
162 |
|
DO ij = iip2, ip1jm |
163 |
|
IF (iadvplus(ij, l) == 1.and.mod(ij, iip1) /= 0) THEN |
164 |
|
iju = iju + 1 |
165 |
|
indu(iju) = ij |
166 |
|
ENDIF |
167 |
|
ENDDO |
168 |
|
niju = iju |
169 |
|
|
170 |
|
! traitement des mailles |
171 |
|
DO iju = 1, niju |
172 |
|
ij = indu(iju) |
173 |
|
j = (ij - 1) / iip1 + 1 |
174 |
|
zu_m = u_m(ij, l) |
175 |
|
u_mq(ij, l) = 0. |
176 |
|
IF (zu_m > 0.) THEN |
177 |
|
ijq = ij |
178 |
|
i = ijq - (j - 1) * iip1 |
179 |
|
! accumulation pour les mailles completements advectees |
180 |
|
do while(zu_m > masse(ijq, l)) |
181 |
|
u_mq(ij, l) = u_mq(ij, l) + q(ijq, l) * masse(ijq, l) |
182 |
|
zu_m = zu_m - masse(ijq, l) |
183 |
|
i = mod(i - 2 + iim, iim) + 1 |
184 |
|
ijq = (j - 1) * iip1 + i |
185 |
|
ENDDO |
186 |
|
! ajout de la maille non completement advectee |
187 |
|
u_mq(ij, l) = u_mq(ij, l) + zu_m * (q(ijq, l) + 0.5 * (1. & |
188 |
|
- zu_m / masse(ijq, l)) * dxq(ijq, l)) |
189 |
|
ELSE |
190 |
|
ijq = ij + 1 |
191 |
|
i = ijq - (j - 1) * iip1 |
192 |
|
! accumulation pour les mailles completements advectees |
193 |
|
do while(- zu_m > masse(ijq, l)) |
194 |
|
u_mq(ij, l) = u_mq(ij, l) - q(ijq, l) * masse(ijq, l) |
195 |
|
zu_m = zu_m + masse(ijq, l) |
196 |
|
i = mod(i, iim) + 1 |
197 |
|
ijq = (j - 1) * iip1 + i |
198 |
|
ENDDO |
199 |
|
! ajout de la maille non completement advectee |
200 |
|
u_mq(ij, l) = u_mq(ij, l) + zu_m * (q(ijq, l) - 0.5 * (1. & |
201 |
|
+ zu_m / masse(ijq, l)) * dxq(ijq, l)) |
202 |
|
ENDIF |
203 |
|
ENDDO |
204 |
ENDIF |
ENDIF |
205 |
ENDDO |
ENDDO |
206 |
ENDDO |
ENDIF |
|
! stop |
|
207 |
|
|
208 |
! go to 9999 |
! bouclage en latitude |
209 |
! detection des points ou on advecte plus que la masse de la |
DO l = 1, llm |
210 |
! maille |
DO ij = iip1 + iip1, ip1jm, iip1 |
211 |
DO l=1,llm |
u_mq(ij, l) = u_mq(ij - iim, l) |
212 |
DO ij=iip2,ip1jm-1 |
ENDDO |
213 |
IF(zdum(ij,l).lt.0) THEN |
ENDDO |
214 |
iadvplus(ij,l)=1 |
|
215 |
u_mq(ij,l)=0. |
! calcul des tENDances |
216 |
ENDIF |
|
217 |
ENDDO |
DO l = 1, llm |
218 |
ENDDO |
DO ij = iip2 + 1, ip1jm |
219 |
!print*,'Ok test 1' |
new_m = masse(ij, l) + u_m(ij - 1, l) - u_m(ij, l) |
220 |
DO l=1,llm |
q(ij, l) = (q(ij, l) * masse(ij, l) + u_mq(ij - 1, l) & |
221 |
DO ij=iip1+iip1,ip1jm,iip1 |
- u_mq(ij, l)) / new_m |
222 |
iadvplus(ij,l)=iadvplus(ij-iim,l) |
masse(ij, l) = new_m |
223 |
ENDDO |
ENDDO |
224 |
ENDDO |
|
225 |
! print*,'Ok test 2' |
DO ij = iip1 + iip1, ip1jm, iip1 |
226 |
|
q(ij - iim, l) = q(ij, l) |
227 |
|
masse(ij - iim, l) = masse(ij, l) |
228 |
! traitement special pour le cas ou on advecte en longitude plus |
ENDDO |
229 |
! que le |
ENDDO |
|
! contenu de la maille. |
|
|
! cette partie est mal vectorisee. |
|
|
|
|
|
! calcul du nombre de maille sur lequel on advecte plus que la maille. |
|
|
|
|
|
n0=0 |
|
|
DO l=1,llm |
|
|
nl(l)=0 |
|
|
DO ij=iip2,ip1jm |
|
|
nl(l)=nl(l)+iadvplus(ij,l) |
|
|
ENDDO |
|
|
n0=n0+nl(l) |
|
|
ENDDO |
|
|
|
|
|
IF(n0.gt.0) THEN |
|
|
!C PRINT*,'Nombre de points pour lesquels on advect plus que le' |
|
|
!C & ,'contenu de la maille : ',n0 |
|
|
|
|
|
DO l=1,llm |
|
|
IF(nl(l).gt.0) THEN |
|
|
iju=0 |
|
|
! indicage des mailles concernees par le traitement special |
|
|
DO ij=iip2,ip1jm |
|
|
IF(iadvplus(ij,l).eq.1.and.mod(ij,iip1).ne.0) THEN |
|
|
iju=iju+1 |
|
|
indu(iju)=ij |
|
|
ENDIF |
|
|
ENDDO |
|
|
niju=iju |
|
|
! PRINT*,'niju,nl',niju,nl(l) |
|
|
|
|
|
! traitement des mailles |
|
|
DO iju=1,niju |
|
|
ij=indu(iju) |
|
|
j=(ij-1)/iip1+1 |
|
|
zu_m=u_m(ij,l) |
|
|
u_mq(ij,l)=0. |
|
|
IF(zu_m.gt.0.) THEN |
|
|
ijq=ij |
|
|
i=ijq-(j-1)*iip1 |
|
|
! accumulation pour les mailles completements advectees |
|
|
do while(zu_m.gt.masse(ijq,l)) |
|
|
u_mq(ij,l)=u_mq(ij,l)+q(ijq,l)*masse(ijq,l) |
|
|
zu_m=zu_m-masse(ijq,l) |
|
|
i=mod(i-2+iim,iim)+1 |
|
|
ijq=(j-1)*iip1+i |
|
|
ENDDO |
|
|
! ajout de la maille non completement advectee |
|
|
u_mq(ij,l)=u_mq(ij,l)+zu_m* & |
|
|
& (q(ijq,l)+0.5*(1.-zu_m/masse(ijq,l))*dxq(ijq,l)) |
|
|
ELSE |
|
|
ijq=ij+1 |
|
|
i=ijq-(j-1)*iip1 |
|
|
! accumulation pour les mailles completements advectees |
|
|
do while(-zu_m.gt.masse(ijq,l)) |
|
|
u_mq(ij,l)=u_mq(ij,l)-q(ijq,l)*masse(ijq,l) |
|
|
zu_m=zu_m+masse(ijq,l) |
|
|
i=mod(i,iim)+1 |
|
|
ijq=(j-1)*iip1+i |
|
|
ENDDO |
|
|
! ajout de la maille non completement advectee |
|
|
u_mq(ij,l)=u_mq(ij,l)+zu_m*(q(ijq,l)- & |
|
|
& 0.5*(1.+zu_m/masse(ijq,l))*dxq(ijq,l)) |
|
|
ENDIF |
|
|
ENDDO |
|
|
ENDIF |
|
|
ENDDO |
|
|
! n0.gt.0 |
|
|
ENDIF |
|
|
9999 continue |
|
|
|
|
|
|
|
|
! bouclage en latitude |
|
|
!print*,'cvant bouclage en latitude' |
|
|
DO l=1,llm |
|
|
DO ij=iip1+iip1,ip1jm,iip1 |
|
|
u_mq(ij,l)=u_mq(ij-iim,l) |
|
|
ENDDO |
|
|
ENDDO |
|
|
|
|
|
|
|
|
! calcul des tENDances |
|
|
|
|
|
DO l=1,llm |
|
|
DO ij=iip2+1,ip1jm |
|
|
new_m=masse(ij,l)+u_m(ij-1,l)-u_m(ij,l) |
|
|
q(ij,l)=(q(ij,l)*masse(ij,l)+ & |
|
|
& u_mq(ij-1,l)-u_mq(ij,l)) & |
|
|
& /new_m |
|
|
masse(ij,l)=new_m |
|
|
ENDDO |
|
|
! ModIF Fred 22 03 96 correction d'un bug (les scopy ci-dessous) |
|
|
DO ij=iip1+iip1,ip1jm,iip1 |
|
|
q(ij-iim,l)=q(ij,l) |
|
|
masse(ij-iim,l)=masse(ij,l) |
|
|
ENDDO |
|
|
ENDDO |
|
230 |
|
|
231 |
|
END SUBROUTINE vlx |
232 |
|
|
233 |
RETURN |
end module vlx_m |
|
END |
|