source: codes/icosagcm/trunk/src/hevi_scheme.f90 @ 362

Last change on this file since 362 was 362, checked in by dubos, 9 years ago

Introduced DEC convention for velocity - HEVI only - cleanup to follow

File size: 4.2 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_kernels_base_mod, ONLY : DEC
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
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 :: alpha=(3.+SQRT(8.))/6., delta=.5/SQRT(2.), gamma=1.-2.*delta
22    REAL(rstd), PARAMETER, DIMENSION(3) :: wj = (/delta,delta,gamma/)
23    CALL set_coefs_hevi(dt, &
24         (/ zero, (/2.*gamma,0.,0./), (/1-alpha,alpha,0./), wj /), &
25         (/ zero, (/gamma,gamma,0./), wj, wj /) )
26  END SUBROUTINE set_coefs_ark23
27
28  SUBROUTINE set_coefs_ark33(dt)
29    ! Fully-explicit RK3 scheme disguised as ARK
30    ! To check correctness of caldyn_hevi
31    REAL(rstd) :: dt
32    REAL(rstd), PARAMETER, DIMENSION(3,4) :: &
33         ajl=(/ zero, (/.5,0.,0./), (/-1.,2.,0./), (/1./6.,2./3.,1./6./) /)
34    CALL set_coefs_hevi(dt, ajl, ajl)
35  END SUBROUTINE set_coefs_ark33
36   
37  SUBROUTINE set_coefs_hevi(dt, ajl_slow, ajl_fast)
38    REAL(rstd) :: dt, ajl_slow(3,4), ajl_fast(3,4) ! fast/slow Butcher tableaus
39    INTEGER :: j
40    DO j=1,3
41       bjl(:,j) = dt*(ajl_slow(:,j+1)-ajl_slow(:,j))
42       cjl(:,j) = dt*(ajl_fast(:,j+1)-ajl_fast(:,j))
43       taujj(j) = dt*ajl_fast(j,j)
44    END DO
45    wj=dt*ajl_slow(:,4)
46  END SUBROUTINE set_coefs_hevi
47
48  SUBROUTINE HEVI_scheme(it, fluxt_zero)
49    USE time_mod
50    USE disvert_mod
51    USE caldyn_hevi_mod
52    LOGICAL :: fluxt_zero(ndomain) ! set to .TRUE. to start accumulating fluxes in time
53    INTEGER :: it,j,l, ind
54    REAL(rstd),POINTER :: hflux(:,:),wflux(:,:),hfluxt(:,:),wfluxt(:,:)
55
56    IF(DEC) CALL legacy_to_DEC(f_ps, f_u)
57    DO j=1,nb_stage
58       CALL caldyn_hevi((j==1) .AND. (MOD(it,itau_out)==0), taujj(j), &
59            f_phis, f_ps,f_mass,f_theta_rhodz,f_u,f_q, &
60            f_geopot, f_hflux, f_wflux, &
61            f_dps_slow(:,j), f_dmass_slow(:,j), f_dtheta_rhodz_slow(:,j), &
62            f_du_slow(:,j), f_du_fast(:,j) )
63       ! accumulate mass fluxes for transport scheme
64       DO ind=1,ndomain
65          IF (.NOT. assigned_domain(ind)) CYCLE
66          CALL swap_dimensions(ind)
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, wj(j), fluxt_zero(ind))
70       END DO
71       ! update model state
72       DO l=1,j
73          IF(caldyn_eta==eta_mass) THEN
74             CALL update_2D(bjl(l,j), f_ps, f_dps_slow(:,l))
75          ELSE
76             CALL update(bjl(l,j), f_mass, f_dmass_slow(:,l))
77          END IF
78          CALL update(bjl(l,j), f_theta_rhodz, f_dtheta_rhodz_slow(:,l))
79          CALL update(bjl(l,j), f_u, f_du_slow(:,l))
80          CALL update(cjl(l,j), f_u, f_du_fast(:,l))
81       END DO
82    END DO
83    IF(DEC) CALL DEC_to_legacy(f_ps, f_u)
84  END SUBROUTINE HEVI_scheme
85 
86  SUBROUTINE update(w, f_y, f_dy)
87    USE dimensions
88    REAL(rstd) :: w
89    TYPE(t_field) :: f_y(:), f_dy(:)
90    REAL(rstd), POINTER :: y(:,:), dy(:,:)
91    INTEGER :: ind
92    IF(w /= 0.) THEN
93       DO ind=1,ndomain
94          IF (.NOT. assigned_domain(ind)) CYCLE
95          CALL swap_dimensions(ind)
96          dy=f_dy(ind); y=f_y(ind)
97          CALL compute_update(w,y,dy)
98       ENDDO
99    END IF
100  END SUBROUTINE update
101   
102  SUBROUTINE compute_update(w, y, dy)
103    USE omp_para
104    USE disvert_mod
105    REAL(rstd) :: w
106    REAL(rstd) :: y(:,:), dy(:,:)
107    INTENT(INOUT) :: y
108    INTENT(IN) :: dy
109    INTEGER :: l
110    DO l=ll_begin,ll_end
111       y(:,l)=y(:,l)+w*dy(:,l)
112    ENDDO
113  END SUBROUTINE compute_update
114 
115  SUBROUTINE update_2D(w, f_y, f_dy)
116    REAL(rstd) :: w
117    TYPE(t_field) :: f_y(:), f_dy(:)
118    REAL(rstd), POINTER :: y(:), dy(:)
119    INTEGER :: ind
120    DO ind=1,ndomain
121       IF (.NOT. assigned_domain(ind)) CYCLE
122       dy=f_dy(ind); y=f_y(ind)
123       CALL compute_update_2D(w,y,dy)
124    ENDDO
125  END SUBROUTINE update_2D
126   
127  SUBROUTINE compute_update_2D(w, y, dy)
128    REAL(rstd) :: w, y(:), dy(:)
129    INTENT(INOUT) :: y
130    INTENT(IN) :: dy
131    y(:)=y(:)+w*dy(:)
132  END SUBROUTINE compute_update_2D
133 
134END MODULE hevi_scheme_mod
Note: See TracBrowser for help on using the repository browser.