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

Last change on this file since 145 was 145, checked in by ymipsl, 11 years ago

Add vampirtrace management

YM

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