source: codes/icosagcm/devel/src/dynamics/compute_caldyn_fast.F90 @ 915

Last change on this file since 915 was 858, checked in by dubos, 5 years ago

devel : moved DYSL into compute_caldyn_fast.F90

File size: 7.8 KB
Line 
1MODULE compute_caldyn_fast_mod
2  USE grid_param, ONLY : llm
3  IMPLICIT NONE
4  PRIVATE
5
6#include "../unstructured/unstructured.h90"
7
8  PUBLIC :: compute_caldyn_fast
9
10CONTAINS
11
12#ifdef BEGIN_DYSL
13
14KERNEL(caldyn_fast)
15!
16  SELECT CASE(caldyn_thermo)
17  CASE(thermo_boussinesq)
18    FORALL_CELLS()
19      ON_PRIMAL
20        berni(CELL) = pk(CELL)
21        ! from now on pk contains the vertically-averaged geopotential
22        pk(CELL) = .5*(geopot(CELL)+geopot(UP(CELL)))
23      END_BLOCK
24    END_BLOCK
25  CASE(thermo_theta)
26    FORALL_CELLS()
27      ON_PRIMAL
28        berni(CELL) = .5*(geopot(CELL)+geopot(UP(CELL)))
29      END_BLOCK
30    END_BLOCK
31  CASE(thermo_entropy)
32    FORALL_CELLS()
33      ON_PRIMAL
34        berni(CELL) = .5*(geopot(CELL)+geopot(UP(CELL)))
35        berni(CELL) = berni(CELL) + pk(CELL)*(cpp-theta(CELL,1)) ! Gibbs = Cp.T-Ts = T(Cp-s)
36      END_BLOCK
37    END_BLOCK
38  CASE(thermo_variable_Cp)
39    ! thermodynamics with variable Cp
40    !           Cp(T) = Cp0 * (T/T0)^nu
41    ! =>            h = Cp(T).T/(nu+1)
42
43    FORALL_CELLS()
44      ON_PRIMAL
45        berni(CELL) = .5*(geopot(CELL)+geopot(UP(CELL)))
46        cp_ik = cpp*(pk(CELL)/Treff)**nu
47        berni(CELL) = berni(CELL) + pk(CELL)*(cp_ik/(nu+1.)-theta(CELL,1)) ! Gibbs = h-Ts = T(Cp/(nu+1)-s)
48      END_BLOCK
49    END_BLOCK
50  CASE DEFAULT
51    PRINT *, 'Unsupported value of caldyn_thermo : ',caldyn_thermo  ! FIXME
52    STOP
53  END SELECT
54!
55  FORALL_CELLS()
56    ON_EDGES
57      due = .5*(theta(CELL1,1)+theta(CELL2,1))*(pk(CELL2)-pk(CELL1)) + berni(CELL2)-berni(CELL1)
58      du(EDGE) = du(EDGE) - SIGN*due
59      u(EDGE) = u(EDGE) + tau*du(EDGE)
60    END_BLOCK
61  END_BLOCK 
62!
63END_BLOCK
64
65#endif END_DYSL
66
67  SUBROUTINE compute_caldyn_fast_unst(tau, pk,berni,theta,geopot, du,u)
68    USE ISO_C_BINDING, only : C_DOUBLE, C_FLOAT
69    USE earth_const
70    USE grid_param, ONLY : nqdyn
71    USE data_unstructured_mod, ONLY : enter_trace, exit_trace, &
72         id_fast, primal_num, dual_num, edge_num, &
73         dual_deg, dual_edge, dual_ne, dual_vertex, &
74         up, down, left, right, Av, fv, Riv2
75    NUM, INTENT(IN) :: tau
76    FIELD_MASS   :: pk,berni  ! INOUT, OUT
77    FIELD_THETA  :: theta     ! IN
78    FIELD_GEOPOT :: geopot    ! IN
79    FIELD_U      :: u,du      ! INOUT,INOUT
80    DECLARE_INDICES
81    DECLARE_EDGES
82    NUM          :: due, cp_ik
83    START_TRACE(id_fast, 4,0,2) ! primal, dual, edge
84#include "../kernels_unst/caldyn_fast.k90"
85    STOP_TRACE
86  END SUBROUTINE compute_caldyn_fast_unst
87
88  SUBROUTINE compute_caldyn_fast(tau,u,rhodz,theta,pk,geopot,du)
89    USE icosa
90    USE trace
91    USE caldyn_vars_mod
92    USE omp_para, ONLY : ll_begin, ll_end
93    REAL(rstd),INTENT(IN)    :: tau                ! "solve" u-tau*du/dt = rhs
94    REAL(rstd),INTENT(INOUT) :: u(iim*3*jjm,llm)   ! OUT if tau>0
95    REAL(rstd),INTENT(IN)    :: rhodz(iim*jjm,llm)
96    REAL(rstd),INTENT(IN)    :: theta(iim*jjm,llm,nqdyn)
97    REAL(rstd),INTENT(INOUT) :: pk(iim*jjm,llm)
98    REAL(rstd),INTENT(INOUT) :: geopot(iim*jjm,llm+1)
99    REAL(rstd),INTENT(INOUT)   :: du(iim*3*jjm,llm)
100    REAL(rstd) :: berni(iim*jjm,llm)  ! Bernoulli function
101    REAL(rstd) :: berniv(iim*jjm,llm)  ! moist Bernoulli function
102
103    INTEGER :: i,j,ij,l
104    REAL(rstd) :: cp_ik, qv, temp, chi, log_p_preff, due, due_right, due_lup, due_ldown
105
106    CALL trace_start("compute_caldyn_fast")
107
108    IF(dysl_caldyn_fast) THEN
109#include "../kernels_hex/caldyn_fast.k90"
110    ELSE
111
112    ! Compute Bernoulli term
113    IF(boussinesq) THEN
114       DO l=ll_begin,ll_end
115          !DIR$ SIMD
116          DO ij=ij_begin,ij_end         
117             berni(ij,l) = pk(ij,l)
118             ! from now on pk contains the vertically-averaged geopotential
119             pk(ij,l) = .5*(geopot(ij,l)+geopot(ij,l+1))
120          END DO
121       END DO
122    ELSE ! compressible
123
124       DO l=ll_begin,ll_end
125          SELECT CASE(caldyn_thermo)
126          CASE(thermo_theta) ! vdp = theta.dpi => B = Phi
127             !DIR$ SIMD
128             DO ij=ij_begin,ij_end         
129                berni(ij,l) = .5*(geopot(ij,l)+geopot(ij,l+1))
130             END DO
131          CASE(thermo_entropy) ! vdp = dG + sdT => B = Phi + G, G=h-Ts=T*(cpp-s)
132             !DIR$ SIMD
133             DO ij=ij_begin,ij_end         
134                berni(ij,l) = .5*(geopot(ij,l)+geopot(ij,l+1)) &
135                     + pk(ij,l)*(cpp-theta(ij,l,1)) ! pk=temperature, theta=entropy
136             END DO
137          CASE(thermo_moist) 
138             !DIR$ SIMD
139             DO ij=ij_begin,ij_end         
140                ! du/dt = grad(Bd)+rv.grad(Bv)+s.grad(T)
141                ! Bd = Phi + gibbs_d
142                ! Bv = Phi + gibbs_v
143                ! pk=temperature, theta=entropy
144                qv = theta(ij,l,2)
145                temp = pk(ij,l)
146                chi = log(temp/Treff)
147                log_p_preff = (chi*(cpp+qv*cppv)-theta(ij,l,1))/(Rd+qv*Rv) ! log(p/preff)
148                berni(ij,l) = .5*(geopot(ij,l)+geopot(ij,l+1)) &
149                     + temp*(cpp*(1.-chi)+Rd*log_p_preff)
150                berniv(ij,l) = .5*(geopot(ij,l)+geopot(ij,l+1)) &
151                     + temp*(cppv*(1.-chi)+Rv*log_p_preff)
152            END DO
153          END SELECT
154       END DO
155
156    END IF ! Boussinesq/compressible
157
158!!! u:=u+tau*du, du = -grad(B)-theta.grad(pi)
159    DO l=ll_begin,ll_end
160       IF(caldyn_thermo == thermo_moist) THEN
161          !DIR$ SIMD
162          DO ij=ij_begin,ij_end         
163             due_right =  berni(ij+t_right,l)-berni(ij,l)       &
164                  + 0.5*(theta(ij,l,1)+theta(ij+t_right,l,1))   &
165                       *(pk(ij+t_right,l)-pk(ij,l))             &
166                  + 0.5*(theta(ij,l,2)+theta(ij+t_right,l,2))   &
167                       *(berniv(ij+t_right,l)-berniv(ij,l))
168             
169             due_lup = berni(ij+t_lup,l)-berni(ij,l)            &
170                  + 0.5*(theta(ij,l,1)+theta(ij+t_lup,l,1))     &
171                       *(pk(ij+t_lup,l)-pk(ij,l))               &
172                  + 0.5*(theta(ij,l,2)+theta(ij+t_lup,l,2))     &
173                       *(berniv(ij+t_lup,l)-berniv(ij,l))
174             
175             due_ldown = berni(ij+t_ldown,l)-berni(ij,l)        &
176                  + 0.5*(theta(ij,l,1)+theta(ij+t_ldown,l,1))   &
177                       *(pk(ij+t_ldown,l)-pk(ij,l))             &
178                  + 0.5*(theta(ij,l,2)+theta(ij+t_ldown,l,2))   &
179                       *(berniv(ij+t_ldown,l)-berniv(ij,l))
180             
181             du(ij+u_right,l) = du(ij+u_right,l) - ne_right*due_right
182             du(ij+u_lup,l)   = du(ij+u_lup,l)   - ne_lup*due_lup
183             du(ij+u_ldown,l) = du(ij+u_ldown,l) - ne_ldown*due_ldown
184             u(ij+u_right,l) = u(ij+u_right,l) + tau*du(ij+u_right,l)
185             u(ij+u_lup,l)   = u(ij+u_lup,l)   + tau*du(ij+u_lup,l)
186             u(ij+u_ldown,l) = u(ij+u_ldown,l) + tau*du(ij+u_ldown,l)
187          END DO
188       ELSE
189          !DIR$ SIMD
190          DO ij=ij_begin,ij_end         
191             due_right =  0.5*(theta(ij,l,1)+theta(ij+t_right,l,1))  &
192                  *(pk(ij+t_right,l)-pk(ij,l))        &
193                  +  berni(ij+t_right,l)-berni(ij,l)
194             due_lup = 0.5*(theta(ij,l,1)+theta(ij+t_lup,l,1))    &
195                  *(pk(ij+t_lup,l)-pk(ij,l))          &
196                  +  berni(ij+t_lup,l)-berni(ij,l)
197             due_ldown = 0.5*(theta(ij,l,1)+theta(ij+t_ldown,l,1)) &
198                  *(pk(ij+t_ldown,l)-pk(ij,l))      &
199                  +   berni(ij+t_ldown,l)-berni(ij,l)
200             du(ij+u_right,l) = du(ij+u_right,l) - ne_right*due_right
201             du(ij+u_lup,l)   = du(ij+u_lup,l)   - ne_lup*due_lup
202             du(ij+u_ldown,l) = du(ij+u_ldown,l) - ne_ldown*due_ldown
203             u(ij+u_right,l) = u(ij+u_right,l) + tau*du(ij+u_right,l)
204             u(ij+u_lup,l)   = u(ij+u_lup,l)   + tau*du(ij+u_lup,l)
205             u(ij+u_ldown,l) = u(ij+u_ldown,l) + tau*du(ij+u_ldown,l)
206          END DO
207       END IF
208    END DO
209
210    END IF ! dysl
211    CALL trace_end("compute_caldyn_fast")
212
213  END SUBROUTINE compute_caldyn_fast
214
215END MODULE compute_caldyn_fast_mod
Note: See TracBrowser for help on using the repository browser.