source: codes/icosagcm/devel/src/time/hevi_scheme.f90

Last change on this file was 1026, checked in by dubos, 4 years ago

devel : towards conformity to F2008 standard

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