source: codes/icosagcm/trunk/src/check_conserve.f90 @ 324

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

Merging OpenMP parallisme mode : by subdomain and on vertical level.
This feature is actually experimental but may be retro-compatible with the last method based only on subdomain

YM

File size: 11.4 KB
RevLine 
[149]1MODULE check_conserve_mod
[151]2  USE icosa 
3  IMPLICIT NONE
[149]4
[151]5  PRIVATE
6    TYPE(t_field),POINTER,SAVE :: f_pk(:), f_pks(:), f_p(:)
7    TYPE(t_field),POINTER,SAVE :: f_vort(:)
8    TYPE(t_field),POINTER,SAVE :: f_rhodz(:) 
[149]9   
[151]10  PUBLIC init_check_conserve, check_conserve 
[295]11    REAL(rstd),SAVE:: mtot0,ztot0,etot0,angtot0,stot0,rmsvtot0
12!$OMP THREADPRIVATE(mtot0,ztot0,etot0,angtot0,stot0,rmsvtot0)
[149]13     
[151]14CONTAINS 
[149]15
16!---------------------------------------------------------------------
17
[151]18  SUBROUTINE init_check_conserve
19  USE icosa
20  IMPLICIT NONE
[149]21    CALL allocate_field(f_pk,field_t,type_real,llm)
22    CALL allocate_field(f_p,field_t,type_real,llm+1)
23    CALL allocate_field(f_pks,field_t,type_real)
24    CALL allocate_field(f_rhodz,field_t,type_real,llm)
25    CALL allocate_field(f_vort,field_z,type_real,llm)
[151]26  END SUBROUTINE init_check_conserve
[149]27
[151]28  SUBROUTINE check_conserve(f_ps,f_dps,f_ue,f_theta_rhodz,f_phis,it) 
29  USE icosa 
30  USE pression_mod
31  USE vorticity_mod
32  USE caldyn_gcm_mod
33  USE exner_mod 
[295]34  USE mpipara, ONLY : is_mpi_master, comm_icosa
35  USE omp_para
[151]36  IMPLICIT NONE
37    TYPE(t_field),POINTER :: f_ps(:)
38    TYPE(t_field),POINTER :: f_dps(:)
39    TYPE(t_field),POINTER :: f_ue(:)
40    TYPE(t_field),POINTER :: f_theta_rhodz(:)
41    TYPE(t_field),POINTER :: f_phis(:)
[160]42    INTEGER::it
43
[151]44    REAL(rstd),POINTER :: p(:,:),rhodz(:,:) 
[160]45    INTEGER::ind,ierr
46    REAL(rstd) :: mtot, rmsdpdt
[295]47    REAL(rstd) :: etot, stot, angtot, rmsvtot, ztot
[151]48
[295]49    CALL transfert_request(f_ue,req_e1_vect)
[151]50    CALL pression(f_ps,f_p)
51
52    DO ind=1,ndomain 
[186]53      IF (.NOT. assigned_domain(ind)) CYCLE
[151]54      CALL swap_dimensions(ind)
55      CALL swap_geometry(ind)
[160]56      p=f_p(ind) 
57      rhodz=f_rhodz(ind)
[151]58      CALL compute_rhodz(p,rhodz) 
[160]59    END DO
[151]60
61    CALL vorticity(f_ue,f_vort)
[160]62    CALL check_mass_conserve(f_ps,f_dps,mtot,rmsdpdt)
[295]63    CALL check_PV(ztot) 
[151]64    CALL exner(f_ps,f_p,f_pks,f_pk)
[295]65    CALL check_EN(f_ue,f_theta_rhodz,f_phis, etot, stot, angtot, rmsvtot) 
[160]66
[295]67    IF (is_master) THEN
68       IF ( it == itau0  ) THEN
[160]69          ztot0 = ztot
70          mtot0 = mtot
71          etot0 = etot 
[295]72          angtot0  = angtot 
[160]73          stot0 = stot 
74       END IF
[151]75
[295]76       rmsvtot=SQRT(rmsvtot/mtot) 
[160]77       ztot=ztot/ztot0-1. ; mtot=mtot/mtot0-1. 
[295]78       etot=etot/etot0-1. ; angtot=angtot/angtot0-1. ; stot=stot/stot0-1. 
[160]79       rmsdpdt= daysec*1.e-2*sqrt(rmsdpdt/ncell_glo) 
80       
[151]81       OPEN(134,file="checkconsicosa.txt",position='append')
[295]82       WRITE(134,4000)mtot,rmsdpdt,etot,ztot,stot,rmsvtot,angtot
83       WRITE(134,*)mtot,rmsdpdt,etot,ztot,stot,rmsvtot,angtot 
[151]84       WRITE(134,*)"=================================================="
[295]85       WRITE(*,4000)mtot,rmsdpdt,etot,ztot,stot,rmsvtot,angtot
[160]86       
[186]874000   FORMAT(10x,'masse',5x,'rmsdpdt',5x,'energie',5x,'enstrophie'  &
88            ,5x,'entropie',5x,'rmsv',5x,'mt.ang',/,'GLOB  '                &
[295]89            ,e10.3,e13.6,5e13.3/)     
[186]90       close(134)
[295]91     
[160]92    END IF
[151]93  END SUBROUTINE check_conserve
94 
[149]95!---------------------------------------------------------------------
96
[160]97  SUBROUTINE check_mass_conserve(f_ps,f_dps,mtot,rmsdpdt)
98  USE mpi_mod
99  USE mpipara
[186]100  USE transfert_omp_mod
[149]101  USE icosa
[295]102  USE omp_para
[149]103  IMPLICIT NONE
104    TYPE(t_field),POINTER :: f_ps(:)
105    TYPE(t_field),POINTER :: f_dps(:)
106    REAL(rstd),POINTER :: ps(:),dps(:) 
[160]107    REAL(rstd), INTENT(OUT) :: mtot, rmsdpdt
108
[149]109    INTEGER :: ind,i,j,ij 
[160]110    REAL :: mloc, rmsloc
[186]111    REAL :: mloc_mpi, rmsloc_mpi
[149]112
[160]113    mloc=0.0; rmsloc=0.0
[151]114    DO ind=1,ndomain
[295]115      IF (.NOT. assigned_domain(ind) .OR. .NOT. is_omp_level_master) CYCLE
[149]116      CALL swap_dimensions(ind)
117      CALL swap_geometry(ind)
118      dps=f_dps(ind) 
119      ps=f_ps(ind)
120      DO j=jj_begin,jj_end
121        DO i=ii_begin,ii_end
122          ij=(j-1)*iim+i
123          IF (domain(ind)%own(i,j)) THEN
[160]124             mloc=mloc+ps(ij)*Ai(ij)
125             rmsloc=rmsloc+dps(ij)*dps(ij)
[151]126          ENDIF
[149]127        ENDDO
128      ENDDO
129    ENDDO
[160]130
[172]131    IF (using_mpi) THEN
[186]132        CALL reduce_sum_omp(mloc, mloc_mpi)
133        CALL reduce_sum_omp(rmsloc, rmsloc_mpi)
134!$OMP MASTER   
135      CALL MPI_REDUCE(mloc_mpi, mtot, 1, MPI_REAL8, MPI_SUM, 0, comm_icosa, ierr)
136      CALL MPI_REDUCE(rmsloc_mpi, rmsdpdt, 1, MPI_REAL8, MPI_SUM, 0, comm_icosa, ierr)
137!$OMP END MASTER
138    ELSE
[295]139      mtot=mloc
140      rmsdpdt=rmsloc
[172]141    ENDIF
142   
[149]143  END SUBROUTINE check_mass_conserve
144
145!---------------------------------------------------------------------
146
[295]147  SUBROUTINE check_en(f_ue,f_theta_rhodz,f_phis, etot, stot, angtot, rmsvtot) 
[151]148  USE icosa
149  USE pression_mod
150  USE vorticity_mod
[295]151  USE mpi_mod
152  USE mpipara
153  USE transfert_omp_mod
[151]154  IMPLICIT NONE
[149]155    TYPE(t_field), POINTER :: f_ue(:)
156    TYPE(t_field), POINTER :: f_theta_rhodz(:)
157    TYPE(t_field), POINTER :: f_phis(:)
[295]158    REAL(rstd),INTENT(OUT) :: etot, stot, angtot, rmsvtot
[149]159    REAL(rstd), POINTER :: ue(:,:)
160    REAL(rstd), POINTER :: p(:,:) 
161    REAL(rstd), POINTER :: theta_rhodz(:,:) 
162    REAL(rstd), POINTER :: pk(:,:) 
163    REAL(rstd), POINTER :: phis(:) 
164    REAL(rstd), POINTER :: rhodz(:,:) 
[295]165    REAL(rstd) :: e, s, ang, rmsv
166    REAL(rstd) :: e_mpi, s_mpi, ang_mpi, rmsv_mpi
[149]167    INTEGER :: ind
168
[295]169    e = 0 ; s = 0 ; ang = 0 ; rmsv = 0
[149]170
[151]171    DO ind=1,ndomain 
[186]172      IF (.NOT. assigned_domain(ind)) CYCLE
[151]173      CALL swap_dimensions(ind)
174      CALL swap_geometry(ind)
175      ue=f_ue(ind) 
176      p=f_p(ind)
177      rhodz=f_rhodz(ind) 
178      theta_rhodz=f_theta_rhodz(ind) 
179      pk=f_pk(ind) 
180      phis=f_phis(ind) 
[295]181      CALL compute_en(ind,ue,p,rhodz,theta_rhodz,pk,phis, e, s, ang, rmsv)
[151]182    END DO
[295]183
184    IF (using_mpi) THEN
185      CALL reduce_sum_omp(e, e_mpi)
186      CALL reduce_sum_omp(s, s_mpi)
187      CALL reduce_sum_omp(ang, ang_mpi)
188      CALL reduce_sum_omp(rmsv, rmsv_mpi)
189!$OMP MASTER   
190      CALL MPI_REDUCE(e_mpi, etot, 1, MPI_REAL8, MPI_SUM, 0, comm_icosa, ierr)
191      CALL MPI_REDUCE(s_mpi, stot, 1, MPI_REAL8, MPI_SUM, 0, comm_icosa, ierr)
192      CALL MPI_REDUCE(ang_mpi, angtot, 1, MPI_REAL8, MPI_SUM, 0, comm_icosa, ierr)
193      CALL MPI_REDUCE(rmsv_mpi, rmsvtot, 1, MPI_REAL8, MPI_SUM, 0, comm_icosa, ierr)
194!$OMP END MASTER
195    ELSE
196      etot=e
197      stot=s
198      angtot=ang
199      rmsvtot=rmsv
200    ENDIF
201
[151]202  END SUBROUTINE check_en 
[149]203
[295]204  SUBROUTINE compute_en(ind,u,p,rhodz,theta_rhodz,pk,phis, e, s, ang, rmsv)
[151]205  USE icosa
206  USE disvert_mod
207  USE wind_mod
[295]208  USE omp_para
[151]209  IMPLICIT NONE
[149]210    INTEGER,INTENT(IN)::ind 
211    REAL(rstd),INTENT(IN) :: u(3*iim*jjm,llm)
212    REAL(rstd),INTENT(IN) :: p(iim*jjm,llm+1)
213    REAL(rstd),INTENT(IN) :: rhodz(iim*jjm,llm)
214    REAL(rstd),INTENT(IN) :: theta_rhodz(iim*jjm,llm)
215    REAL(rstd),INTENT(IN) :: pk(iim*jjm,llm)
216    REAL(rstd),INTENT(IN) :: phis(iim*jjm)
[295]217    REAL(rstd),INTENT(INOUT) :: e
218    REAL(rstd),INTENT(INOUT) :: s
219    REAL(rstd),INTENT(INOUT) :: ang
220    REAL(rstd),INTENT(INOUT) :: rmsv
221   
[149]222    REAL(rstd):: theta(iim*jjm,llm)
223    REAL(rstd)::KE(iim*jjm,llm) 
224    REAL(rstd) :: ucenter(iim*jjm,3,llm)
225    REAL(rstd) :: ulon(iim*jjm,llm)
226    REAL(rstd) :: ulat(iim*jjm,llm)
227
228    REAL(rstd)::masse(iim*jjm,llm) 
229    REAL(rstd)::rad,radomeg,lat,lon
[198]230    REAL(rstd) ::xyz(3)
[149]231    INTEGER :: i,j,ij,l,ij2
232
233 
[295]234    DO l = ll_begin, ll_end
[151]235      DO j=jj_begin,jj_end
236        DO i=ii_begin,ii_end
237          ij=(j-1)*iim+i
238          masse(ij,l) = rhodz(ij,l)*Ai(ij) 
239          theta(ij,l) = theta_rhodz(ij,l)/rhodz(ij,l)
240          IF (domain(ind)%own(i,j)) THEN
[295]241            s = s + Ai(ij)*theta_rhodz(ij,l)
[151]242          END IF
243        END DO
244      END DO
245    END DO
[149]246
[295]247    DO l = ll_begin,ll_end
[151]248      DO j=jj_begin,jj_end
249        DO i=ii_begin,ii_end
250          ij=(j-1)*iim+i
251          IF (domain(ind)%own(i,j)) THEN
252            KE(ij,l)=   1/(4*Ai(ij))*(le(ij+u_right)*de(ij+u_right)*u(ij+u_right,l)**2 +   &
253                                      le(ij+u_rup)*de(ij+u_rup)*u(ij+u_rup,l)**2 +           &
254                                      le(ij+u_lup)*de(ij+u_lup)*u(ij+u_lup,l)**2 +           &
255                                      le(ij+u_left)*de(ij+u_left)*u(ij+u_left,l)**2 +        &
256                                      le(ij+u_ldown)*de(ij+u_ldown)*u(ij+u_ldown,l)**2 +     &
257                                      le(ij+u_rdown)*de(ij+u_rdown)*u(ij+u_rdown,l)**2 ) 
258            rmsv = rmsv + 2*masse(ij,l)*KE(ij,l) 
259          END IF
260        END DO
261      END DO
262    END DO 
[149]263
[295]264    DO l = ll_begin,ll_end
[151]265      DO j=jj_begin,jj_end
266        DO i=ii_begin,ii_end
267          ij=(j-1)*iim+i
268          IF (domain(ind)%own(i,j)) THEN
[295]269            e = e + masse(ij,l)*(phis(ij)+theta(ij,l)*pk(ij,l)+KE(ij,l))
[151]270          END IF
[149]271        END DO
[151]272      END DO
273    END DO 
[149]274
275!------------------------------ ANGULAR VELOCITY
[151]276    CALL compute_wind_centered(u,ucenter)
277    CALL compute_wind_centered_lonlat_compound(ucenter,ulon,ulat)
278    rad = radius 
279    radomeg = rad*omega
[149]280
[295]281    DO l = ll_begin,ll_end
[151]282      DO j=jj_begin,jj_end
283        DO i=ii_begin,ii_end
284          ij=(j-1)*iim+i
285          IF (domain(ind)%own(i,j)) THEN
[286]286            lat=lat_i(ij) 
[151]287            ang=ang+rad*cos(lat)*masse(ij,l)*(ulon(ij,l)+ radomeg*cos(lat))
288          END IF
289        END DO
290      END DO
291    END DO   
[149]292         
[151]293  END SUBROUTINE compute_en
[149]294
295!---------------------------------------------------------------------
296
[295]297  SUBROUTINE check_PV(ztot)
[151]298  USE icosa
[295]299  USE mpi_mod
300  USE mpipara
301  USE transfert_omp_mod
[151]302  IMPLICIT NONE
[295]303     REAL(rstd),INTENT(OUT) :: ztot
[151]304     REAL(rstd), POINTER :: vort(:,:)
305     REAL(rstd), POINTER :: rhodz(:,:) 
306     INTEGER :: ind
[295]307     REAL(rstd) :: z,z_mpi
[149]308
[295]309     z=0
[151]310     DO ind=1,ndomain 
[186]311       IF (.NOT. assigned_domain(ind)) CYCLE
[151]312       CALL swap_dimensions(ind)
313       CALL swap_geometry(ind)
314       vort=f_vort(ind)
315       rhodz=f_rhodz(ind) 
[295]316       CALL compute_PV(vort,rhodz,z) 
[151]317     ENDDO
[295]318
319    IF (using_mpi) THEN
320      CALL reduce_sum_omp(z, z_mpi)
321!$OMP MASTER   
322      CALL MPI_REDUCE(z_mpi, ztot, 1, MPI_REAL8, MPI_SUM, 0, comm_icosa, ierr)
323!$OMP END MASTER
324    ELSE
325      ztot=z
326    ENDIF
[149]327 
[151]328  END SUBROUTINE check_PV 
[149]329
[295]330  SUBROUTINE compute_PV(vort,rhodz,z) 
[151]331  USE icosa
332  USE disvert_mod
[295]333  USE omp_para
[151]334  IMPLICIT NONE
[149]335    REAL(rstd),INTENT(IN) :: vort(2*iim*jjm,llm)
336    REAL(rstd),INTENT(IN) :: rhodz(iim*jjm,llm) 
[295]337    REAL(rstd),INTENT(INOUT) :: z
[149]338    REAL(rstd)::qv1,qv2 
339    REAL(rstd)::hv1,hv2 
340    INTEGER :: i,j,ij,l,ij2
341
[151]342    hv1 = 0.0 ; hv2 = 0.0 
[149]343   
[295]344    DO l = ll_begin,ll_end
[149]345      DO j=jj_begin+1,jj_end-1
[151]346        DO i=ii_begin+1,ii_end-1
347          ij=(j-1)*iim+i
348          hv1 =  Riv2(ij,vup)        * rhodz(ij,l)           &
349            + Riv2(ij+t_rup,vldown) * rhodz(ij+t_rup,l)     &
350            + Riv2(ij+t_lup,vrdown) * rhodz(ij+t_lup,l)
351   
352          qv1 = ( vort(ij+z_up,l)+fv(ij+z_up) )/hv1
353         
354          hv2  =  Riv2(ij,vdown)     * rhodz(ij,l)          &
355            + Riv2(ij+t_ldown,vrup) * rhodz(ij+t_ldown,l)  &
356            + Riv2(ij+t_rdown,vlup) * rhodz(ij+t_rdown,l)
357                     
358          qv2 =( vort(ij+z_down,l)+fv(ij+z_down) )/hv2
[149]359
[295]360          z = z + (qv1*qv1*hv1 + qv2*qv2*hv2) 
[151]361
[149]362        ENDDO
[151]363      ENDDO
[295]364     
[151]365    ENDDO
366
367  END SUBROUTINE compute_PV
[149]368!---------------------------------------------------------------------
369
[151]370   SUBROUTINE compute_rhodz(p,rhodz) 
371   USE icosa 
372   IMPLICIT NONE
[149]373     REAL(rstd),INTENT(IN) :: p(iim*jjm,llm+1)
374     REAL(rstd),INTENT(OUT):: rhodz(iim*jjm,llm)
375     REAL(rstd) ::mass(iim*jjm,llm)
376     INTEGER :: i,j,ij,l 
377       
378     DO l = 1, llm
379      DO j=jj_begin,jj_end
380       DO i=ii_begin,ii_end
381         ij=(j-1)*iim+i
382         mass(ij,l) = ( p(ij,l) - p(ij,l+1) ) * Ai(ij)/g
383         rhodz(ij,l) = mass(ij,l) / Ai(ij)
384       ENDDO
385      ENDDO
386     ENDDO
387
[151]388   END SUBROUTINE compute_rhodz
[149]389!====================================================================
390
391
392 END MODULE check_conserve_mod
Note: See TracBrowser for help on using the repository browser.