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

Last change on this file since 186 was 186, checked in by ymipsl, 10 years ago

Add new openMP parallelism based on distribution of domains on threads. There is no more limitation of number of threads by MPI process.

YM

File size: 5.7 KB
Line 
1MODULE caldyn_adv_mod
2  USE icosa
3
4  IMPLICIT NONE
5  PRIVATE
6  PUBLIC :: init_caldyn, caldyn
7
8CONTAINS
9
10  SUBROUTINE init_caldyn
11  END SUBROUTINE init_caldyn
12
13  SUBROUTINE check_mass_conservation(f_ps,f_dps)
14    USE icosa
15    TYPE(t_field),POINTER :: f_ps(:)
16    TYPE(t_field),POINTER :: f_dps(:)
17    REAL(rstd),POINTER :: ps(:)
18    REAL(rstd),POINTER :: dps(:)
19    REAL(rstd) :: mass_tot,dmass_tot
20    INTEGER :: ind,i,j,ij
21
22    mass_tot=0
23    dmass_tot=0
24
25    CALL transfert_request(f_dps,req_i1)
26    CALL transfert_request(f_ps,req_i1)
27
28    DO ind=1,ndomain
29       IF (.NOT. assigned_domain(ind)) CYCLE
30       CALL swap_dimensions(ind)
31       CALL swap_geometry(ind)
32
33       ps=f_ps(ind)
34       dps=f_dps(ind)
35
36       DO j=jj_begin,jj_end
37          DO i=ii_begin,ii_end
38             ij=(j-1)*iim+i
39             IF (domain(ind)%own(i,j)) THEN
40                mass_tot=mass_tot+ps(ij)*Ai(ij)/g
41                dmass_tot=dmass_tot+dps(ij)*Ai(ij)/g
42             ENDIF
43          ENDDO
44       ENDDO
45
46    ENDDO
47    PRINT*, "mass_tot ", mass_tot,"      dmass_tot ",dmass_tot       
48
49  END SUBROUTINE check_mass_conservation
50
51
52  SUBROUTINE caldyn(write_out,f_phis, f_ps, f_theta_rhodz, f_u, f_q, &
53       f_hflux, f_wflux, f_dps, f_dtheta_rhodz, f_du)
54    USE icosa
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 writefield("ps",f_ps)
99       CALL writefield("wflux",f_wflux)
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.