source: codes/icosagcm/trunk/src/time/euler_scheme.F90 @ 1004

Last change on this file since 1004 was 953, checked in by adurocher, 5 years ago

trunk : GPU implementation with OpenACC ( merge from glcp.idris.fr )

File size: 8.4 KB
RevLine 
[360]1MODULE euler_scheme_mod
2  USE field_mod
[953]3  USE abort_mod
[360]4  IMPLICIT NONE
5  PRIVATE
6
7  TYPE(t_field),POINTER,SAVE,PUBLIC :: f_geopot(:), f_q(:), &
[366]8       f_rhodz(:), f_mass(:), f_massm1(:), f_massm2(:), f_dmass(:), & ! current and previous time steps + tendency of mass,
9       f_phis(:), f_ps(:),f_psm1(:), f_psm2(:), f_dps(:), &           ! column-integrated mass
10       f_u(:),f_um1(:),f_um2(:), f_du(:), f_W(:), &                   ! 'horizontal' and vertical (NH) momentum
11       f_theta_rhodz(:),f_theta_rhodzm1(:),f_theta_rhodzm2(:), f_dtheta_rhodz(:), & ! mass-weighted theta/entropy
12       f_hflux(:), f_wflux(:), f_hfluxt(:), f_wfluxt(:), &            ! accumulated mass fluxes
13       f_du_slow(:,:), f_du_fast(:,:), &                              ! slow/fast trend arrays
14       f_dmass_slow(:,:), f_dps_slow(:,:), f_dtheta_rhodz_slow(:,:), &! for HEVI time scheme
15       f_dPhi_slow(:,:), f_dPhi_fast(:,:), &                          ! geopotential tendencies (NH)
16       f_dW_slow(:,:), f_dW_fast(:,:)                                 ! vertical momentum tendencies (NH)
[360]17
18  INTEGER, PARAMETER, PUBLIC :: explicit=1, hevi=2, euler=1, rk4=2, mlf=3, rk25=4, ark23=6, ark33=7
19
20  INTEGER,SAVE, PUBLIC :: nb_stage, matsuno_period, scheme, scheme_family
21  !$OMP THREADPRIVATE(nb_stage, matsuno_period, scheme, scheme_family)
22
[362]23  PUBLIC :: euler_scheme, accumulate_fluxes, legacy_to_DEC, DEC_to_legacy
[360]24CONTAINS
25
26  SUBROUTINE Euler_scheme(with_dps,fluxt_zero)
27    USE icosa
28    USE disvert_mod
29    USE omp_para
30    USE trace
31    LOGICAL :: with_dps
32    LOGICAL, OPTIONAL :: fluxt_zero(ndomain) ! set to .TRUE. to start accumulating fluxes in time
33    REAL(rstd),POINTER :: ps(:), dps(:)
34    REAL(rstd),POINTER :: u(:,:) , du(:,:)
35    REAL(rstd),POINTER :: mass(:,:), dmass(:,:)
[387]36    REAL(rstd),POINTER :: theta_rhodz(:,:,:), dtheta_rhodz(:,:,:)
[360]37    REAL(rstd),POINTER :: hflux(:,:),wflux(:,:),hfluxt(:,:),wfluxt(:,:)
38    INTEGER :: ind
[899]39    INTEGER :: ij,l
[360]40    CALL trace_start("Euler_scheme") 
41
42    DO ind=1,ndomain
43       IF (.NOT. assigned_domain(ind)) CYCLE
44       CALL swap_dimensions(ind)
45       CALL swap_geometry(ind)
46
47       IF(with_dps) THEN ! update ps/mass
[953]48          CALL abort_acc("Euler_scheme/with_dps")
[360]49          IF(caldyn_eta==eta_mass) THEN ! update ps
50             ps=f_ps(ind) ; dps=f_dps(ind) ;             
51             IF (is_omp_first_level) THEN
[487]52                !DIR$ SIMD
[360]53                DO ij=ij_begin,ij_end
54                   ps(ij)=ps(ij)+dt*dps(ij)
55                ENDDO
56             ENDIF
57          ELSE ! update mass
58             mass=f_mass(ind) ; dmass=f_dmass(ind) ;             
59             DO l=ll_begin,ll_end
[487]60                !DIR$ SIMD
[360]61                DO ij=ij_begin,ij_end
62                   mass(ij,l)=mass(ij,l)+dt*dmass(ij,l)
63                ENDDO
64             END DO
65          END IF
66
67          hflux=f_hflux(ind);     hfluxt=f_hfluxt(ind)
68          wflux=f_wflux(ind);     wfluxt=f_wfluxt(ind)
69          CALL accumulate_fluxes(hflux,wflux,hfluxt,wfluxt,dt,fluxt_zero(ind))
70       END IF ! update ps/mass
71
72       u=f_u(ind) ; theta_rhodz=f_theta_rhodz(ind)
73       du=f_du(ind) ; dtheta_rhodz=f_dtheta_rhodz(ind)
74
[953]75       CALL compute_euler_scheme(u, du, theta_rhodz, dtheta_rhodz)
76    ENDDO
77
78    CALL trace_end("Euler_scheme")
79
80    CONTAINS
81
82    SUBROUTINE compute_euler_scheme(u, du, theta_rhodz, dtheta_rhodz)
83       REAL(rstd),INTENT(INOUT) :: u(iim*3*jjm,llm)
84       REAL(rstd),INTENT(IN)    :: du(iim*3*jjm,llm)
85       REAL(rstd),INTENT(INOUT) :: theta_rhodz(iim*jjm,llm,nqdyn)
86       REAL(rstd),INTENT(IN)    :: dtheta_rhodz(iim*jjm,llm,nqdyn)
87
88       !$acc data present(theta_rhodz(:,:,:), u(:,:),du(:,:), dtheta_rhodz(:,:,:)) async
89
90       !$acc parallel loop async
[360]91       DO l=ll_begin,ll_end
[953]92          !$acc loop
[487]93          !DIR$ SIMD
[360]94          DO ij=ij_begin,ij_end
95             u(ij+u_right,l)=u(ij+u_right,l)+dt*du(ij+u_right,l)
96             u(ij+u_lup,l)=u(ij+u_lup,l)+dt*du(ij+u_lup,l)
97             u(ij+u_ldown,l)=u(ij+u_ldown,l)+dt*du(ij+u_ldown,l)
[387]98             theta_rhodz(ij,l,1)=theta_rhodz(ij,l,1)+dt*dtheta_rhodz(ij,l,1)
[360]99          ENDDO
100       ENDDO
[953]101       
102       !$acc end data
103    END SUBROUTINE compute_euler_scheme
[360]104
105  END SUBROUTINE Euler_scheme
106
107  SUBROUTINE accumulate_fluxes(hflux,wflux, hfluxt,wfluxt, tau,fluxt_zero)
108    USE dimensions
109    USE omp_para
110    USE disvert_mod
111    IMPLICIT NONE
112    REAL(rstd), INTENT(IN)    :: hflux(3*iim*jjm,llm), wflux(iim*jjm,llm+1)
113    REAL(rstd), INTENT(INOUT) :: hfluxt(3*iim*jjm,llm), wfluxt(iim*jjm,llm+1)
114    REAL(rstd), INTENT(IN) :: tau
115    LOGICAL, INTENT(INOUT) :: fluxt_zero
[899]116    INTEGER :: l,ij
[360]117
[953]118    !$acc data present(hflux(:,:), wflux(:,:), hfluxt(:,:), wfluxt(:,:)) async
119
[360]120    IF(fluxt_zero) THEN
121
122       fluxt_zero=.FALSE.
[953]123       !$acc parallel loop async
[360]124       DO l=ll_begin,ll_end
[953]125          !$acc loop
[487]126          !DIR$ SIMD
[360]127          DO ij=ij_begin_ext,ij_end_ext
128             hfluxt(ij+u_right,l) = tau*hflux(ij+u_right,l)
129             hfluxt(ij+u_lup,l) = tau*hflux(ij+u_lup,l)
130             hfluxt(ij+u_ldown,l) = tau*hflux(ij+u_ldown,l)
131          ENDDO
132       ENDDO
133
134       IF(caldyn_eta==eta_mass) THEN ! no need for vertical fluxes if eta_lag
[953]135          !$acc parallel loop async
[360]136          DO l=ll_begin,ll_endp1
[953]137             !$acc loop
[487]138             !DIR$ SIMD
[360]139             DO ij=ij_begin,ij_end
140                wfluxt(ij,l) = tau*wflux(ij,l)
141             ENDDO
142          ENDDO
143       END IF
144
145    ELSE
[953]146       !$acc parallel loop async
[360]147       DO l=ll_begin,ll_end
[953]148          !$acc loop
[487]149          !DIR$ SIMD
[360]150          DO ij=ij_begin_ext,ij_end_ext
151             hfluxt(ij+u_right,l) = hfluxt(ij+u_right,l)+tau*hflux(ij+u_right,l)
152             hfluxt(ij+u_lup,l) = hfluxt(ij+u_lup,l)+tau*hflux(ij+u_lup,l)
153             hfluxt(ij+u_ldown,l) = hfluxt(ij+u_ldown,l)+tau*hflux(ij+u_ldown,l)
154          ENDDO
155       ENDDO
156
157       IF(caldyn_eta==eta_mass) THEN ! no need for vertical fluxes if eta_lag
[953]158          !$acc parallel loop async
[360]159          DO l=ll_begin,ll_endp1
[953]160             !$acc loop
[487]161             !DIR$ SIMD
[360]162             DO ij=ij_begin,ij_end
163                wfluxt(ij,l) = wfluxt(ij,l)+tau*wflux(ij,l)
164             ENDDO
165          ENDDO
166       END IF
167    END IF
[953]168    !$acc end data
[360]169  END SUBROUTINE accumulate_fluxes
170
[362]171  SUBROUTINE legacy_to_DEC(f_ps, f_u)
172    USE icosa
173    USE disvert_mod
174    USE omp_para
175    USE trace
176    TYPE(t_field),POINTER :: f_ps(:), f_u(:)
177    REAL(rstd), POINTER :: ps(:), u(:,:)
178    INTEGER :: ind,ij,l
[953]179
[362]180    CALL trace_start("legacy_to_DEC")
181
182    DO ind=1,ndomain
183       IF (.NOT. assigned_domain(ind)) CYCLE
184       CALL swap_dimensions(ind)
185       CALL swap_geometry(ind)
186
187       IF(caldyn_eta==eta_mass .AND. is_omp_first_level) THEN ! update ps
188          ps=f_ps(ind)
[953]189          !$acc parallel loop async default(present)
[487]190          !DIR$ SIMD
[362]191          DO ij=ij_begin,ij_end
192             ps(ij)=(ps(ij)-ptop)/g ! convert ps to column-integrated mass
193          ENDDO
194       END IF
195
196       u=f_u(ind)
[953]197       !$acc parallel loop async default(present)
[362]198       DO l=ll_begin,ll_end
[953]199          !$acc loop
[487]200          !DIR$ SIMD
[362]201          DO ij=ij_begin,ij_end
202             u(ij+u_right,l)=u(ij+u_right,l)*de(ij+u_right)
203             u(ij+u_lup,l)=u(ij+u_lup,l)*de(ij+u_lup)
204             u(ij+u_ldown,l)=u(ij+u_ldown,l)*de(ij+u_ldown)
205          ENDDO
206       ENDDO
207    ENDDO
208
209    CALL trace_end("legacy_to_DEC") 
[953]210
[362]211  END SUBROUTINE Legacy_to_DEC
212
213  SUBROUTINE DEC_to_legacy(f_ps, f_u)
214    USE icosa
215    USE disvert_mod
216    USE omp_para
217    USE trace
218    TYPE(t_field),POINTER :: f_ps(:), f_u(:)
219    REAL(rstd), POINTER :: ps(:), u(:,:)
220    INTEGER :: ind,ij,l
221    CALL trace_start("legacy_to_DEC")
222
223    DO ind=1,ndomain
224       IF (.NOT. assigned_domain(ind)) CYCLE
225       CALL swap_dimensions(ind)
226       CALL swap_geometry(ind)
227
228       IF(caldyn_eta==eta_mass .AND. is_omp_first_level) THEN
229          ps=f_ps(ind)
[953]230          !$acc parallel loop async default(present)
[487]231          !DIR$ SIMD
[362]232          DO ij=ij_begin,ij_end
233             ps(ij)=ptop+ps(ij)*g ! convert column-integrated mass to ps
234          ENDDO
235       ENDIF
236       
237       u=f_u(ind)
[953]238       !$acc parallel loop async default(present)
[362]239       DO l=ll_begin,ll_end
[953]240          !$acc loop
[487]241          !DIR$ SIMD
[362]242          DO ij=ij_begin,ij_end
243             u(ij+u_right,l)=u(ij+u_right,l)/de(ij+u_right)
244             u(ij+u_lup,l)=u(ij+u_lup,l)/de(ij+u_lup)
245             u(ij+u_ldown,l)=u(ij+u_ldown,l)/de(ij+u_ldown)
246          ENDDO
247       ENDDO
248    ENDDO
249
250    CALL trace_end("DEC_to_legacy") 
251  END SUBROUTINE DEC_to_legacy
252
[360]253END MODULE euler_scheme_mod
Note: See TracBrowser for help on using the repository browser.