source: codes/icosagcm/trunk/src/caldyn_adv.f90 @ 352

Last change on this file since 352 was 343, checked in by dubos, 9 years ago

Fix output for pure transport

File size: 5.7 KB
Line 
1MODULE caldyn_adv_mod
2  USE icosa
3  IMPLICIT NONE
4  PRIVATE
5  PUBLIC :: init_caldyn, caldyn
6
7CONTAINS
8
9  SUBROUTINE init_caldyn
10  END SUBROUTINE init_caldyn
11
12  SUBROUTINE check_mass_conservation(f_ps,f_dps)
13    USE icosa
14    TYPE(t_field),POINTER :: f_ps(:)
15    TYPE(t_field),POINTER :: f_dps(:)
16    REAL(rstd),POINTER :: ps(:)
17    REAL(rstd),POINTER :: dps(:)
18    REAL(rstd) :: mass_tot,dmass_tot
19    INTEGER :: ind,i,j,ij
20
21    mass_tot=0
22    dmass_tot=0
23
24    CALL transfert_request(f_dps,req_i1)
25    CALL transfert_request(f_ps,req_i1)
26
27    DO ind=1,ndomain
28       IF (.NOT. assigned_domain(ind)) CYCLE
29       CALL swap_dimensions(ind)
30       CALL swap_geometry(ind)
31
32       ps=f_ps(ind)
33       dps=f_dps(ind)
34
35       DO j=jj_begin,jj_end
36          DO i=ii_begin,ii_end
37             ij=(j-1)*iim+i
38             IF (domain(ind)%own(i,j)) THEN
39                mass_tot=mass_tot+ps(ij)*Ai(ij)/g
40                dmass_tot=dmass_tot+dps(ij)*Ai(ij)/g
41             ENDIF
42          ENDDO
43       ENDDO
44
45    ENDDO
46    PRINT*, "mass_tot ", mass_tot,"      dmass_tot ",dmass_tot       
47
48  END SUBROUTINE check_mass_conservation
49
50
51  SUBROUTINE caldyn(write_out,f_phis, f_ps, f_theta_rhodz, f_u, f_q, &
52       f_hflux, f_wflux, f_dps, f_dtheta_rhodz, f_du)
53    USE icosa
54    USE output_field_mod
55    USE vorticity_mod
56    USE kinetic_mod
57    USE theta2theta_rhodz_mod
58    IMPLICIT NONE
59    LOGICAL,INTENT(IN)    :: write_out
60    TYPE(t_field),POINTER :: f_phis(:)
61    TYPE(t_field),POINTER :: f_ps(:)
62    TYPE(t_field),POINTER :: f_theta_rhodz(:)
63    TYPE(t_field),POINTER :: f_u(:)
64    TYPE(t_field),POINTER :: f_q(:)
65    TYPE(t_field),POINTER :: f_hflux(:), f_wflux(:)
66    TYPE(t_field),POINTER :: f_dps(:)
67    TYPE(t_field),POINTER :: f_dtheta_rhodz(:)
68    TYPE(t_field),POINTER :: f_du(:)
69
70    REAL(rstd),POINTER :: ps(:)
71    REAL(rstd),POINTER :: u(:,:)
72    REAL(rstd),POINTER :: dps(:)
73    REAL(rstd),POINTER :: hflux(:,:), wflux(:,:)
74    REAL(rstd),POINTER :: dtheta_rhodz(:,:), du(:,:)  ! set to 0
75    INTEGER :: ind
76
77    CALL transfert_request(f_ps,req_i1) 
78    CALL transfert_request(f_u,req_e1_vect)
79
80    DO ind=1,ndomain
81       IF (.NOT. assigned_domain(ind)) CYCLE
82       CALL swap_dimensions(ind)
83       CALL swap_geometry(ind)
84       ps=f_ps(ind)
85       u=f_u(ind)
86       dps=f_dps(ind)
87       hflux=f_hflux(ind)
88       wflux=f_wflux(ind)
89       dtheta_rhodz=f_dtheta_rhodz(ind)
90       du=f_du(ind)
91
92!       !$OMP PARALLEL DEFAULT(SHARED)
93       CALL compute_caldyn(ps,u,hflux, wflux, dps, dtheta_rhodz, du)
94!       !$OMP END PARALLEL
95    ENDDO
96
97    IF (write_out) THEN
98       CALL output_field("wflux",f_wflux)
99       CALL output_field("ps",f_ps)
100    ENDIF
101    !    CALL check_mass_conservation(f_ps,f_dps)
102
103  END SUBROUTINE caldyn
104
105
106  SUBROUTINE compute_caldyn(ps,u, hflux,wflux,dps, dtheta_rhodz,du)
107    USE icosa
108    USE disvert_mod
109    IMPLICIT NONE
110    REAL(rstd),INTENT(IN)  :: ps(iim*jjm)
111    REAL(rstd),INTENT(IN)  :: u(iim*3*jjm,llm)
112    REAL(rstd),INTENT(OUT) :: du(iim*3*jjm,llm), hflux(iim*3*jjm,llm) ! hflux in kg/s
113    REAL(rstd),INTENT(OUT) :: dtheta_rhodz(iim*jjm,llm)
114    REAL(rstd),INTENT(OUT) :: dps(iim*jjm)
115    REAL(rstd),INTENT(OUT) :: wflux(iim*jjm,llm+1) ! vertical mass flux (kg/m2/s)
116
117    REAL(rstd),ALLOCATABLE :: rhodz(:,:)
118    REAL(rstd),ALLOCATABLE :: divm(:,:)  ! mass flux divergence
119
120    INTEGER :: i,j,ij,l   
121    LOGICAL,SAVE :: first=.TRUE.
122
123    ALLOCATE(rhodz(iim*jjm,llm))
124    ALLOCATE(divm(iim*jjm,llm))    ! mass flux divergence
125
126    dtheta_rhodz(:,:)=0.
127    du(:,:)=0.
128
129!!! Compute mass
130    DO l = 1, llm
131       DO j=jj_begin-1,jj_end+1
132          DO i=ii_begin-1,ii_end+1
133             ij=(j-1)*iim+i
134             rhodz(ij,l) = (ap(l)-ap(l+1) + ps(ij)*(bp(l)-bp(l+1)) )/g
135          ENDDO
136       ENDDO
137    ENDDO
138
139    DO l = 1, llm
140!!!  Mass fluxes
141       DO j=jj_begin-1,jj_end+1
142          DO i=ii_begin-1,ii_end+1
143             ij=(j-1)*iim+i
144             hflux(ij+u_right,l)=0.5*(rhodz(ij,l)+rhodz(ij+t_right,l))*u(ij+u_right,l)*le(ij+u_right)
145             hflux(ij+u_lup,l)=0.5*(rhodz(ij,l)+rhodz(ij+t_lup,l))*u(ij+u_lup,l)*le(ij+u_lup)
146             hflux(ij+u_ldown,l)=0.5*(rhodz(ij,l)+rhodz(ij+t_ldown,l))*u(ij+u_ldown,l)*le(ij+u_ldown)
147          ENDDO
148       ENDDO
149!!! Horizontal divergence of fluxes
150       DO j=jj_begin,jj_end
151          DO i=ii_begin,ii_end
152             ij=(j-1)*iim+i 
153             ! divm = +div(mass flux), sign convention as in Ringler et al. 2012, eq. 21
154             divm(ij,l)= 1./Ai(ij)*(ne(ij,right)*hflux(ij+u_right,l)   +  &
155                  ne(ij,rup)*hflux(ij+u_rup,l)       +  & 
156                  ne(ij,lup)*hflux(ij+u_lup,l)       +  & 
157                  ne(ij,left)*hflux(ij+u_left,l)     +  & 
158                  ne(ij,ldown)*hflux(ij+u_ldown,l)   +  & 
159                  ne(ij,rdown)*hflux(ij+u_rdown,l))
160          ENDDO
161       ENDDO
162    ENDDO
163
164!!! cumulate mass flux divergence from top to bottom
165    DO  l = llm-1, 1, -1
166       !$OMP DO
167       DO j=jj_begin,jj_end
168          DO i=ii_begin,ii_end
169             ij=(j-1)*iim+i
170             divm(ij,l) = divm(ij,l) + divm(ij,l+1)
171          ENDDO
172       ENDDO
173    ENDDO
174
175!!! Compute vertical mass flux
176    DO l = 1,llm-1
177       DO j=jj_begin,jj_end
178          DO i=ii_begin,ii_end
179             ij=(j-1)*iim+i
180             ! w = int(z,ztop,div(flux)dz) + B(eta)dps/dt
181             ! => w>0 for upward transport
182             wflux( ij, l+1 ) = divm( ij, l+1 ) - bp(l+1) * divm( ij, 1 )
183          ENDDO
184       ENDDO
185    ENDDO
186
187    ! compute dps, set vertical mass flux at the surface to 0
188    DO j=jj_begin,jj_end
189       DO i=ii_begin,ii_end
190          ij=(j-1)*iim+i
191          wflux(ij,1)  = 0.
192          ! dps/dt = -int(div flux)dz
193          dps(ij)=-divm(ij,1) * g 
194       ENDDO
195    ENDDO
196
197    DEALLOCATE(rhodz)
198    DEALLOCATE(divm)
199   
200  END SUBROUTINE compute_caldyn
201
202END MODULE caldyn_adv_mod
Note: See TracBrowser for help on using the repository browser.