source: codes/icosagcm/trunk/src/dissip_gcm.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: 25.5 KB
RevLine 
[15]1MODULE dissip_gcm_mod
[19]2  USE icosa
[15]3
[26]4  PRIVATE
5
6  TYPE(t_field),POINTER,SAVE :: f_due_diss1(:)
7  TYPE(t_field),POINTER,SAVE :: f_due_diss2(:)
8
[109]9  TYPE(t_field),POINTER,SAVE :: f_theta(:), f_phi(:), f_pk(:), f_pks(:), f_p(:)
[26]10  TYPE(t_field),POINTER,SAVE :: f_dtheta_diss(:)
11  TYPE(t_field),POINTER,SAVE :: f_dtheta_rhodz_diss(:)
[186]12  TYPE(t_message),SAVE :: req_due, req_dtheta 
[15]13 
[26]14  INTEGER,SAVE :: nitergdiv=1
[186]15!$OMP THREADPRIVATE(nitergdiv)
[26]16  INTEGER,SAVE :: nitergrot=1
[186]17!$OMP THREADPRIVATE(nitergrot)
[26]18  INTEGER,SAVE :: niterdivgrad=1
[186]19!$OMP THREADPRIVATE(niterdivgrad)
[15]20
21  REAL,ALLOCATABLE,SAVE :: tau_graddiv(:)
[186]22!$OMP THREADPRIVATE(tau_graddiv)
[15]23  REAL,ALLOCATABLE,SAVE :: tau_gradrot(:)
[186]24!$OMP THREADPRIVATE(tau_gradrot)
[15]25  REAL,ALLOCATABLE,SAVE :: tau_divgrad(:)
[186]26!$OMP THREADPRIVATE(tau_divgrad)
[15]27 
28  REAL,SAVE :: cgraddiv
[186]29!$OMP THREADPRIVATE(cgraddiv)
[15]30  REAL,SAVE :: cgradrot
[186]31!$OMP THREADPRIVATE(cgradrot)
[15]32  REAL,SAVE :: cdivgrad
[186]33!$OMP THREADPRIVATE(cdivgrad)
[109]34
35  INTEGER, SAVE :: rayleigh_friction_type, rayleigh_shear
[186]36!$OMP THREADPRIVATE(rayleigh_friction_type)
37  REAL, SAVE    :: rayleigh_tau
38!$OMP THREADPRIVATE(rayleigh_shear)
[15]39 
[26]40  REAL,SAVE    :: dtdissip
[186]41!$OMP THREADPRIVATE(dtdissip)
[151]42 
[26]43  PUBLIC init_dissip, dissip
[15]44CONTAINS
45
46  SUBROUTINE allocate_dissip
[19]47  USE icosa
[15]48  IMPLICIT NONE 
[26]49    CALL allocate_field(f_due_diss1,field_u,type_real,llm)
50    CALL allocate_field(f_due_diss2,field_u,type_real,llm)
51    CALL allocate_field(f_theta,field_t,type_real,llm)
52    CALL allocate_field(f_dtheta_diss,field_t,type_real,llm)
53    CALL allocate_field(f_dtheta_rhodz_diss,field_t,type_real,llm)
[109]54
55    CALL allocate_field(f_phi,field_t,type_real,llm)
56    CALL allocate_field(f_pk,field_t,type_real,llm)
57    CALL allocate_field(f_p,field_t,type_real,llm+1)
58    CALL allocate_field(f_pks,field_t,type_real)
[26]59   
[15]60    ALLOCATE(tau_graddiv(llm))
61    ALLOCATE(tau_gradrot(llm))   
62    ALLOCATE(tau_divgrad(llm))
63  END SUBROUTINE allocate_dissip
64 
[98]65  SUBROUTINE init_dissip
[19]66  USE icosa
[15]67  USE disvert_mod
[26]68  USE mpi_mod
69  USE mpipara
[151]70  USE transfert_mod
[148]71  USE time_mod
[186]72  USE transfert_omp_mod
[15]73  IMPLICIT NONE
74 
[186]75  TYPE(t_field),POINTER,SAVE  :: f_u(:)
76  TYPE(t_field),POINTER,SAVE  :: f_du(:)
77  REAL(rstd),POINTER     :: u(:)
78  REAL(rstd),POINTER     :: du(:)
79  TYPE(t_field),POINTER,SAVE  :: f_theta(:)
80  TYPE(t_field),POINTER ,SAVE :: f_dtheta(:)
[15]81  REAL(rstd),POINTER    :: theta(:)
82  REAL(rstd),POINTER    :: dtheta(:)
[59]83  REAL(rstd)            :: dumax,dumax1
84  REAL(rstd)            :: dthetamax,dthetamax1
[15]85  REAL(rstd)            :: r
86  REAL(rstd)            :: tau
87  REAL(rstd)            :: zz, zvert, fact
88  INTEGER               :: l
[109]89  CHARACTER(len=255)    :: rayleigh_friction_key
[148]90  REAL(rstd)            :: mintau
[174]91  INTEGER               :: seed_size
92  INTEGER,ALLOCATABLE   :: seed(:)
[15]93 
94           
[174]95  INTEGER :: i,j,ij,ind,it,iter
[15]96
[109]97   rayleigh_friction_key='none'
98   CALL getin("rayleigh_friction_type",rayleigh_friction_key)
99   SELECT CASE(TRIM(rayleigh_friction_key))
100   CASE('none')
101      rayleigh_friction_type=0
[131]102      IF (is_mpi_root) PRINT *, 'No Rayleigh friction'
[109]103   CASE('dcmip2_schaer_noshear')
104      rayleigh_friction_type=1
105      rayleigh_shear=0
[131]106      IF (is_mpi_root) PRINT *, 'Rayleigh friction : Schaer-like mountain without shear DCMIP2.1'
[109]107   CASE('dcmip2_schaer_shear')
108      rayleigh_shear=1
109      rayleigh_friction_type=2
[131]110      IF (is_mpi_root) PRINT *, 'Rayleigh friction : Schaer-like mountain with shear DCMIP2.2'
[109]111   CASE DEFAULT
[151]112      IF (is_mpi_root) PRINT *, 'Bad selector : rayleigh_friction_type =', TRIM(rayleigh_friction_key), ' in dissip_gcm.f90/init_dissip'
[109]113      STOP
114   END SELECT
115
116   IF(rayleigh_friction_type>0) THEN
117      rayleigh_tau=0.
118      CALL getin("rayleigh_friction_tau",rayleigh_tau)
119      rayleigh_tau = rayleigh_tau / scale_factor
120      IF(rayleigh_tau<=0) THEN
[131]121         IF (is_mpi_root) PRINT *, 'Forbidden : negative value for rayleigh_friction_tau =',rayleigh_tau
[109]122         STOP
123      END IF
124   END IF
125
[15]126    CALL allocate_dissip
127    CALL allocate_field(f_u,field_u,type_real)
128    CALL allocate_field(f_du,field_u,type_real)
129    CALL allocate_field(f_theta,field_t,type_real)
130    CALL allocate_field(f_dtheta,field_t,type_real)
[151]131   
132    CALL init_message(f_due_diss1,req_e1_vect,req_due)
133    CALL init_message(f_dtheta_diss,req_i1,req_dtheta)
[15]134
135    tau_graddiv(:)=5000
136    CALL getin("tau_graddiv",tau)
[32]137    tau_graddiv(:)=tau/scale_factor
[26]138
139    CALL getin("nitergdiv",nitergdiv)
[15]140   
141    tau_gradrot(:)=5000
[186]142    CALL getin("tau_gradrot",tau)
[32]143    tau_gradrot(:)=tau/scale_factor
[26]144
145    CALL getin("nitergrot",nitergrot)
[15]146   
147
148    tau_divgrad(:)=5000
149    CALL getin("tau_divgrad",tau)
[32]150    tau_divgrad(:)=tau/scale_factor
[26]151
152    CALL getin("niterdivgrad",niterdivgrad)
[15]153
154
155    cgraddiv=-1
156    cdivgrad=-1
157    cgradrot=-1
158   
159    DO ind=1,ndomain
[186]160      IF (.NOT. assigned_domain(ind)) CYCLE
[15]161      CALL swap_dimensions(ind)
162      CALL swap_geometry(ind)
163      u=f_u(ind)
164
165      DO j=jj_begin,jj_end
166        DO i=ii_begin,ii_end
[174]167          ij=(j-1)*iim+i   
[15]168          CALL RANDOM_NUMBER(r)
[174]169          u(ij+u_right)=r-0.5
[15]170          CALL RANDOM_NUMBER(r)
[174]171          u(ij+u_lup)=r-0.5
[15]172          CALL RANDOM_NUMBER(r)
[174]173          u(ij+u_ldown)=r-0.5
174        ENDDO
175      ENDDO       
[15]176    ENDDO
177 
178
179
[29]180    DO it=1,20
[26]181     
[15]182      dumax=0
[26]183      DO iter=1,nitergdiv
[146]184        CALL transfert_request(f_u,req_e1_vect)
[26]185        DO ind=1,ndomain
[186]186          IF (.NOT. assigned_domain(ind)) CYCLE
[26]187          CALL swap_dimensions(ind)
188          CALL swap_geometry(ind)
189          u=f_u(ind)
190          du=f_du(ind)
[151]191          CALL compute_gradiv(u,du,1,1)
[26]192          u=du
193        ENDDO
[15]194      ENDDO
[26]195
[146]196      CALL transfert_request(f_du,req_e1_vect)
[15]197     
198      DO ind=1,ndomain
[186]199        IF (.NOT. assigned_domain(ind)) CYCLE
[15]200        CALL swap_dimensions(ind)
201        CALL swap_geometry(ind)
202        u=f_u(ind)
203        du=f_du(ind)
[26]204         
[15]205        DO j=jj_begin,jj_end
206          DO i=ii_begin,ii_end
[174]207            ij=(j-1)*iim+i   
208            if (le(ij+u_right)>1e-100) dumax=MAX(dumax,ABS(du(ij+u_right)))
209            if (le(ij+u_lup)>1e-100)   dumax=MAX(dumax,ABS(du(ij+u_lup)))
210            if (le(ij+u_ldown)>1e-100) dumax=MAX(dumax,ABS(du(ij+u_ldown)))
[15]211          ENDDO
212        ENDDO
213      ENDDO
214
[59]215      IF (using_mpi) THEN
[186]216        CALL reduce_sum_omp(dumax,dumax1)
217!$OMP MASTER       
218        CALL MPI_ALLREDUCE(dumax1,dumax,1,MPI_REAL8,MPI_MAX,comm_icosa,ierr)
219!$OMP END MASTER     
220        CALL bcast_omp(dumax) 
221      ELSE
222        CALL allreduce_sum_omp(dumax,dumax1)
[59]223        dumax=dumax1
[186]224      ENDIF 
[59]225                       
[15]226      DO ind=1,ndomain
[186]227        IF (.NOT. assigned_domain(ind)) CYCLE
[15]228        CALL swap_dimensions(ind)
229        CALL swap_geometry(ind)
230        u=f_u(ind)
231        du=f_du(ind)
232        u=du/dumax
233      ENDDO
[131]234      IF (is_mpi_root) PRINT *,"gradiv : it :",it ,": dumax",dumax
[15]235
236    ENDDO 
[131]237    IF (is_mpi_root) PRINT *,"gradiv : dumax",dumax
238    IF (is_mpi_root) PRINT *, 'mean T-cell edge size (km)', 1.45*radius/iim_glo/1000., &
239                              'effective T-cell half-edge size (km)', dumax**(-.5/nitergdiv)/1000
240    IF (is_mpi_root)  PRINT *, 'Max. time step assuming c=340 m/s and Courant number=2.8 :', &
241                               2.8/340.*dumax**(-.5/nitergdiv)
[129]242
[15]243    cgraddiv=dumax**(-1./nitergdiv)
[131]244    IF (is_mpi_root) PRINT *,"cgraddiv : ",cgraddiv
[15]245
246    DO ind=1,ndomain
[186]247      IF (.NOT. assigned_domain(ind)) CYCLE
[15]248      CALL swap_dimensions(ind)
249      CALL swap_geometry(ind)
250      u=f_u(ind)
251
[174]252      DO j=jj_begin,jj_end
[15]253        DO i=ii_begin,ii_end
[174]254          ij=(j-1)*iim+i   
[15]255          CALL RANDOM_NUMBER(r)
[174]256          u(ij+u_right)=r-0.5
[15]257          CALL RANDOM_NUMBER(r)
[174]258          u(ij+u_lup)=r-0.5
[15]259          CALL RANDOM_NUMBER(r)
[174]260          u(ij+u_ldown)=r-0.5
261        ENDDO
262      ENDDO       
[15]263    ENDDO
264
265
[29]266    DO it=1,20
[15]267 
268      dumax=0
[26]269      DO iter=1,nitergrot
[146]270        CALL transfert_request(f_u,req_e1_vect)
[26]271        DO ind=1,ndomain
[186]272          IF (.NOT. assigned_domain(ind)) CYCLE
[26]273          CALL swap_dimensions(ind)
274          CALL swap_geometry(ind)
275          u=f_u(ind)
276          du=f_du(ind)
[151]277          CALL compute_gradrot(u,du,1,1)
[26]278          u=du
279        ENDDO
[15]280      ENDDO
281
[146]282      CALL transfert_request(f_du,req_e1_vect)
[15]283     
284      DO ind=1,ndomain
[186]285        IF (.NOT. assigned_domain(ind)) CYCLE
[15]286        CALL swap_dimensions(ind)
287        CALL swap_geometry(ind)
288        u=f_u(ind)
289        du=f_du(ind)
290       
291        DO j=jj_begin,jj_end
292          DO i=ii_begin,ii_end
[174]293            ij=(j-1)*iim+i   
294            if (le(ij+u_right)>1e-100) dumax=MAX(dumax,ABS(du(ij+u_right)))
295            if (le(ij+u_lup)>1e-100) dumax=MAX(dumax,ABS(du(ij+u_lup)))
296            if (le(ij+u_ldown)>1e-100) dumax=MAX(dumax,ABS(du(ij+u_ldown)))
[15]297          ENDDO
298        ENDDO
299      ENDDO
[26]300
[186]301      IF (using_mpi) THEN
302        CALL reduce_sum_omp(dumax,dumax1)
303!$OMP MASTER       
304        CALL MPI_ALLREDUCE(dumax1,dumax,1,MPI_REAL8,MPI_MAX,comm_icosa,ierr)
305!$OMP END MASTER     
306        CALL bcast_omp(dumax) 
307      ELSE
308        CALL allreduce_sum_omp(dumax,dumax1)
[59]309        dumax=dumax1
[186]310      ENDIF 
311
[15]312     
313      DO ind=1,ndomain
[186]314        IF (.NOT. assigned_domain(ind)) CYCLE
[15]315        CALL swap_dimensions(ind)
316        CALL swap_geometry(ind)
317        u=f_u(ind)
318        du=f_du(ind)
319        u=du/dumax
320      ENDDO
321     
[131]322      IF (is_mpi_root) PRINT *,"gradrot : it :",it ,": dumax",dumax
[15]323
324    ENDDO 
[131]325    IF (is_mpi_root) PRINT *,"gradrot : dumax",dumax
[15]326 
[26]327    cgradrot=dumax**(-1./nitergrot) 
[131]328    IF (is_mpi_root) PRINT *,"cgradrot : ",cgradrot
[15]329   
330
331
332    DO ind=1,ndomain
[186]333      IF (.NOT. assigned_domain(ind)) CYCLE
[15]334      CALL swap_dimensions(ind)
335      CALL swap_geometry(ind)
336      theta=f_theta(ind)
337 
[174]338      DO j=jj_begin,jj_end
339        DO i=ii_begin,ii_end
340          ij=(j-1)*iim+i   
341          CALL RANDOM_NUMBER(r)
342          theta(ij)=r-0.5
[15]343        ENDDO
[174]344      ENDDO 
[15]345    ENDDO
346
[29]347    DO it=1,20
[15]348
349      dthetamax=0
[26]350      DO iter=1,niterdivgrad
351        CALL transfert_request(f_theta,req_i1)
352        DO ind=1,ndomain
[186]353          IF (.NOT. assigned_domain(ind)) CYCLE
[26]354          CALL swap_dimensions(ind)
355          CALL swap_geometry(ind)
356          theta=f_theta(ind)
357          dtheta=f_dtheta(ind)
[151]358          CALL compute_divgrad(theta,dtheta,1,1)
[26]359          theta=dtheta
360        ENDDO
[15]361      ENDDO
362
363      CALL transfert_request(f_dtheta,req_i1)
364     
365      DO ind=1,ndomain
[186]366        IF (.NOT. assigned_domain(ind)) CYCLE
[15]367        CALL swap_dimensions(ind)
368        CALL swap_geometry(ind)
369        theta=f_theta(ind)
370        dtheta=f_dtheta(ind)
371       
372        DO j=jj_begin,jj_end
373          DO i=ii_begin,ii_end
[174]374            ij=(j-1)*iim+i   
375            dthetamax=MAX(dthetamax,ABS(dtheta(ij)))
[15]376          ENDDO
377        ENDDO
378      ENDDO
[186]379
380      IF (using_mpi) THEN
381        CALL reduce_sum_omp(dthetamax ,dthetamax1)
382!$OMP MASTER       
383        CALL MPI_ALLREDUCE(dthetamax1,dthetamax,1,MPI_REAL8,MPI_MAX,comm_icosa,ierr)
384!$OMP END MASTER     
385        CALL bcast_omp(dthetamax) 
386      ELSE
387        CALL allreduce_sum_omp(dthetamax,dthetamax1)
388        dumax=dumax1
389      ENDIF 
[174]390     
[131]391      IF (is_mpi_root) PRINT *,"divgrad : it :",it ,": dthetamax",dthetamax
[15]392
393      DO ind=1,ndomain
[186]394        IF (.NOT. assigned_domain(ind)) CYCLE
[15]395        CALL swap_dimensions(ind)
396        CALL swap_geometry(ind)
397        theta=f_theta(ind)
398        dtheta=f_dtheta(ind)
399        theta=dtheta/dthetamax
400      ENDDO
401    ENDDO 
402
[131]403    IF (is_mpi_root) PRINT *,"divgrad : divgrad",dthetamax
[15]404 
[26]405    cdivgrad=dthetamax**(-1./niterdivgrad) 
[131]406    IF (is_mpi_root) PRINT *,"cdivgrad : ",cdivgrad
[15]407
408     
409    fact=2
410    DO l=1,llm
[167]411       IF(ap_bp_present) THEN ! height-dependent dissipation
412          zz= 1. - preff/presnivs(l)
413       ELSE
414          zz = 0.
415       END IF
[15]416       zvert=fact-(fact-1)/(1+zz*zz)
417       tau_graddiv(l) = tau_graddiv(l)/zvert
418       tau_gradrot(l) = tau_gradrot(l)/zvert
419       tau_divgrad(l) = tau_divgrad(l)/zvert
420    ENDDO
[148]421
422    mintau=tau_graddiv(1)
423    DO l=1,llm
424      mintau=MIN(mintau,tau_graddiv(l))
425      mintau=MIN(mintau,tau_gradrot(l))
426      mintau=MIN(mintau,tau_divgrad(l))
427    ENDDO
[15]428       
[148]429    itau_dissip=INT(mintau/dt)
430    itau_dissip=MAX(1,itau_dissip)
431    dtdissip=itau_dissip*dt
432    IF (is_mpi_root) PRINT *,"mintau ",mintau,"itau_dissip",itau_dissip," dtdissip ",dtdissip
[15]433
434  END SUBROUTINE init_dissip 
435 
436 
[167]437  SUBROUTINE dissip(f_ue,f_due,f_mass,f_phis,f_theta_rhodz,f_dtheta_rhodz)
[19]438  USE icosa
[15]439  USE theta2theta_rhodz_mod
[109]440  USE pression_mod
441  USE exner_mod
442  USE geopotential_mod
[145]443  USE trace
[148]444  USE time_mod
[151]445  USE omp_para
[15]446  IMPLICIT NONE
447    TYPE(t_field),POINTER :: f_ue(:)
448    TYPE(t_field),POINTER :: f_due(:)
[167]449    TYPE(t_field),POINTER :: f_mass(:), f_phis(:)
[15]450    TYPE(t_field),POINTER :: f_theta_rhodz(:)
451    TYPE(t_field),POINTER :: f_dtheta_rhodz(:)
[26]452
[15]453    REAL(rstd),POINTER         :: due(:,:)
[109]454    REAL(rstd),POINTER         :: phi(:,:), ue(:,:)
[26]455    REAL(rstd),POINTER         :: due_diss1(:,:)
456    REAL(rstd),POINTER         :: due_diss2(:,:)
[15]457    REAL(rstd),POINTER         :: dtheta_rhodz(:,:)
[26]458    REAL(rstd),POINTER         :: dtheta_rhodz_diss(:,:)
[15]459
[109]460    INTEGER :: ind, shear
[174]461    INTEGER :: l,ij
[151]462
463!$OMP BARRIER
[15]464   
[145]465    CALL trace_start("dissip")
[26]466    CALL gradiv(f_ue,f_due_diss1)
467    CALL gradrot(f_ue,f_due_diss2)
[167]468
469    CALL divgrad_theta_rhodz(f_mass,f_theta_rhodz,f_dtheta_rhodz_diss)
[26]470   
[151]471! later for openmp   
472!    IF(rayleigh_friction_type>0) THEN
473!       CALL pression(f_ps, f_p)
474!       CALL exner(f_ps, f_p, f_pks, f_pk)
475!       CALL geopotential(f_phis,f_pks,f_pk,f_theta,f_phi)
476!    END IF
[109]477
[15]478    DO ind=1,ndomain
[186]479      IF (.NOT. assigned_domain(ind)) CYCLE
[15]480      CALL swap_dimensions(ind)
481      CALL swap_geometry(ind)
482      due=f_due(ind) 
[26]483      due_diss1=f_due_diss1(ind)
484      due_diss2=f_due_diss2(ind)
485      dtheta_rhodz=f_dtheta_rhodz(ind)
486      dtheta_rhodz_diss=f_dtheta_rhodz_diss(ind)
[151]487
488      DO l=ll_begin,ll_end
[174]489!$SIMD
490        DO ij=ij_begin,ij_end
[15]491
[174]492            due(ij+u_right,l) = -0.5*( due_diss1(ij+u_right,l)/tau_graddiv(l) + due_diss2(ij+u_right,l)/tau_gradrot(l))*itau_dissip 
493            due(ij+u_lup,l)   = -0.5*( due_diss1(ij+u_lup,l)  /tau_graddiv(l) + due_diss2(ij+u_lup,l)  /tau_gradrot(l))*itau_dissip
494            due(ij+u_ldown,l) = -0.5*( due_diss1(ij+u_ldown,l)/tau_graddiv(l) + due_diss2(ij+u_ldown,l)/tau_gradrot(l))*itau_dissip
[26]495
[174]496            dtheta_rhodz(ij,l) = -0.5*dtheta_rhodz_diss(ij,l)/tau_divgrad(l)*itau_dissip
[26]497        ENDDO
498      ENDDO
[109]499
[151]500!      dtheta_rhodz=0
501!      due=0
502
503! later for openmp 
504!      IF(rayleigh_friction_type>0) THEN
505!         phi=f_phi(ind)
506!         ue=f_ue(ind)
507!         DO l=1,llm
508!            DO j=jj_begin,jj_end
509!               DO i=ii_begin,ii_end
510!                  n=(j-1)*iim+i
511!                  CALL relax(t_right, u_right)
512!                  CALL relax(t_lup,   u_lup)
513!                  CALL relax(t_ldown, u_ldown)
514!               ENDDO
515!            ENDDO
516!         END DO
517!      END IF
[109]518   END DO
519
[145]520   CALL trace_end("dissip")
521
[151]522!$OMP BARRIER
523
[109]524    CONTAINS
525      SUBROUTINE relax(shift_t, shift_u)
526        USE dcmip_initial_conditions_test_1_2_3
527        REAL(rstd) :: z, ulon,ulat, lon,lat, & ! input to test2_schaer_mountain
528             p,hyam,hybm,w,t,phis,ps,rho,q, &   ! unused input/output to test2_schaer_mountain
529             fz, u3d(3), uref
530        REAL(rstd), PARAMETER :: zh=2e4,ztop=3e4  ! DCMIP values
531        LOGICAL :: hybrid_eta
532        INTEGER :: shift_u, shift_t, zcoords, nn
[174]533        z = (phi(ij,l)+phi(ij+shift_t,l))/(2.*g)
[109]534        IF(z>zh) THEN  ! relax only in the sponge layer z>zh
[151]535
[174]536           nn = ij+shift_u
[109]537           CALL xyz2lonlat(xyz_e(nn,:),lon,lat)
538           zcoords = 1 ; hybrid_eta = .FALSE. ! use z instead of p or hyam/hybm
539           CALL test2_schaer_mountain(lon,lat,p,z,zcoords,hybrid_eta, &
540                hyam,hybm,shear,ulon,ulat,w,t,phis,ps,rho,q)
541!           u3d = ulon*elon_e(nn,:) + ulat*elat_e(nn,:)
542           u3d = ulon*elon_e(nn,:) ! ulat=0
543           uref = sum(u3d*ep_e(nn,:))
544
545           fz = sin((pi/2)*(z-zh)/(ztop-zh))
546           fz = fz*fz/rayleigh_tau
547!           fz = 1/rayleigh_tau
548           due(nn,l) = due(nn,l) - fz*(ue(nn,l)-uref)
549!           due(nn,l) = due(nn,l) - fz*ue(nn,l)
550         END IF
551       END SUBROUTINE relax
[15]552     
553  END SUBROUTINE dissip
554
[26]555  SUBROUTINE gradiv(f_ue,f_due)
[19]556  USE icosa
[145]557  USE trace
[151]558  USE omp_para
[15]559  IMPLICIT NONE
[26]560    TYPE(t_field),POINTER :: f_ue(:)
561    TYPE(t_field),POINTER :: f_due(:)
562    REAL(rstd),POINTER    :: ue(:,:)
563    REAL(rstd),POINTER    :: due(:,:)
564    INTEGER :: ind
[174]565    INTEGER :: it,l,ij
[26]566       
[145]567    CALL trace_start("gradiv")
568
[26]569    DO ind=1,ndomain
[186]570      IF (.NOT. assigned_domain(ind)) CYCLE
[26]571      CALL swap_dimensions(ind)
572      CALL swap_geometry(ind)
573      ue=f_ue(ind)
574      due=f_due(ind) 
[151]575      DO  l = ll_begin, ll_end
[174]576!$SIMD
577        DO ij=ij_begin,ij_end
[151]578             due(ij+u_right,l)=ue(ij+u_right,l)
579             due(ij+u_lup,l)=ue(ij+u_lup,l)
580             due(ij+u_ldown,l)=ue(ij+u_ldown,l)
581        ENDDO
582      ENDDO
[26]583    ENDDO
[15]584
[26]585    DO it=1,nitergdiv
586       
[151]587      CALL send_message(f_due,req_due)
588      CALL wait_message(req_due)
[26]589       
590      DO ind=1,ndomain
[186]591        IF (.NOT. assigned_domain(ind)) CYCLE
[26]592        CALL swap_dimensions(ind)
593        CALL swap_geometry(ind)
594        due=f_due(ind) 
[151]595        CALL compute_gradiv(due,due,ll_begin,ll_end)
[26]596      ENDDO
597    ENDDO
[15]598
[145]599   CALL trace_end("gradiv")
600
[26]601  END SUBROUTINE gradiv
602 
603
604  SUBROUTINE gradrot(f_ue,f_due)
605  USE icosa
[145]606  USE trace
[151]607  USE omp_para
[26]608  IMPLICIT NONE
609    TYPE(t_field),POINTER :: f_ue(:)
610    TYPE(t_field),POINTER :: f_due(:)
611    REAL(rstd),POINTER    :: ue(:,:)
612    REAL(rstd),POINTER    :: due(:,:)
[15]613    INTEGER :: ind
[174]614    INTEGER :: it,l,ij
[26]615       
[145]616    CALL trace_start("gradrot")
617
[26]618    DO ind=1,ndomain
[186]619      IF (.NOT. assigned_domain(ind)) CYCLE
[26]620      CALL swap_dimensions(ind)
621      CALL swap_geometry(ind)
622      ue=f_ue(ind)
623      due=f_due(ind) 
[151]624      DO  l = ll_begin, ll_end
[174]625!$SIMD
626        DO ij=ij_begin,ij_end
[151]627             due(ij+u_right,l)=ue(ij+u_right,l)
628             due(ij+u_lup,l)=ue(ij+u_lup,l)
629             due(ij+u_ldown,l)=ue(ij+u_ldown,l)
630        ENDDO
631      ENDDO
[26]632    ENDDO
[15]633
[26]634    DO it=1,nitergrot
635       
[151]636      CALL send_message(f_due,req_due)
637      CALL wait_message(req_due)
[26]638       
639      DO ind=1,ndomain
[186]640        IF (.NOT. assigned_domain(ind)) CYCLE
[26]641        CALL swap_dimensions(ind)
642        CALL swap_geometry(ind)
643        due=f_due(ind) 
[151]644        CALL compute_gradrot(due,due,ll_begin,ll_end)
[15]645      ENDDO
646
[26]647    ENDDO
[15]648
[145]649    CALL trace_end("gradrot")
650
[26]651  END SUBROUTINE gradrot
652 
653  SUBROUTINE divgrad(f_theta,f_dtheta)
654  USE icosa
[145]655  USE trace
[151]656  USE omp_para
[26]657  IMPLICIT NONE
658    TYPE(t_field),POINTER :: f_theta(:)
659    TYPE(t_field),POINTER :: f_dtheta(:)
660    REAL(rstd),POINTER    :: theta(:,:)
661    REAL(rstd),POINTER    :: dtheta(:,:)
662    INTEGER :: ind
663    INTEGER :: it
[145]664
665    CALL trace_start("divgrad")
[26]666       
667    DO ind=1,ndomain
[186]668      IF (.NOT. assigned_domain(ind)) CYCLE
[26]669      CALL swap_dimensions(ind)
670      CALL swap_geometry(ind)
671      theta=f_theta(ind)
672      dtheta=f_dtheta(ind) 
673      dtheta=theta
674    ENDDO
[15]675
[26]676    DO it=1,niterdivgrad
677       
678      CALL transfert_request(f_dtheta,req_i1)
679       
680      DO ind=1,ndomain
[186]681        IF (.NOT. assigned_domain(ind)) CYCLE
[26]682        CALL swap_dimensions(ind)
683        CALL swap_geometry(ind)
684        dtheta=f_dtheta(ind) 
[151]685        CALL compute_divgrad(dtheta,dtheta,ll_begin,ll_end)
[26]686      ENDDO
[15]687
[26]688    ENDDO
689
[145]690    CALL trace_end("divgrad")
691
[26]692  END SUBROUTINE divgrad
693   
[167]694  SUBROUTINE divgrad_theta_rhodz(f_mass,f_theta_rhodz,f_dtheta_rhodz)
[151]695  USE icosa
696  USE trace
697  USE omp_para
698  IMPLICIT NONE
[167]699    TYPE(t_field),POINTER :: f_mass(:)
[151]700    TYPE(t_field),POINTER :: f_theta_rhodz(:)
701    TYPE(t_field),POINTER :: f_dtheta_rhodz(:)
702   
[167]703    REAL(rstd),POINTER :: mass(:,:)
[151]704    REAL(rstd),POINTER :: theta_rhodz(:,:)
705    REAL(rstd),POINTER :: dtheta_rhodz(:,:)
[26]706
[151]707    INTEGER :: ind
[174]708    INTEGER :: it,l,ij
[151]709
710    CALL trace_start("divgrad")
711       
712    DO ind=1,ndomain
[186]713      IF (.NOT. assigned_domain(ind)) CYCLE
[151]714      CALL swap_dimensions(ind)
715      CALL swap_geometry(ind)
[167]716      mass=f_mass(ind)
[151]717      theta_rhodz=f_theta_rhodz(ind)
718      dtheta_rhodz=f_dtheta_rhodz(ind) 
719      DO  l = ll_begin, ll_end
[174]720!$SIMD
721        DO ij=ij_begin,ij_end
[167]722            dtheta_rhodz(ij,l) = theta_rhodz(ij,l) / mass(ij,l)
[151]723        ENDDO
724      ENDDO
725    ENDDO
726
727    DO it=1,niterdivgrad
728       
729      CALL send_message(f_dtheta_rhodz,req_dtheta)
730      CALL wait_message(req_dtheta)
731      DO ind=1,ndomain
[186]732        IF (.NOT. assigned_domain(ind)) CYCLE
[151]733        CALL swap_dimensions(ind)
734        CALL swap_geometry(ind)
735        dtheta_rhodz=f_dtheta_rhodz(ind) 
736        CALL compute_divgrad(dtheta_rhodz,dtheta_rhodz,ll_begin,ll_end)
737      ENDDO
738
739    ENDDO
740
741    DO ind=1,ndomain
[186]742      IF (.NOT. assigned_domain(ind)) CYCLE
[151]743      CALL swap_dimensions(ind)
744      CALL swap_geometry(ind)
745      dtheta_rhodz=f_dtheta_rhodz(ind) 
[175]746      mass=f_mass(ind)
[151]747   
748      DO  l = ll_begin, ll_end
[174]749!$SIMD
750        DO ij=ij_begin,ij_end
[167]751            dtheta_rhodz(ij,l) = dtheta_rhodz(ij,l) * mass(ij,l)
[151]752        ENDDO
753      ENDDO
754    ENDDO
755
756
757    CALL trace_end("divgrad")
758
759  END SUBROUTINE divgrad_theta_rhodz 
[15]760 
[151]761  SUBROUTINE compute_gradiv(ue,gradivu_e,llb,lle)
[19]762  USE icosa
[15]763  IMPLICIT NONE
[151]764    INTEGER,INTENT(IN)     :: llb
765    INTEGER,INTENT(IN)     :: lle
766    REAL(rstd),INTENT(IN)  :: ue(iim*3*jjm,llm)
767    REAL(rstd),INTENT(OUT) :: gradivu_e(iim*3*jjm,llm)
768    REAL(rstd) :: divu_i(iim*jjm,llb:lle)
[15]769   
[174]770    INTEGER :: ij,l
[15]771
[151]772    DO l=llb,lle
[174]773!$SIMD
774      DO ij=ij_begin,ij_end
775          divu_i(ij,l)=1./Ai(ij)*(ne(ij,right)*ue(ij+u_right,l)*le(ij+u_right)  +  &
776                             ne(ij,rup)*ue(ij+u_rup,l)*le(ij+u_rup)        +  & 
777                             ne(ij,lup)*ue(ij+u_lup,l)*le(ij+u_lup)        +  & 
778                             ne(ij,left)*ue(ij+u_left,l)*le(ij+u_left)     +  & 
779                             ne(ij,ldown)*ue(ij+u_ldown,l)*le(ij+u_ldown)  +  & 
780                             ne(ij,rdown)*ue(ij+u_rdown,l)*le(ij+u_rdown))
[15]781      ENDDO
782    ENDDO
783   
[151]784    DO l=llb,lle
[174]785!$SIMD
786      DO ij=ij_begin,ij_end
[15]787 
[174]788          gradivu_e(ij+u_right,l)=-1/de(ij+u_right)*(ne(ij,right)*divu_i(ij,l)+ ne(ij+t_right,left)*divu_i(ij+t_right,l) )       
[15]789
[174]790          gradivu_e(ij+u_lup,l)=-1/de(ij+u_lup)*(ne(ij,lup)*divu_i(ij,l)+ ne(ij+t_lup,rdown)*divu_i(ij+t_lup,l))       
[15]791   
[174]792          gradivu_e(ij+u_ldown,l)=-1/de(ij+u_ldown)*(ne(ij,ldown)*divu_i(ij,l)+ne(ij+t_ldown,rup)*divu_i(ij+t_ldown,l) )
[15]793
794      ENDDO
795    ENDDO
796
[151]797    DO l=llb,lle
[174]798!$SIMD
799      DO ij=ij_begin,ij_end
800          gradivu_e(ij+u_right,l)=-gradivu_e(ij+u_right,l)*cgraddiv
801          gradivu_e(ij+u_lup,l)=-gradivu_e(ij+u_lup,l)*cgraddiv
802          gradivu_e(ij+u_ldown,l)=-gradivu_e(ij+u_ldown,l)*cgraddiv
[15]803      ENDDO
804    ENDDO
805
[148]806   
[26]807  END SUBROUTINE compute_gradiv
[15]808 
[151]809  SUBROUTINE compute_divgrad(theta,divgrad_i,llb,lle)
[19]810  USE icosa
[15]811  IMPLICIT NONE
[151]812    INTEGER,INTENT(IN)     :: llb
813    INTEGER,INTENT(IN)     :: lle
814    REAL(rstd),INTENT(IN)  :: theta(iim*jjm,llm)
815    REAL(rstd),INTENT(OUT) :: divgrad_i(iim*jjm,llm)
816    REAL(rstd)  :: grad_e(3*iim*jjm,llb:lle)
[15]817
[174]818    INTEGER :: ij,l
[15]819
[148]820       
[151]821    DO l=llb,lle
[174]822!$SIMD
823      DO ij=ij_begin_ext,ij_end_ext
[15]824 
[174]825          grad_e(ij+u_right,l)=-1/de(ij+u_right)*(ne(ij,right)*theta(ij,l)+ ne(ij+t_right,left)*theta(ij+t_right,l) )       
[15]826
[174]827          grad_e(ij+u_lup,l)=-1/de(ij+u_lup)*(ne(ij,lup)*theta(ij,l)+ ne(ij+t_lup,rdown)*theta(ij+t_lup,l ))       
[15]828   
[174]829          grad_e(ij+u_ldown,l)=-1/de(ij+u_ldown)*(ne(ij,ldown)*theta(ij,l)+ne(ij+t_ldown,rup)*theta(ij+t_ldown,l) )
[15]830
831      ENDDO
832    ENDDO
833   
834   
[151]835    DO l=llb,lle
[174]836!$SIMD
[175]837      DO ij=ij_begin,ij_end
[174]838
839          divgrad_i(ij,l)=1./Ai(ij)*(ne(ij,right)*grad_e(ij+u_right,l)*le(ij+u_right)  +  &
840                             ne(ij,rup)*grad_e(ij+u_rup,l)*le(ij+u_rup)              +  & 
841                             ne(ij,lup)*grad_e(ij+u_lup,l)*le(ij+u_lup)              +  & 
842                             ne(ij,left)*grad_e(ij+u_left,l)*le(ij+u_left)           +  & 
843                             ne(ij,ldown)*grad_e(ij+u_ldown,l)*le(ij+u_ldown)        +  & 
844                             ne(ij,rdown)*grad_e(ij+u_rdown,l)*le(ij+u_rdown))
[15]845      ENDDO
846    ENDDO
847   
[151]848    DO l=llb,lle
[174]849      DO ij=ij_begin,ij_end
850          divgrad_i(ij,l)=-divgrad_i(ij,l)*cdivgrad
[15]851      ENDDO
852    ENDDO
853
[26]854  END SUBROUTINE compute_divgrad
[15]855
856   
[151]857  SUBROUTINE compute_gradrot(ue,gradrot_e,llb,lle)
[19]858  USE icosa
[15]859  IMPLICIT NONE
[151]860    INTEGER,INTENT(IN)     :: llb
861    INTEGER,INTENT(IN)     :: lle
862    REAL(rstd),INTENT(IN)  :: ue(iim*3*jjm,llm)
863    REAL(rstd),INTENT(OUT) :: gradrot_e(iim*3*jjm,llm)
864    REAL(rstd) :: rot_v(2*iim*jjm,llb:lle)
[15]865
[174]866    INTEGER :: ij,l
[15]867     
[151]868    DO l=llb,lle
[174]869!$SIMD
870      DO ij=ij_begin_ext,ij_end_ext
[15]871       
[174]872          rot_v(ij+z_up,l)= 1./Av(ij+z_up)*(  ne(ij,rup)*ue(ij+u_rup,l)*de(ij+u_rup)                     &
873                                + ne(ij+t_rup,left)*ue(ij+t_rup+u_left,l)*de(ij+t_rup+u_left)          &
874                                - ne(ij,lup)*ue(ij+u_lup,l)*de(ij+u_lup) ) 
[15]875                             
[174]876          rot_v(ij+z_down,l) = 1./Av(ij+z_down)*( ne(ij,ldown)*ue(ij+u_ldown,l)*de(ij+u_ldown)                 &
877                                     + ne(ij+t_ldown,right)*ue(ij+t_ldown+u_right,l)*de(ij+t_ldown+u_right)  &
878                                     - ne(ij,rdown)*ue(ij+u_rdown,l)*de(ij+u_rdown) )
[15]879 
880      ENDDO
881    ENDDO                             
882 
[151]883    DO l=llb,lle
[174]884!$SIMD
885      DO ij=ij_begin,ij_end
[15]886 
[174]887          gradrot_e(ij+u_right,l)=1/le(ij+u_right)*ne(ij,right)*(rot_v(ij+z_rdown,l)-rot_v(ij+z_rup,l)) 
[15]888         
[174]889          gradrot_e(ij+u_lup,l)=1/le(ij+u_lup)*ne(ij,lup)*(rot_v(ij+z_up,l)-rot_v(ij+z_lup,l)) 
[15]890       
[174]891          gradrot_e(ij+u_ldown,l)=1/le(ij+u_ldown)*ne(ij,ldown)*(rot_v(ij+z_ldown,l)-rot_v(ij+z_down,l))
[15]892       
893      ENDDO
894    ENDDO
895
[151]896    DO l=llb,lle
[174]897!$SIMD
898      DO ij=ij_begin,ij_end
[15]899   
[174]900          gradrot_e(ij+u_right,l)=-gradrot_e(ij+u_right,l)*cgradrot       
901          gradrot_e(ij+u_lup,l)=-gradrot_e(ij+u_lup,l)*cgradrot
902          gradrot_e(ij+u_ldown,l)=-gradrot_e(ij+u_ldown,l)*cgradrot
[15]903       
904      ENDDO
905    ENDDO 
906   
[26]907  END SUBROUTINE compute_gradrot
[15]908
909
910END MODULE dissip_gcm_mod
911       
Note: See TracBrowser for help on using the repository browser.