source: codes/icosagcm/trunk/src/advect_tracer.f90 @ 141

Last change on this file since 141 was 138, checked in by dubos, 11 years ago

Transport now working again - tested with dcmip4.1.0

File size: 8.2 KB
Line 
1MODULE advect_tracer_mod
2  USE icosa
3  IMPLICIT NONE
4  PRIVATE
5
6  TYPE(t_field),POINTER :: f_normal(:)
7  TYPE(t_field),POINTER :: f_tangent(:)
8  TYPE(t_field),POINTER :: f_gradq3d(:)
9  TYPE(t_field),POINTER :: f_cc(:)  ! starting point of backward-trajectory (Miura approach)
10
11  REAL(rstd), PARAMETER :: pente_max=2.0 ! for vlz
12
13  PUBLIC init_advect_tracer, advect_tracer
14
15CONTAINS
16
17  SUBROUTINE init_advect_tracer
18    USE advect_mod
19    REAL(rstd),POINTER :: tangent(:,:)
20    REAL(rstd),POINTER :: normal(:,:)
21    INTEGER :: ind
22
23    CALL allocate_field(f_normal,field_u,type_real,3, name='normal')
24    CALL allocate_field(f_tangent,field_u,type_real,3, name='tangent')
25    CALL allocate_field(f_gradq3d,field_t,type_real,llm,3, name='gradq3d')
26    CALL allocate_field(f_cc,field_u,type_real,llm,3, name='cc')
27
28    DO ind=1,ndomain
29       CALL swap_dimensions(ind)
30       CALL swap_geometry(ind)
31       normal=f_normal(ind)
32       tangent=f_tangent(ind)
33       CALL init_advect(normal,tangent)
34    END DO
35
36  END SUBROUTINE init_advect_tracer
37
38  SUBROUTINE advect_tracer(f_hfluxt, f_wfluxt,f_u, f_q,f_rhodz)
39    USE advect_mod
40    USE mpipara
41    IMPLICIT NONE
42
43    TYPE(t_field),POINTER :: f_hfluxt(:)   ! time-integrated horizontal mass flux
44    TYPE(t_field),POINTER :: f_wfluxt(:)   ! time-integrated vertical mass flux
45    TYPE(t_field),POINTER :: f_u(:)        ! velocity (for back-trajectories)
46    TYPE(t_field),POINTER :: f_q(:)        ! tracer
47    TYPE(t_field),POINTER :: f_rhodz(:)    ! mass field at beginning of macro time step
48
49    REAL(rstd),POINTER :: q(:,:,:), normal(:,:), tangent(:,:), gradq3d(:,:,:), cc(:,:,:)
50    REAL(rstd),POINTER :: hfluxt(:,:), wfluxt(:,:)
51    REAL(rstd),POINTER :: rhodz(:,:), u(:,:) 
52    INTEGER :: ind,k
53
54    CALL transfert_request(f_u,req_e1)
55!    CALL transfert_request(f_hfluxt,req_e1)  ! BUG : This (unnecessary) transfer makes the computation go wrong
56    CALL transfert_request(f_wfluxt,req_i1)
57    CALL transfert_request(f_q,req_i1)
58    CALL transfert_request(f_rhodz,req_i1)
59       
60    IF (is_mpi_root) PRINT *, 'Advection scheme'
61
62!    DO ind=1,ndomain
63!       CALL swap_dimensions(ind)
64!       CALL swap_geometry(ind)
65!       normal  = f_normal(ind)
66!       tangent = f_tangent(ind)
67!       cc      = f_cc(ind)
68!       u       = f_u(ind)
69!       q       = f_q(ind)
70!       rhodz   = f_rhodz(ind)
71!       hfluxt  = f_hfluxt(ind)
72!       wfluxt  = f_wfluxt(ind)
73!       gradq3d = f_gradq3d(ind)
74!
75!       ! 1/2 vertical transport
76!       DO k = 1, nqtot
77!          CALL vlz(k==nqtot,0.5, wfluxt,rhodz,q(:,:,k))
78!       END DO
79!
80!       ! horizontal transport
81!       CALL compute_backward_traj(tangent,normal,u,0.5*dt*itau_adv, cc)
82!       DO k = 1,nqtot
83!          CALL compute_gradq3d(q(:,:,k),gradq3d)
84!          CALL compute_advect_horiz(k==nqtot,hfluxt,cc,gradq3d, rhodz,q(:,:,k))
85!       END DO
86!
87!       ! 1/2 vertical transport
88!       DO k = 1,nqtot
89!          CALL vlz(k==nqtot, 0.5,wfluxt,rhodz, q(:,:,k))
90!       END DO
91!    END DO
92
93    ! 1/2 vertical transport + back-trajectories
94    DO ind=1,ndomain
95       CALL swap_dimensions(ind)
96       CALL swap_geometry(ind)
97       normal  = f_normal(ind)
98       tangent = f_tangent(ind)
99       cc      = f_cc(ind)
100       u       = f_u(ind)
101       q       = f_q(ind)
102       rhodz   = f_rhodz(ind)
103       wfluxt  = f_wfluxt(ind) 
104       DO k = 1, nqtot
105          CALL vlz(k==nqtot,0.5, wfluxt,rhodz,q(:,:,k))
106       END DO
107       CALL compute_backward_traj(tangent,normal,u,0.5*dt*itau_adv, cc) 
108    END DO
109
110    CALL transfert_request(f_q,req_i1)      ! necessary ?
111    CALL transfert_request(f_rhodz,req_i1)  ! necessary ?
112
113    ! horizontal transport - split in two to place transfer of gradq3d
114
115    DO k = 1, nqtot
116       DO ind=1,ndomain
117          CALL swap_dimensions(ind)
118          CALL swap_geometry(ind)
119          q       = f_q(ind)
120          gradq3d = f_gradq3d(ind)
121          CALL compute_gradq3d(q(:,:,k),gradq3d)
122       END DO
123
124       CALL transfert_request(f_gradq3d,req_i1)
125
126       DO ind=1,ndomain
127          CALL swap_dimensions(ind)
128          CALL swap_geometry(ind)
129          cc      = f_cc(ind)
130          q       = f_q(ind)
131          rhodz   = f_rhodz(ind)
132          hfluxt  = f_hfluxt(ind) 
133          gradq3d = f_gradq3d(ind)
134          CALL compute_advect_horiz(k==nqtot,hfluxt,cc,gradq3d, rhodz,q(:,:,k))
135       END DO
136    END DO
137
138    CALL transfert_request(f_q,req_i1)      ! necessary ?
139    CALL transfert_request(f_rhodz,req_i1)  ! necessary ?
140
141    ! 1/2 vertical transport
142    DO ind=1,ndomain
143       CALL swap_dimensions(ind)
144       CALL swap_geometry(ind)
145       q       = f_q(ind)
146       rhodz   = f_rhodz(ind)
147       wfluxt  = f_wfluxt(ind) 
148       DO k = 1,nqtot
149          CALL vlz(k==nqtot, 0.5,wfluxt,rhodz, q(:,:,k))
150       END DO
151    END DO
152
153  END SUBROUTINE advect_tracer
154
155  SUBROUTINE vlz(update_mass, fac,wfluxt,mass, q)
156    !
157    !     Auteurs:   P.Le Van, F.Hourdin, F.Forget, T. Dubos
158    !
159    !    ********************************************************************
160    !     Update tracers using vertical mass flux only
161    !     Van Leer scheme with minmod limiter
162    !     wfluxt >0 for upward transport
163    !    ********************************************************************
164    IMPLICIT NONE
165    LOGICAL, INTENT(IN)       :: update_mass
166    REAL(rstd), INTENT(IN)    :: fac, wfluxt(iim*jjm,llm+1) ! vertical mass flux
167    REAL(rstd), INTENT(INOUT) :: mass(iim*jjm,llm)
168    REAL(rstd), INTENT(INOUT) :: q(iim*jjm,llm)
169
170    REAL(rstd) :: dq(iim*jjm,llm), & ! increase of q
171         dzqw(iim*jjm,llm),        & ! vertical finite difference of q
172         adzqw(iim*jjm,llm),       & ! abs(dzqw)
173         dzq(iim*jjm,llm),         & ! limited slope of q
174         wq(iim*jjm,llm+1)           ! time-integrated flux of q
175    REAL(rstd) :: dzqmax, newmass, sigw, qq, w
176    INTEGER :: i,ij,l,j
177
178    ! finite difference of q
179    DO l=2,llm
180       DO j=jj_begin-1,jj_end+1
181          DO i=ii_begin-1,ii_end+1
182             ij=(j-1)*iim+i
183             dzqw(ij,l)=q(ij,l)-q(ij,l-1)
184             adzqw(ij,l)=abs(dzqw(ij,l))
185          ENDDO
186       ENDDO
187    ENDDO
188
189    ! minmod-limited slope of q
190    ! dzq = slope*dz, i.e. the reconstructed q varies by dzq inside level l
191    DO l=2,llm-1
192       DO j=jj_begin-1,jj_end+1
193          DO i=ii_begin-1,ii_end+1
194             ij=(j-1)*iim+i
195             IF(dzqw(ij,l)*dzqw(ij,l+1).gt.0.) THEN
196                dzq(ij,l) = 0.5*( dzqw(ij,l)+dzqw(ij,l+1) )
197                dzqmax    = pente_max * min( adzqw(ij,l),adzqw(ij,l+1) )
198                dzq(ij,l) = sign( min(abs(dzq(ij,l)),dzqmax) , dzq(ij,l) )  ! NB : sign(a,b)=a*sign(b)
199             ELSE
200                dzq(ij,l)=0.
201             ENDIF
202          ENDDO
203       ENDDO
204    ENDDO
205
206    ! 0 slope in top and bottom layers
207    DO j=jj_begin-1,jj_end+1
208       DO i=ii_begin-1,ii_end+1
209          ij=(j-1)*iim+i
210          dzq(ij,1)=0.
211          dzq(ij,llm)=0.
212       ENDDO
213    ENDDO
214
215    ! sigw = fraction of mass that leaves level l/l+1
216    ! then amount of q leaving level l/l+1 = wq = w * qq
217    DO l = 1,llm-1
218       DO j=jj_begin-1,jj_end+1
219          DO i=ii_begin-1,ii_end+1
220             ij=(j-1)*iim+i
221             w = fac*wfluxt(ij,l+1)
222             IF(w>0.) THEN  ! upward transport, upwind side is at level l
223                sigw       = w/mass(ij,l)
224                qq         = q(ij,l)+0.5*(1.-sigw)*dzq(ij,l) ! qq = q if sigw=1 , qq = q+dzq/2 if sigw=0
225             ELSE           ! downward transport, upwind side is at level l+1
226                sigw       = w/mass(ij,l+1)
227                qq         = q(ij,l+1)-0.5*(1.+sigw)*dzq(ij,l+1) ! qq = q if sigw=-1 , qq = q-dzq/2 if sigw=0               
228             ENDIF
229             wq(ij,l+1) = w*qq
230          ENDDO
231       ENDDO
232    END DO
233    ! wq = 0 at top and bottom
234    DO j=jj_begin-1,jj_end+1
235       DO i=ii_begin-1,ii_end+1
236          ij=(j-1)*iim+i
237          wq(ij,llm+1)=0.
238          wq(ij,1)=0.
239       ENDDO
240    END DO
241
242    ! update q, mass is updated only after all q's have been updated
243    DO l=1,llm
244       DO j=jj_begin-1,jj_end+1
245          DO i=ii_begin-1,ii_end+1
246             ij=(j-1)*iim+i
247             newmass = mass(ij,l) + fac*(wfluxt(ij,l)-wfluxt(ij,l+1))
248             q(ij,l) = ( q(ij,l)*mass(ij,l) + wq(ij,l)-wq(ij,l+1) ) / newmass
249             IF(update_mass) mass(ij,l)=newmass
250          ENDDO
251       ENDDO
252    END DO
253
254  END SUBROUTINE vlz
255
256END MODULE advect_tracer_mod
Note: See TracBrowser for help on using the repository browser.