source: codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM/src/dissip_gcm.f90 @ 221

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

Creating temporary dynamico/lmdz/saturn branche

YM

File size: 25.5 KB
Line 
1MODULE dissip_gcm_mod
2  USE icosa
3
4  PRIVATE
5
6  TYPE(t_field),POINTER,SAVE :: f_due_diss1(:)
7  TYPE(t_field),POINTER,SAVE :: f_due_diss2(:)
8
9  TYPE(t_field),POINTER,SAVE :: f_theta(:), f_phi(:), f_pk(:), f_pks(:), f_p(:)
10  TYPE(t_field),POINTER,SAVE :: f_dtheta_diss(:)
11  TYPE(t_field),POINTER,SAVE :: f_dtheta_rhodz_diss(:)
12  TYPE(t_message),SAVE :: req_due, req_dtheta 
13 
14  INTEGER,SAVE :: nitergdiv=1
15!$OMP THREADPRIVATE(nitergdiv)
16  INTEGER,SAVE :: nitergrot=1
17!$OMP THREADPRIVATE(nitergrot)
18  INTEGER,SAVE :: niterdivgrad=1
19!$OMP THREADPRIVATE(niterdivgrad)
20
21  REAL,ALLOCATABLE,SAVE :: tau_graddiv(:)
22!$OMP THREADPRIVATE(tau_graddiv)
23  REAL,ALLOCATABLE,SAVE :: tau_gradrot(:)
24!$OMP THREADPRIVATE(tau_gradrot)
25  REAL,ALLOCATABLE,SAVE :: tau_divgrad(:)
26!$OMP THREADPRIVATE(tau_divgrad)
27 
28  REAL,SAVE :: cgraddiv
29!$OMP THREADPRIVATE(cgraddiv)
30  REAL,SAVE :: cgradrot
31!$OMP THREADPRIVATE(cgradrot)
32  REAL,SAVE :: cdivgrad
33!$OMP THREADPRIVATE(cdivgrad)
34
35  INTEGER, SAVE :: rayleigh_friction_type, rayleigh_shear
36!$OMP THREADPRIVATE(rayleigh_friction_type)
37  REAL, SAVE    :: rayleigh_tau
38!$OMP THREADPRIVATE(rayleigh_shear)
39 
40  REAL,SAVE    :: dtdissip
41!$OMP THREADPRIVATE(dtdissip)
42 
43  PUBLIC init_dissip, dissip
44CONTAINS
45
46  SUBROUTINE allocate_dissip
47  USE icosa
48  IMPLICIT NONE 
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)
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)
59   
60    ALLOCATE(tau_graddiv(llm))
61    ALLOCATE(tau_gradrot(llm))   
62    ALLOCATE(tau_divgrad(llm))
63  END SUBROUTINE allocate_dissip
64 
65  SUBROUTINE init_dissip
66  USE icosa
67  USE disvert_mod
68  USE mpi_mod
69  USE mpipara
70  USE transfert_mod
71  USE time_mod
72  USE transfert_omp_mod
73  IMPLICIT NONE
74 
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(:)
81  REAL(rstd),POINTER    :: theta(:)
82  REAL(rstd),POINTER    :: dtheta(:)
83  REAL(rstd)            :: dumax,dumax1
84  REAL(rstd)            :: dthetamax,dthetamax1
85  REAL(rstd)            :: r
86  REAL(rstd)            :: tau
87  REAL(rstd)            :: zz, zvert, fact
88  INTEGER               :: l
89  CHARACTER(len=255)    :: rayleigh_friction_key
90  REAL(rstd)            :: mintau
91  INTEGER               :: seed_size
92  INTEGER,ALLOCATABLE   :: seed(:)
93 
94           
95  INTEGER :: i,j,ij,ind,it,iter
96
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
102      IF (is_mpi_root) PRINT *, 'No Rayleigh friction'
103   CASE('dcmip2_schaer_noshear')
104      rayleigh_friction_type=1
105      rayleigh_shear=0
106      IF (is_mpi_root) PRINT *, 'Rayleigh friction : Schaer-like mountain without shear DCMIP2.1'
107   CASE('dcmip2_schaer_shear')
108      rayleigh_shear=1
109      rayleigh_friction_type=2
110      IF (is_mpi_root) PRINT *, 'Rayleigh friction : Schaer-like mountain with shear DCMIP2.2'
111   CASE DEFAULT
112      IF (is_mpi_root) PRINT *, 'Bad selector : rayleigh_friction_type =', TRIM(rayleigh_friction_key), ' in dissip_gcm.f90/init_dissip'
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
121         IF (is_mpi_root) PRINT *, 'Forbidden : negative value for rayleigh_friction_tau =',rayleigh_tau
122         STOP
123      END IF
124   END IF
125
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)
131   
132    CALL init_message(f_due_diss1,req_e1_vect,req_due)
133    CALL init_message(f_dtheta_diss,req_i1,req_dtheta)
134
135    tau_graddiv(:)=5000
136    CALL getin("tau_graddiv",tau)
137    tau_graddiv(:)=tau/scale_factor
138
139    CALL getin("nitergdiv",nitergdiv)
140   
141    tau_gradrot(:)=5000
142    CALL getin("tau_gradrot",tau)
143    tau_gradrot(:)=tau/scale_factor
144
145    CALL getin("nitergrot",nitergrot)
146   
147
148    tau_divgrad(:)=5000
149    CALL getin("tau_divgrad",tau)
150    tau_divgrad(:)=tau/scale_factor
151
152    CALL getin("niterdivgrad",niterdivgrad)
153
154
155    cgraddiv=-1
156    cdivgrad=-1
157    cgradrot=-1
158   
159    DO ind=1,ndomain
160      IF (.NOT. assigned_domain(ind)) CYCLE
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
167          ij=(j-1)*iim+i   
168          CALL RANDOM_NUMBER(r)
169          u(ij+u_right)=r-0.5
170          CALL RANDOM_NUMBER(r)
171          u(ij+u_lup)=r-0.5
172          CALL RANDOM_NUMBER(r)
173          u(ij+u_ldown)=r-0.5
174        ENDDO
175      ENDDO       
176    ENDDO
177 
178
179
180    DO it=1,20
181     
182      dumax=0
183      DO iter=1,nitergdiv
184        CALL transfert_request(f_u,req_e1_vect)
185        DO ind=1,ndomain
186          IF (.NOT. assigned_domain(ind)) CYCLE
187          CALL swap_dimensions(ind)
188          CALL swap_geometry(ind)
189          u=f_u(ind)
190          du=f_du(ind)
191          CALL compute_gradiv(u,du,1,1)
192          u=du
193        ENDDO
194      ENDDO
195
196      CALL transfert_request(f_du,req_e1_vect)
197     
198      DO ind=1,ndomain
199        IF (.NOT. assigned_domain(ind)) CYCLE
200        CALL swap_dimensions(ind)
201        CALL swap_geometry(ind)
202        u=f_u(ind)
203        du=f_du(ind)
204         
205        DO j=jj_begin,jj_end
206          DO i=ii_begin,ii_end
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)))
211          ENDDO
212        ENDDO
213      ENDDO
214
215      IF (using_mpi) THEN
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)
223        dumax=dumax1
224      ENDIF 
225                       
226      DO ind=1,ndomain
227        IF (.NOT. assigned_domain(ind)) CYCLE
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
234      IF (is_mpi_root) PRINT *,"gradiv : it :",it ,": dumax",dumax
235
236    ENDDO 
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)
242
243    cgraddiv=dumax**(-1./nitergdiv)
244    IF (is_mpi_root) PRINT *,"cgraddiv : ",cgraddiv
245
246    DO ind=1,ndomain
247      IF (.NOT. assigned_domain(ind)) CYCLE
248      CALL swap_dimensions(ind)
249      CALL swap_geometry(ind)
250      u=f_u(ind)
251
252      DO j=jj_begin,jj_end
253        DO i=ii_begin,ii_end
254          ij=(j-1)*iim+i   
255          CALL RANDOM_NUMBER(r)
256          u(ij+u_right)=r-0.5
257          CALL RANDOM_NUMBER(r)
258          u(ij+u_lup)=r-0.5
259          CALL RANDOM_NUMBER(r)
260          u(ij+u_ldown)=r-0.5
261        ENDDO
262      ENDDO       
263    ENDDO
264
265
266    DO it=1,20
267 
268      dumax=0
269      DO iter=1,nitergrot
270        CALL transfert_request(f_u,req_e1_vect)
271        DO ind=1,ndomain
272          IF (.NOT. assigned_domain(ind)) CYCLE
273          CALL swap_dimensions(ind)
274          CALL swap_geometry(ind)
275          u=f_u(ind)
276          du=f_du(ind)
277          CALL compute_gradrot(u,du,1,1)
278          u=du
279        ENDDO
280      ENDDO
281
282      CALL transfert_request(f_du,req_e1_vect)
283     
284      DO ind=1,ndomain
285        IF (.NOT. assigned_domain(ind)) CYCLE
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
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)))
297          ENDDO
298        ENDDO
299      ENDDO
300
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)
309        dumax=dumax1
310      ENDIF 
311
312     
313      DO ind=1,ndomain
314        IF (.NOT. assigned_domain(ind)) CYCLE
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     
322      IF (is_mpi_root) PRINT *,"gradrot : it :",it ,": dumax",dumax
323
324    ENDDO 
325    IF (is_mpi_root) PRINT *,"gradrot : dumax",dumax
326 
327    cgradrot=dumax**(-1./nitergrot) 
328    IF (is_mpi_root) PRINT *,"cgradrot : ",cgradrot
329   
330
331
332    DO ind=1,ndomain
333      IF (.NOT. assigned_domain(ind)) CYCLE
334      CALL swap_dimensions(ind)
335      CALL swap_geometry(ind)
336      theta=f_theta(ind)
337 
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
343        ENDDO
344      ENDDO 
345    ENDDO
346
347    DO it=1,20
348
349      dthetamax=0
350      DO iter=1,niterdivgrad
351        CALL transfert_request(f_theta,req_i1)
352        DO ind=1,ndomain
353          IF (.NOT. assigned_domain(ind)) CYCLE
354          CALL swap_dimensions(ind)
355          CALL swap_geometry(ind)
356          theta=f_theta(ind)
357          dtheta=f_dtheta(ind)
358          CALL compute_divgrad(theta,dtheta,1,1)
359          theta=dtheta
360        ENDDO
361      ENDDO
362
363      CALL transfert_request(f_dtheta,req_i1)
364     
365      DO ind=1,ndomain
366        IF (.NOT. assigned_domain(ind)) CYCLE
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
374            ij=(j-1)*iim+i   
375            dthetamax=MAX(dthetamax,ABS(dtheta(ij)))
376          ENDDO
377        ENDDO
378      ENDDO
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 
390     
391      IF (is_mpi_root) PRINT *,"divgrad : it :",it ,": dthetamax",dthetamax
392
393      DO ind=1,ndomain
394        IF (.NOT. assigned_domain(ind)) CYCLE
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
403    IF (is_mpi_root) PRINT *,"divgrad : divgrad",dthetamax
404 
405    cdivgrad=dthetamax**(-1./niterdivgrad) 
406    IF (is_mpi_root) PRINT *,"cdivgrad : ",cdivgrad
407
408     
409    fact=2
410    DO l=1,llm
411       IF(ap_bp_present) THEN ! height-dependent dissipation
412          zz= 1. - preff/presnivs(l)
413       ELSE
414          zz = 0.
415       END IF
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
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
428       
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
433
434  END SUBROUTINE init_dissip 
435 
436 
437  SUBROUTINE dissip(f_ue,f_due,f_mass,f_phis,f_theta_rhodz,f_dtheta_rhodz)
438  USE icosa
439  USE theta2theta_rhodz_mod
440  USE pression_mod
441  USE exner_mod
442  USE geopotential_mod
443  USE trace
444  USE time_mod
445  USE omp_para
446  IMPLICIT NONE
447    TYPE(t_field),POINTER :: f_ue(:)
448    TYPE(t_field),POINTER :: f_due(:)
449    TYPE(t_field),POINTER :: f_mass(:), f_phis(:)
450    TYPE(t_field),POINTER :: f_theta_rhodz(:)
451    TYPE(t_field),POINTER :: f_dtheta_rhodz(:)
452
453    REAL(rstd),POINTER         :: due(:,:)
454    REAL(rstd),POINTER         :: phi(:,:), ue(:,:)
455    REAL(rstd),POINTER         :: due_diss1(:,:)
456    REAL(rstd),POINTER         :: due_diss2(:,:)
457    REAL(rstd),POINTER         :: dtheta_rhodz(:,:)
458    REAL(rstd),POINTER         :: dtheta_rhodz_diss(:,:)
459
460    INTEGER :: ind, shear
461    INTEGER :: l,ij
462
463!$OMP BARRIER
464   
465    CALL trace_start("dissip")
466    CALL gradiv(f_ue,f_due_diss1)
467    CALL gradrot(f_ue,f_due_diss2)
468
469    CALL divgrad_theta_rhodz(f_mass,f_theta_rhodz,f_dtheta_rhodz_diss)
470   
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
477
478    DO ind=1,ndomain
479      IF (.NOT. assigned_domain(ind)) CYCLE
480      CALL swap_dimensions(ind)
481      CALL swap_geometry(ind)
482      due=f_due(ind) 
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)
487
488      DO l=ll_begin,ll_end
489!$SIMD
490        DO ij=ij_begin,ij_end
491
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
495
496            dtheta_rhodz(ij,l) = -0.5*dtheta_rhodz_diss(ij,l)/tau_divgrad(l)*itau_dissip
497        ENDDO
498      ENDDO
499
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
518   END DO
519
520   CALL trace_end("dissip")
521
522!$OMP BARRIER
523
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
533        z = (phi(ij,l)+phi(ij+shift_t,l))/(2.*g)
534        IF(z>zh) THEN  ! relax only in the sponge layer z>zh
535
536           nn = ij+shift_u
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
552     
553  END SUBROUTINE dissip
554
555  SUBROUTINE gradiv(f_ue,f_due)
556  USE icosa
557  USE trace
558  USE omp_para
559  IMPLICIT NONE
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
565    INTEGER :: it,l,ij
566       
567    CALL trace_start("gradiv")
568
569    DO ind=1,ndomain
570      IF (.NOT. assigned_domain(ind)) CYCLE
571      CALL swap_dimensions(ind)
572      CALL swap_geometry(ind)
573      ue=f_ue(ind)
574      due=f_due(ind) 
575      DO  l = ll_begin, ll_end
576!$SIMD
577        DO ij=ij_begin,ij_end
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
583    ENDDO
584
585    DO it=1,nitergdiv
586       
587      CALL send_message(f_due,req_due)
588      CALL wait_message(req_due)
589       
590      DO ind=1,ndomain
591        IF (.NOT. assigned_domain(ind)) CYCLE
592        CALL swap_dimensions(ind)
593        CALL swap_geometry(ind)
594        due=f_due(ind) 
595        CALL compute_gradiv(due,due,ll_begin,ll_end)
596      ENDDO
597    ENDDO
598
599   CALL trace_end("gradiv")
600
601  END SUBROUTINE gradiv
602 
603
604  SUBROUTINE gradrot(f_ue,f_due)
605  USE icosa
606  USE trace
607  USE omp_para
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(:,:)
613    INTEGER :: ind
614    INTEGER :: it,l,ij
615       
616    CALL trace_start("gradrot")
617
618    DO ind=1,ndomain
619      IF (.NOT. assigned_domain(ind)) CYCLE
620      CALL swap_dimensions(ind)
621      CALL swap_geometry(ind)
622      ue=f_ue(ind)
623      due=f_due(ind) 
624      DO  l = ll_begin, ll_end
625!$SIMD
626        DO ij=ij_begin,ij_end
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
632    ENDDO
633
634    DO it=1,nitergrot
635       
636      CALL send_message(f_due,req_due)
637      CALL wait_message(req_due)
638       
639      DO ind=1,ndomain
640        IF (.NOT. assigned_domain(ind)) CYCLE
641        CALL swap_dimensions(ind)
642        CALL swap_geometry(ind)
643        due=f_due(ind) 
644        CALL compute_gradrot(due,due,ll_begin,ll_end)
645      ENDDO
646
647    ENDDO
648
649    CALL trace_end("gradrot")
650
651  END SUBROUTINE gradrot
652 
653  SUBROUTINE divgrad(f_theta,f_dtheta)
654  USE icosa
655  USE trace
656  USE omp_para
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
664
665    CALL trace_start("divgrad")
666       
667    DO ind=1,ndomain
668      IF (.NOT. assigned_domain(ind)) CYCLE
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
675
676    DO it=1,niterdivgrad
677       
678      CALL transfert_request(f_dtheta,req_i1)
679       
680      DO ind=1,ndomain
681        IF (.NOT. assigned_domain(ind)) CYCLE
682        CALL swap_dimensions(ind)
683        CALL swap_geometry(ind)
684        dtheta=f_dtheta(ind) 
685        CALL compute_divgrad(dtheta,dtheta,ll_begin,ll_end)
686      ENDDO
687
688    ENDDO
689
690    CALL trace_end("divgrad")
691
692  END SUBROUTINE divgrad
693   
694  SUBROUTINE divgrad_theta_rhodz(f_mass,f_theta_rhodz,f_dtheta_rhodz)
695  USE icosa
696  USE trace
697  USE omp_para
698  IMPLICIT NONE
699    TYPE(t_field),POINTER :: f_mass(:)
700    TYPE(t_field),POINTER :: f_theta_rhodz(:)
701    TYPE(t_field),POINTER :: f_dtheta_rhodz(:)
702   
703    REAL(rstd),POINTER :: mass(:,:)
704    REAL(rstd),POINTER :: theta_rhodz(:,:)
705    REAL(rstd),POINTER :: dtheta_rhodz(:,:)
706
707    INTEGER :: ind
708    INTEGER :: it,l,ij
709
710    CALL trace_start("divgrad")
711       
712    DO ind=1,ndomain
713      IF (.NOT. assigned_domain(ind)) CYCLE
714      CALL swap_dimensions(ind)
715      CALL swap_geometry(ind)
716      mass=f_mass(ind)
717      theta_rhodz=f_theta_rhodz(ind)
718      dtheta_rhodz=f_dtheta_rhodz(ind) 
719      DO  l = ll_begin, ll_end
720!$SIMD
721        DO ij=ij_begin,ij_end
722            dtheta_rhodz(ij,l) = theta_rhodz(ij,l) / mass(ij,l)
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
732        IF (.NOT. assigned_domain(ind)) CYCLE
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
742      IF (.NOT. assigned_domain(ind)) CYCLE
743      CALL swap_dimensions(ind)
744      CALL swap_geometry(ind)
745      dtheta_rhodz=f_dtheta_rhodz(ind) 
746      mass=f_mass(ind)
747   
748      DO  l = ll_begin, ll_end
749!$SIMD
750        DO ij=ij_begin,ij_end
751            dtheta_rhodz(ij,l) = dtheta_rhodz(ij,l) * mass(ij,l)
752        ENDDO
753      ENDDO
754    ENDDO
755
756
757    CALL trace_end("divgrad")
758
759  END SUBROUTINE divgrad_theta_rhodz 
760 
761  SUBROUTINE compute_gradiv(ue,gradivu_e,llb,lle)
762  USE icosa
763  IMPLICIT NONE
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)
769   
770    INTEGER :: ij,l
771
772    DO l=llb,lle
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))
781      ENDDO
782    ENDDO
783   
784    DO l=llb,lle
785!$SIMD
786      DO ij=ij_begin,ij_end
787 
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) )       
789
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))       
791   
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) )
793
794      ENDDO
795    ENDDO
796
797    DO l=llb,lle
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
803      ENDDO
804    ENDDO
805
806   
807  END SUBROUTINE compute_gradiv
808 
809  SUBROUTINE compute_divgrad(theta,divgrad_i,llb,lle)
810  USE icosa
811  IMPLICIT NONE
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)
817
818    INTEGER :: ij,l
819
820       
821    DO l=llb,lle
822!$SIMD
823      DO ij=ij_begin_ext,ij_end_ext
824 
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) )       
826
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 ))       
828   
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) )
830
831      ENDDO
832    ENDDO
833   
834   
835    DO l=llb,lle
836!$SIMD
837      DO ij=ij_begin,ij_end
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))
845      ENDDO
846    ENDDO
847   
848    DO l=llb,lle
849      DO ij=ij_begin,ij_end
850          divgrad_i(ij,l)=-divgrad_i(ij,l)*cdivgrad
851      ENDDO
852    ENDDO
853
854  END SUBROUTINE compute_divgrad
855
856   
857  SUBROUTINE compute_gradrot(ue,gradrot_e,llb,lle)
858  USE icosa
859  IMPLICIT NONE
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)
865
866    INTEGER :: ij,l
867     
868    DO l=llb,lle
869!$SIMD
870      DO ij=ij_begin_ext,ij_end_ext
871       
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) ) 
875                             
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) )
879 
880      ENDDO
881    ENDDO                             
882 
883    DO l=llb,lle
884!$SIMD
885      DO ij=ij_begin,ij_end
886 
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)) 
888         
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)) 
890       
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))
892       
893      ENDDO
894    ENDDO
895
896    DO l=llb,lle
897!$SIMD
898      DO ij=ij_begin,ij_end
899   
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
903       
904      ENDDO
905    ENDDO 
906   
907  END SUBROUTINE compute_gradrot
908
909
910END MODULE dissip_gcm_mod
911       
Note: See TracBrowser for help on using the repository browser.