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

Last change on this file since 187 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
RevLine 
[17]1MODULE caldyn_adv_mod
[19]2  USE icosa
[17]3
[139]4  IMPLICIT NONE
5  PRIVATE
6  PUBLIC :: init_caldyn, caldyn
7
[17]8CONTAINS
[139]9
[98]10  SUBROUTINE init_caldyn
[17]11  END SUBROUTINE init_caldyn
12
13  SUBROUTINE check_mass_conservation(f_ps,f_dps)
[139]14    USE icosa
[17]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
[139]21
[17]22    mass_tot=0
23    dmass_tot=0
[139]24
[17]25    CALL transfert_request(f_dps,req_i1)
26    CALL transfert_request(f_ps,req_i1)
27
28    DO ind=1,ndomain
[186]29       IF (.NOT. assigned_domain(ind)) CYCLE
[139]30       CALL swap_dimensions(ind)
31       CALL swap_geometry(ind)
[17]32
[139]33       ps=f_ps(ind)
34       dps=f_dps(ind)
[17]35
[139]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
[17]46    ENDDO
47    PRINT*, "mass_tot ", mass_tot,"      dmass_tot ",dmass_tot       
48
49  END SUBROUTINE check_mass_conservation
50
51
[139]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
[17]77    CALL transfert_request(f_ps,req_i1) 
[146]78    CALL transfert_request(f_u,req_e1_vect)
[139]79
[17]80    DO ind=1,ndomain
[186]81       IF (.NOT. assigned_domain(ind)) CYCLE
[139]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
[186]92!       !$OMP PARALLEL DEFAULT(SHARED)
[139]93       CALL compute_caldyn(ps,u,hflux, wflux, dps, dtheta_rhodz, du)
[186]94!       !$OMP END PARALLEL
[17]95    ENDDO
96
[129]97    IF (write_out) THEN
[139]98       CALL writefield("ps",f_ps)
99       CALL writefield("wflux",f_wflux)
[17]100    ENDIF
[139]101    !    CALL check_mass_conservation(f_ps,f_dps)
[17]102
103  END SUBROUTINE caldyn
[139]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   
[17]121    LOGICAL,SAVE :: first=.TRUE.
[139]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
[17]129!!! Compute mass
[139]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
[17]136       ENDDO
[139]137    ENDDO
[17]138
[139]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
[17]163
[139]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
[17]173    ENDDO
174
[139]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
[17]186
[139]187    ! compute dps, set vertical mass flux at the surface to 0
[17]188    DO j=jj_begin,jj_end
[139]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 
[17]194       ENDDO
195    ENDDO
196
[139]197    DEALLOCATE(rhodz)
198    DEALLOCATE(divm)
199   
[17]200  END SUBROUTINE compute_caldyn
[139]201
[17]202END MODULE caldyn_adv_mod
Note: See TracBrowser for help on using the repository browser.