source: codes/icosagcm/trunk/src/time/hevi_scheme.F90

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

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

File size: 5.6 KB
Line 
1MODULE hevi_scheme_mod
2  USE prec
3  USE domain_mod
4  USE field_mod
5  USE euler_scheme_mod
6  USE abort_mod
7  IMPLICIT NONE
8  PRIVATE
9
10  REAL(rstd), SAVE :: wj(3), bjl(3,3), cjl(3,3), taujj(3)
11  REAL(rstd), PARAMETER, DIMENSION(3) :: zero = (/0.,0.,0./)
12
13  PUBLIC :: set_coefs_ark23, set_coefs_ark33, hevi_scheme
14
15CONTAINS
16  SUBROUTINE set_coefs_ark23(dt)
17    ! ARK2 scheme by Giraldo, Kelly, Constantinescu 2013
18    ! See Weller et al., 2013 - ARK2 scheme Fig. 2
19    REAL(rstd) :: dt
20    REAL(rstd), PARAMETER :: delta=.5/SQRT(2.), gamma=1.-2.*delta
21!    REAL(rstd), PARAMETER :: alpha=(3.+SQRT(8.))/6. ! original value in GKC2013
22    REAL(rstd), PARAMETER :: alpha=0.7
23    REAL(rstd), PARAMETER, DIMENSION(3) :: wj = (/delta,delta,gamma/)
24    CALL set_coefs_hevi(dt, &
25         (/ zero, (/2.*gamma,0.,0./), (/1-alpha,alpha,0./), wj /), &
26         (/ zero, (/gamma,gamma,0./), wj, wj /) )
27  END SUBROUTINE set_coefs_ark23
28
29  SUBROUTINE set_coefs_ark33(dt)
30    ! Fully-explicit RK3 scheme disguised as ARK
31    REAL(rstd) :: dt
32    CALL set_coefs_rk(dt, (/ zero, (/.5,0.,0./), (/-1.,2.,0./), (/1./6.,2./3.,1./6./) /) )
33  END SUBROUTINE set_coefs_ark33
34   
35  SUBROUTINE set_coefs_rk(dt, ajl)
36    REAL(rstd) :: dt, ajl(3,4)
37    CALL set_coefs_hevi(dt,ajl,ajl)
38  END SUBROUTINE set_coefs_rk
39
40  SUBROUTINE set_coefs_hevi(dt, ajl_slow, ajl_fast)
41    REAL(rstd) :: dt, ajl_slow(3,4), ajl_fast(3,4) ! fast/slow Butcher tableaus
42    INTEGER :: j
43    DO j=1,3
44       bjl(:,j) = dt*(ajl_slow(:,j+1)-ajl_slow(:,j))
45       cjl(:,j) = dt*(ajl_fast(:,j+1)-ajl_fast(:,j))
46       taujj(j) = dt*ajl_fast(j,j)
47    END DO
48    wj=dt*ajl_slow(:,4)
49  END SUBROUTINE set_coefs_hevi
50
51  SUBROUTINE HEVI_scheme(it, fluxt_zero)
52    USE time_mod
53    USE disvert_mod
54    USE caldyn_hevi_mod
55    USE omp_para
56    USE checksum_mod
57    LOGICAL :: fluxt_zero(ndomain) ! set to .TRUE. to start accumulating fluxes in time
58    INTEGER :: it,j,l, ind
59    REAL(rstd),POINTER :: hflux(:,:),wflux(:,:),hfluxt(:,:),wfluxt(:,:)
60
61    CALL legacy_to_DEC(f_ps, f_u)
62
63    DO j=1,nb_stage
64       CALL caldyn_hevi((j==1) .AND. (MOD(it,itau_out)==0), taujj(j), &
65            f_phis, f_ps,f_mass,f_theta_rhodz,f_u,f_q, &
66            f_W, f_geopot, f_hflux, f_wflux, &
67            f_dps_slow(:,j), f_dmass_slow(:,j), f_dtheta_rhodz_slow(:,j), &
68            f_du_slow(:,j), f_du_fast(:,j), &
69            f_dPhi_slow(:,j), f_dPhi_fast(:,j), &
70            f_dW_slow(:,j), f_dW_fast(:,j) )
71       ! accumulate mass fluxes for transport scheme
72       
73       DO ind=1,ndomain
74          IF (.NOT. assigned_domain(ind)) CYCLE
75          CALL swap_dimensions(ind)
76          hflux=f_hflux(ind);     hfluxt=f_hfluxt(ind)
77          wflux=f_wflux(ind);     wfluxt=f_wfluxt(ind)
78          CALL accumulate_fluxes(hflux,wflux, hfluxt,wfluxt, wj(j), fluxt_zero(ind))
79
80       END DO
81       ! update model state
82       DO l=1,j
83          IF(caldyn_eta==eta_mass) THEN
84             CALL update_2D(bjl(l,j), f_ps, f_dps_slow(:,l))
85          ELSE
86             CALL update_3D(bjl(l,j), f_mass, f_dmass_slow(:,l))
87          END IF
88          CALL update_4D(bjl(l,j), f_theta_rhodz, f_dtheta_rhodz_slow(:,l))
89          CALL update_3D(bjl(l,j), f_u, f_du_slow(:,l))
90          CALL update_3D(cjl(l,j), f_u, f_du_fast(:,l))
91          IF(.NOT. hydrostatic) THEN
92             CALL abort_acc("HEVI_scheme/!hydrostatic")
93             CALL update_3D(bjl(l,j), f_W, f_dW_slow(:,l))
94             CALL update_3D(cjl(l,j), f_W, f_dW_fast(:,l))
95             CALL update_3D(bjl(l,j), f_geopot, f_dPhi_slow(:,l))
96             CALL update_3D(cjl(l,j), f_geopot, f_dPhi_fast(:,l))
97          END IF
98
99!$OMP BARRIER       
100       END DO
101    END DO
102    CALL DEC_to_legacy(f_ps, f_u)
103  END SUBROUTINE HEVI_scheme
104 
105  SUBROUTINE update_4D(w, f_y, f_dy)
106    USE dimensions
107    USE grid_param, ONLY : nqdyn
108    REAL(rstd) :: w
109    TYPE(t_field) :: f_y(:), f_dy(:)
110    REAL(rstd), POINTER :: y(:,:,:), dy(:,:,:)
111    INTEGER :: ind, iq
112    IF(w /= 0.) THEN
113       DO ind=1,ndomain
114          IF (.NOT. assigned_domain(ind)) CYCLE
115          CALL swap_dimensions(ind)
116          dy=f_dy(ind); y=f_y(ind)
117          DO iq=1,nqdyn
118             CALL compute_update_3D(w,y(:,:,iq),dy(:,:,iq))
119          END DO
120       ENDDO
121    END IF
122  END SUBROUTINE update_4D
123   
124  SUBROUTINE update_3D(w, f_y, f_dy)
125    USE dimensions
126    REAL(rstd) :: w
127    TYPE(t_field) :: f_y(:), f_dy(:)
128    REAL(rstd), POINTER :: y(:,:), dy(:,:)
129    INTEGER :: ind
130    IF(w /= 0.) THEN
131       DO ind=1,ndomain
132          IF (.NOT. assigned_domain(ind)) CYCLE
133          CALL swap_dimensions(ind)
134          dy=f_dy(ind); y=f_y(ind)
135          CALL compute_update_3D(w,y,dy)
136       ENDDO
137    END IF
138  END SUBROUTINE update_3D
139   
140  SUBROUTINE compute_update_3D(w, y, dy)
141    USE omp_para
142    USE disvert_mod
143    REAL(rstd) :: w
144    REAL(rstd) :: y(:,:), dy(:,:)
145    INTENT(INOUT) :: y
146    INTENT(IN) :: dy
147    INTEGER :: l
148    !$acc kernels async default(present)
149    DO l=ll_begin,ll_end
150       y(:,l)=y(:,l)+w*dy(:,l)
151    ENDDO
152    !$acc end kernels
153  END SUBROUTINE compute_update_3D
154 
155  SUBROUTINE update_2D(w, f_y, f_dy)
156  USE omp_para
157    REAL(rstd) :: w
158    TYPE(t_field) :: f_y(:), f_dy(:)
159    REAL(rstd), POINTER :: y(:), dy(:)
160    INTEGER :: ind
161    DO ind=1,ndomain
162       IF (.NOT. assigned_domain(ind)) CYCLE
163       dy=f_dy(ind); y=f_y(ind)
164       IF (is_omp_level_master) CALL compute_update_2D(w,y,dy)
165    ENDDO
166  END SUBROUTINE update_2D
167   
168  SUBROUTINE compute_update_2D(w, y, dy)
169    REAL(rstd) :: w, y(:), dy(:)
170    INTENT(INOUT) :: y
171    INTENT(IN) :: dy
172    !$acc kernels async default(present)
173    y(:)=y(:)+w*dy(:)
174    !$acc end kernels
175  END SUBROUTINE compute_update_2D
176 
177END MODULE hevi_scheme_mod
Note: See TracBrowser for help on using the repository browser.