source: codes/icosagcm/devel/src/dynamics/caldyn_kernels_hevi.F90 @ 565

Last change on this file since 565 was 565, checked in by dubos, 7 years ago

devel : fix compilation without -dysl

File size: 37.3 KB
Line 
1MODULE caldyn_kernels_hevi_mod
2  USE icosa
3  USE trace
4  USE omp_para
5  USE disvert_mod
6  USE transfert_mod
7  USE caldyn_kernels_base_mod
8  IMPLICIT NONE
9  PRIVATE
10
11  REAL(rstd), PARAMETER :: pbot=1e5, rho_bot=1e6
12
13  LOGICAL, SAVE :: debug_hevi_solver = .FALSE.
14
15  PUBLIC :: compute_theta, compute_pvort_only, compute_caldyn_Coriolis, &
16       compute_caldyn_slow_hydro, compute_caldyn_slow_NH, &
17       compute_caldyn_solver, compute_caldyn_fast
18
19CONTAINS
20
21  SUBROUTINE compute_theta(ps,theta_rhodz, rhodz,theta)
22    REAL(rstd),INTENT(IN)    :: ps(iim*jjm)
23    REAL(rstd),INTENT(IN)    :: theta_rhodz(iim*jjm,llm,nqdyn)
24    REAL(rstd),INTENT(INOUT) :: rhodz(iim*jjm,llm)
25    REAL(rstd),INTENT(OUT)   :: theta(iim*jjm,llm,nqdyn)
26    INTEGER :: ij,l,iq
27    REAL(rstd) :: m
28    CALL trace_start("compute_theta")
29
30    IF(caldyn_eta==eta_mass) THEN ! Compute mass
31       DO l = ll_begin,ll_end
32          !DIR$ SIMD
33          DO ij=ij_begin_ext,ij_end_ext
34             m = mass_dak(l)+(ps(ij)*g+ptop)*mass_dbk(l) ! ps is actually Ms
35             rhodz(ij,l) = m/g
36          END DO
37       END DO
38    END IF
39
40    DO l = ll_begin,ll_end
41       DO iq=1,nqdyn
42          !DIR$ SIMD
43          DO ij=ij_begin_ext,ij_end_ext
44             theta(ij,l,iq) = theta_rhodz(ij,l,iq)/rhodz(ij,l)
45          END DO
46       END DO
47    END DO
48
49    CALL trace_end("compute_theta")
50  END SUBROUTINE compute_theta
51
52  SUBROUTINE compute_pvort_only(u,rhodz,qu,qv)
53    REAL(rstd),INTENT(IN)  :: u(iim*3*jjm,llm)
54    REAL(rstd),INTENT(INOUT) :: rhodz(iim*jjm,llm)
55    REAL(rstd),INTENT(OUT) :: qu(iim*3*jjm,llm)
56    REAL(rstd),INTENT(OUT) :: qv(iim*2*jjm,llm)
57
58    INTEGER :: ij,l
59    REAL(rstd) :: etav,hv,radius_m2
60
61    CALL trace_start("compute_pvort_only") 
62!!! Compute shallow-water potential vorticity
63    IF(dysl_pvort_only) THEN
64#ifdef CPP_DYSL
65#include "../kernels/pvort_only.k90"
66#else
67        STOP 'dysl_pvort_only=.TRUE. but DYNAMICO is compiled without the -dysl option'
68#endif
69    ELSE
70
71    radius_m2=radius**(-2)
72    DO l = ll_begin,ll_end
73       !DIR$ SIMD
74       DO ij=ij_begin_ext,ij_end_ext
75          etav= 1./Av(ij+z_up)*(  ne_rup  * u(ij+u_rup,l)   &
76                  + ne_left * u(ij+t_rup+u_left,l)          &
77                  - ne_lup  * u(ij+u_lup,l) )                               
78          hv =   Riv2(ij,vup)          * rhodz(ij,l)        &
79               + Riv2(ij+t_rup,vldown) * rhodz(ij+t_rup,l)  &
80               + Riv2(ij+t_lup,vrdown) * rhodz(ij+t_lup,l)
81          qv(ij+z_up,l) = ( etav+fv(ij+z_up) )/hv
82         
83          etav = 1./Av(ij+z_down)*(  ne_ldown * u(ij+u_ldown,l)   &
84               + ne_right * u(ij+t_ldown+u_right,l)               &
85               - ne_rdown * u(ij+u_rdown,l) )
86          hv =   Riv2(ij,vdown)        * rhodz(ij,l)              &
87               + Riv2(ij+t_ldown,vrup) * rhodz(ij+t_ldown,l)      &
88               + Riv2(ij+t_rdown,vlup) * rhodz(ij+t_rdown,l)
89          qv(ij+z_down,l) =( etav+fv(ij+z_down) )/hv
90       ENDDO
91
92       !DIR$ SIMD
93       DO ij=ij_begin,ij_end
94          qu(ij+u_right,l) = 0.5*(qv(ij+z_rdown,l)+qv(ij+z_rup,l)) 
95          qu(ij+u_lup,l) = 0.5*(qv(ij+z_up,l)+qv(ij+z_lup,l)) 
96          qu(ij+u_ldown,l) = 0.5*(qv(ij+z_ldown,l)+qv(ij+z_down,l)) 
97       END DO
98
99    ENDDO
100   
101    END IF ! dysl
102    CALL trace_end("compute_pvort_only")
103
104  END SUBROUTINE compute_pvort_only
105
106  SUBROUTINE compute_NH_geopot(tau, phis, m_ik, m_il, theta, W_il, Phi_il)
107    REAL(rstd),INTENT(IN)    :: tau ! solve Phi-tau*dPhi/dt = Phi_rhs
108    REAL(rstd),INTENT(IN)    :: phis(iim*jjm)
109    REAL(rstd),INTENT(IN)    :: m_ik(iim*jjm,llm)
110    REAL(rstd),INTENT(IN)    :: m_il(iim*jjm,llm+1)
111    REAL(rstd),INTENT(IN)    :: theta(iim*jjm,llm)
112    REAL(rstd),INTENT(IN)    :: W_il(iim*jjm,llm+1)   ! vertical momentum
113    REAL(rstd),INTENT(INOUT) :: Phi_il(iim*jjm,llm+1) ! geopotential
114
115    REAL(rstd) :: Phi_star_il(iim*jjm,llm+1) 
116    REAL(rstd) :: p_ik(iim*jjm,llm)      ! pressure
117    REAL(rstd) :: R_il(iim*jjm,llm+1)    ! rhs of tridiag problem
118    REAL(rstd) :: x_il(iim*jjm,llm+1)    ! solution of tridiag problem
119    REAL(rstd) :: A_ik(iim*jjm,llm)      ! off-diagonal coefficients of tridiag problem
120    REAL(rstd) :: B_il(iim*jjm,llm+1)    ! diagonal coefficients of tridiag problem
121    REAL(rstd) :: C_ik(iim*jjm,llm)      ! Thomas algorithm
122    REAL(rstd) :: D_il(iim*jjm,llm+1)    ! Thomas algorithm
123    REAL(rstd) :: gamma, rho_ij, X_ij, Y_ij
124    REAL(rstd) :: wil, tau2_g, g2, gm2, ml_g2, c2_mik
125
126    INTEGER    :: iter, ij, l, ij_omp_begin_ext, ij_omp_end_ext
127
128    CALL distrib_level(ij_end_ext-ij_begin_ext+1,ij_omp_begin_ext,ij_omp_end_ext)
129    ij_omp_begin_ext=ij_omp_begin_ext+ij_begin_ext-1
130    ij_omp_end_ext=ij_omp_end_ext+ij_begin_ext-1
131
132#ifdef CPP_DYSL
133#define PHI_BOT(ij) phis(ij)
134#include "../kernels/compute_NH_geopot.k90"
135#else
136!    FIXME : vertical OpenMP parallelism will not work
137   
138    tau2_g=tau*tau/g
139    g2=g*g
140    gm2 = g**-2
141    gamma = 1./(1.-kappa)
142   
143    ! compute Phi_star
144    DO l=1,llm+1
145       !DIR$ SIMD
146       DO ij=ij_begin_ext,ij_end_ext
147          Phi_star_il(ij,l) = Phi_il(ij,l) + tau*g2*(W_il(ij,l)/m_il(ij,l)-tau)
148       ENDDO
149    ENDDO
150
151    ! Newton-Raphson iteration : Phi_il contains current guess value
152    DO iter=1,5 ! 2 iterations should be enough
153
154       ! Compute pressure, A_ik
155       DO l=1,llm
156          !DIR$ SIMD
157          DO ij=ij_begin_ext,ij_end_ext
158             rho_ij = (g*m_ik(ij,l))/(Phi_il(ij,l+1)-Phi_il(ij,l))
159             X_ij = (cpp/preff)*kappa*theta(ij,l)*rho_ij
160             p_ik(ij,l) = preff*(X_ij**gamma)
161             c2_mik = gamma*p_ik(ij,l)/(rho_ij*m_ik(ij,l)) ! c^2 = gamma*R*T = gamma*p/rho
162             A_ik(ij,l) = c2_mik*(tau/g*rho_ij)**2
163          ENDDO
164       ENDDO
165
166       ! Compute residual, B_il
167       ! bottom interface l=1
168       !DIR$ SIMD
169       DO ij=ij_begin_ext,ij_end_ext
170          ml_g2 = gm2*m_il(ij,1) 
171          B_il(ij,1) = A_ik(ij,1) + ml_g2 + tau2_g*rho_bot
172          R_il(ij,1) = ml_g2*( Phi_il(ij,1)-Phi_star_il(ij,1))  &
173               + tau2_g*( p_ik(ij,1)-pbot+rho_bot*(Phi_il(ij,1)-phis(ij)) )
174       ENDDO
175       ! inner interfaces
176       DO l=2,llm
177          !DIR$ SIMD
178          DO ij=ij_begin_ext,ij_end_ext
179             ml_g2 = gm2*m_il(ij,l) 
180             B_il(ij,l) = A_ik(ij,l)+A_ik(ij,l-1) + ml_g2
181             R_il(ij,l) = ml_g2*( Phi_il(ij,l)-Phi_star_il(ij,l))  &
182                     + tau2_g*(p_ik(ij,l)-p_ik(ij,l-1))
183             ! consistency check : if Wil=0 and initial state is in hydrostatic balance
184             ! then Phi_star_il(ij,l) = Phi_il(ij,l) - tau^2*g^2
185             ! and residual = tau^2*(ml+(1/g)dl_pi)=0
186          ENDDO
187       ENDDO
188       ! top interface l=llm+1
189       !DIR$ SIMD
190       DO ij=ij_begin_ext,ij_end_ext
191          ml_g2 = gm2*m_il(ij,llm+1) 
192          B_il(ij,llm+1) = A_ik(ij,llm) + ml_g2
193          R_il(ij,llm+1) = ml_g2*( Phi_il(ij,llm+1)-Phi_star_il(ij,llm+1))  &
194               + tau2_g*( ptop-p_ik(ij,llm) )
195       ENDDO
196
197       ! FIXME later
198       ! the lines below modify the tridiag problem
199       ! for flat, rigid boundary conditions at top and bottom :
200       ! zero out A(1), A(llm), R(1), R(llm+1)
201       ! => x(l)=0 at l=1,llm+1
202       DO ij=ij_begin_ext,ij_end_ext
203          A_ik(ij,1) = 0.
204          A_ik(ij,llm) = 0.
205          R_il(ij,1) = 0.
206          R_il(ij,llm+1) = 0.
207       ENDDO
208
209       IF(debug_hevi_solver) THEN ! print Linf(residual)
210          PRINT *, '[hevi_solver] R,p', iter, MAXVAL(ABS(R_il)), MAXVAL(p_ik)
211       END IF
212
213       ! Solve -A(l-1)x(l-1) + B(l)x(l) - A(l)x(l+1) = R(l) using Thomas algorithm
214       ! Forward sweep :
215       ! C(0)=0, C(l) = -A(l) / (B(l)+A(l-1)C(l-1)),
216       ! D(0)=0, D(l) = (R(l)+A(l-1)D(l-1)) / (B(l)+A(l-1)C(l-1))
217       ! bottom interface l=1
218       !DIR$ SIMD
219       DO ij=ij_begin_ext,ij_end_ext
220          X_ij = 1./B_il(ij,1)
221          C_ik(ij,1) = -A_ik(ij,1) * X_ij 
222          D_il(ij,1) =  R_il(ij,1) * X_ij
223       ENDDO
224       ! inner interfaces/layers
225       DO l=2,llm
226          !DIR$ SIMD
227          DO ij=ij_begin_ext,ij_end_ext
228             X_ij = 1./(B_il(ij,l) + A_ik(ij,l-1)*C_ik(ij,l-1))
229             C_ik(ij,l) = -A_ik(ij,l) * X_ij 
230             D_il(ij,l) =  (R_il(ij,l)+A_ik(ij,l-1)*D_il(ij,l-1)) * X_ij
231          ENDDO
232       ENDDO
233       ! top interface l=llm+1
234       !DIR$ SIMD
235       DO ij=ij_begin_ext,ij_end_ext
236          X_ij = 1./(B_il(ij,llm+1) + A_ik(ij,llm)*C_ik(ij,llm))
237          D_il(ij,llm+1) =  (R_il(ij,llm+1)+A_ik(ij,llm)*D_il(ij,llm)) * X_ij
238       ENDDO
239       
240       ! Back substitution :
241       ! x(i) = D(i)-C(i)x(i+1), x(N+1)=0
242       ! + Newton-Raphson update
243       x_il=0. ! FIXME
244       ! top interface l=llm+1
245       !DIR$ SIMD
246       DO ij=ij_begin_ext,ij_end_ext
247          x_il(ij,llm+1) = D_il(ij,llm+1)
248          Phi_il(ij,llm+1) = Phi_il(ij,llm+1) - x_il(ij,llm+1)
249       ENDDO
250       ! lower interfaces
251       DO l=llm,1,-1
252          !DIR$ SIMD
253          DO ij=ij_begin_ext,ij_end_ext
254             x_il(ij,l) = D_il(ij,l) - C_ik(ij,l)*x_il(ij,l+1)
255             Phi_il(ij,l) = Phi_il(ij,l) - x_il(ij,l)
256          ENDDO
257       ENDDO
258
259       IF(debug_hevi_solver) THEN
260          PRINT *, '[hevi_solver] A,B', iter, MAXVAL(ABS(A_ik)),MAXVAL(ABS(B_il))
261          PRINT *, '[hevi_solver] C,D', iter, MAXVAL(ABS(C_ik)),MAXVAL(ABS(D_il))
262          DO l=1,llm+1
263             WRITE(*,'(A,I2.1,I3.2,E9.2)'), '[hevi_solver] x', iter,l, MAXVAL(ABS(x_il(:,l)))
264          END DO
265       END IF
266
267    END DO ! Newton-Raphson
268
269#endif
270   
271  END SUBROUTINE compute_NH_geopot
272
273  SUBROUTINE compute_caldyn_solver(tau,phis, rhodz,theta,pk, geopot,W, m_il,pres, dPhi,dW,du)
274    REAL(rstd),INTENT(IN) :: tau ! "solve" Phi-tau*dPhi/dt = Phi_rhs
275    REAL(rstd),INTENT(IN)    :: phis(iim*jjm)
276    REAL(rstd),INTENT(IN)    :: rhodz(iim*jjm,llm)
277    REAL(rstd),INTENT(IN)    :: theta(iim*jjm,llm,nqdyn)
278    REAL(rstd),INTENT(OUT)   :: pk(iim*jjm,llm)
279    REAL(rstd),INTENT(INOUT) :: geopot(iim*jjm,llm+1)
280    REAL(rstd),INTENT(INOUT) :: W(iim*jjm,llm+1) ! OUT if tau>0
281    REAL(rstd),INTENT(OUT)   :: m_il(iim*jjm,llm+1)        ! rhodz averaged to interfaces
282    REAL(rstd),INTENT(OUT)   :: pres(iim*jjm,llm)          ! pressure
283    REAL(rstd),INTENT(OUT)   :: dW(iim*jjm,llm+1)
284    REAL(rstd),INTENT(OUT)   :: dPhi(iim*jjm,llm+1)
285    REAL(rstd),INTENT(OUT)   :: du(3*iim*jjm,llm)
286
287    REAL(rstd) :: berni(iim*jjm,llm)         ! (W/m_il)^2
288    REAL(rstd) :: gamma, rho_ij, T_ij, X_ij, Y_ij, vreff, Rd, Cvd
289    INTEGER    :: ij, l
290
291    CALL trace_start("compute_caldyn_solver")
292
293    Rd=cpp*kappa
294
295#ifdef CPP_DYSL
296!$OMP BARRIER
297#define PHI_BOT(ij) phis(ij)
298#define PHI_BOT_VAR phis
299#include "../kernels/caldyn_solver.k90"
300!$OMP BARRIER
301#else
302#define BERNI(ij) berni(ij,1)
303    ! FIXME : vertical OpenMP parallelism will not work
304
305    ! average m_ik to interfaces => m_il
306    !DIR$ SIMD
307    DO ij=ij_begin_ext,ij_end_ext
308       m_il(ij,1) = .5*rhodz(ij,1)
309    ENDDO
310    DO l=2,llm
311       !DIR$ SIMD
312       DO ij=ij_begin_ext,ij_end_ext
313          m_il(ij,l) = .5*(rhodz(ij,l-1)+rhodz(ij,l))
314       ENDDO
315    ENDDO
316    !DIR$ SIMD
317    DO ij=ij_begin_ext,ij_end_ext
318       m_il(ij,llm+1) = .5*rhodz(ij,llm)
319    ENDDO
320
321    IF(tau>0) THEN ! solve implicit problem for geopotential
322       CALL compute_NH_geopot(tau, phis, rhodz, m_il, theta, W, geopot)
323    END IF
324
325    ! Compute pressure, stored temporarily in pk
326    ! kappa = R/Cp
327    ! 1-kappa = Cv/Cp
328    ! Cp/Cv = 1/(1-kappa)
329    gamma = 1./(1.-kappa)
330    DO l=1,llm
331       !DIR$ SIMD
332       DO ij=ij_begin_ext,ij_end_ext
333          rho_ij = (g*rhodz(ij,l))/(geopot(ij,l+1)-geopot(ij,l))
334          X_ij = (cpp/preff)*kappa*theta(ij,l,1)*rho_ij
335          ! kappa.theta.rho = p/exner
336          ! => X = (p/p0)/(exner/Cp)
337          !      = (p/p0)^(1-kappa)
338          pk(ij,l) = preff*(X_ij**gamma)
339       ENDDO
340    ENDDO
341
342    ! Update W, compute tendencies
343    DO l=2,llm
344       !DIR$ SIMD
345       DO ij=ij_begin_ext,ij_end_ext
346          dW(ij,l)   = (1./g)*(pk(ij,l-1)-pk(ij,l)) - m_il(ij,l)
347          W(ij,l)    = W(ij,l)+tau*dW(ij,l) ! update W
348          dPhi(ij,l) = g*g*W(ij,l)/m_il(ij,l)
349       ENDDO
350       !       PRINT *,'Max dPhi', l,ij_begin,ij_end, MAXVAL(abs(dPhi(ij_begin:ij_end,l)))
351       !       PRINT *,'Max dW', l,ij_begin,ij_end, MAXVAL(abs(dW(ij_begin:ij_end,l)))
352    ENDDO
353    ! Lower BC (FIXME : no orography yet !)
354    DO ij=ij_begin,ij_end         
355       dPhi(ij,1)=0
356       W(ij,1)=0
357       dW(ij,1)=0
358       dPhi(ij,llm+1)=0 ! rigid lid
359       W(ij,llm+1)=0
360       dW(ij,llm+1)=0
361    ENDDO
362    ! Upper BC p=ptop
363    !    DO ij=ij_omp_begin_ext,ij_omp_end_ext
364    !       dPhi(ij,llm+1) = W(ij,llm+1)/rhodz(ij,llm)
365    !       dW(ij,llm+1) = (1./g)*(pk(ij,llm)-ptop) - .5*rhodz(ij,llm)
366    !    ENDDO
367   
368    ! Compute Exner function (needed by compute_caldyn_fast) and du=-g^2.grad(w^2)
369    DO l=1,llm
370       !DIR$ SIMD
371       DO ij=ij_begin_ext,ij_end_ext
372          pk(ij,l) = cpp*((pk(ij,l)/preff)**kappa) ! other formulae possible if exponentiation is slow
373          BERNI(ij) = (-.25*g*g)*(              &
374                 (W(ij,l)/m_il(ij,l))**2       &
375               + (W(ij,l+1)/m_il(ij,l+1))**2 )
376       ENDDO
377       DO ij=ij_begin,ij_end         
378          du(ij+u_right,l) = ne_right*(BERNI(ij)-BERNI(ij+t_right))
379          du(ij+u_lup,l)   = ne_lup  *(BERNI(ij)-BERNI(ij+t_lup))
380          du(ij+u_ldown,l) = ne_ldown*(BERNI(ij)-BERNI(ij+t_ldown))
381       ENDDO
382    ENDDO
383#undef BERNI
384#endif
385
386    CALL trace_end("compute_caldyn_solver")
387   
388  END SUBROUTINE compute_caldyn_solver
389 
390  SUBROUTINE compute_caldyn_fast(tau,u,rhodz,theta,pk,geopot,du)
391    REAL(rstd),INTENT(IN)    :: tau                ! "solve" u-tau*du/dt = rhs
392    REAL(rstd),INTENT(INOUT) :: u(iim*3*jjm,llm)   ! OUT if tau>0
393    REAL(rstd),INTENT(IN)    :: rhodz(iim*jjm,llm)
394    REAL(rstd),INTENT(IN)    :: theta(iim*jjm,llm,nqdyn)
395    REAL(rstd),INTENT(INOUT) :: pk(iim*jjm,llm)
396    REAL(rstd),INTENT(INOUT) :: geopot(iim*jjm,llm+1)
397    REAL(rstd),INTENT(INOUT)   :: du(iim*3*jjm,llm)
398    REAL(rstd) :: berni(iim*jjm,llm)  ! Bernoulli function
399    REAL(rstd) :: berniv(iim*jjm,llm)  ! moist Bernoulli function
400
401    INTEGER :: i,j,ij,l
402    REAL(rstd) :: Rd, qv, temp, chi, nu, due, due_right, due_lup, due_ldown
403
404    CALL trace_start("compute_caldyn_fast")
405
406    Rd=cpp*kappa
407
408    IF(dysl_caldyn_fast) THEN
409#ifdef CPP_DYSL
410#include "../kernels/caldyn_fast.k90"
411#else
412    STOP 'dysl_caldyn_fast=.TRUE. but DYNAMICO is compiled without the -dysl option'
413#endif
414    ELSE
415
416    ! Compute Bernoulli term
417    IF(boussinesq) THEN
418       DO l=ll_begin,ll_end
419          !DIR$ SIMD
420          DO ij=ij_begin,ij_end         
421             berni(ij,l) = pk(ij,l)
422             ! from now on pk contains the vertically-averaged geopotential
423             pk(ij,l) = .5*(geopot(ij,l)+geopot(ij,l+1))
424          END DO
425       END DO
426    ELSE ! compressible
427
428       DO l=ll_begin,ll_end
429          SELECT CASE(caldyn_thermo)
430          CASE(thermo_theta) ! vdp = theta.dpi => B = Phi
431             !DIR$ SIMD
432             DO ij=ij_begin,ij_end         
433                berni(ij,l) = .5*(geopot(ij,l)+geopot(ij,l+1))
434             END DO
435          CASE(thermo_entropy) ! vdp = dG + sdT => B = Phi + G, G=h-Ts=T*(cpp-s)
436             !DIR$ SIMD
437             DO ij=ij_begin,ij_end         
438                berni(ij,l) = .5*(geopot(ij,l)+geopot(ij,l+1)) &
439                     + pk(ij,l)*(cpp-theta(ij,l,1)) ! pk=temperature, theta=entropy
440             END DO
441          CASE(thermo_moist) 
442             !DIR$ SIMD
443             DO ij=ij_begin,ij_end         
444                ! du/dt = grad(Bd)+rv.grad(Bv)+s.grad(T)
445                ! Bd = Phi + gibbs_d
446                ! Bv = Phi + gibbs_v
447                ! pk=temperature, theta=entropy
448                qv = theta(ij,l,2)
449                temp = pk(ij,l)
450                chi = log(temp/Treff)
451                nu = (chi*(cpp+qv*cppv)-theta(ij,l,1))/(Rd+qv*Rv) ! log(p/preff)
452                berni(ij,l) = .5*(geopot(ij,l)+geopot(ij,l+1)) &
453                     + temp*(cpp*(1.-chi)+Rd*nu)
454                berniv(ij,l) = .5*(geopot(ij,l)+geopot(ij,l+1)) &
455                     + temp*(cppv*(1.-chi)+Rv*nu)
456            END DO
457          END SELECT
458       END DO
459
460    END IF ! Boussinesq/compressible
461
462!!! u:=u+tau*du, du = -grad(B)-theta.grad(pi)
463    DO l=ll_begin,ll_end
464       IF(caldyn_thermo == thermo_moist) THEN
465          !DIR$ SIMD
466          DO ij=ij_begin,ij_end         
467             due_right =  berni(ij+t_right,l)-berni(ij,l)       &
468                  + 0.5*(theta(ij,l,1)+theta(ij+t_right,l,1))   &
469                       *(pk(ij+t_right,l)-pk(ij,l))             &
470                  + 0.5*(theta(ij,l,2)+theta(ij+t_right,l,2))   &
471                       *(berniv(ij+t_right,l)-berniv(ij,l))
472             
473             due_lup = berni(ij+t_lup,l)-berni(ij,l)            &
474                  + 0.5*(theta(ij,l,1)+theta(ij+t_lup,l,1))     &
475                       *(pk(ij+t_lup,l)-pk(ij,l))               &
476                  + 0.5*(theta(ij,l,2)+theta(ij+t_lup,l,2))     &
477                       *(berniv(ij+t_lup,l)-berniv(ij,l))
478             
479             due_ldown = berni(ij+t_ldown,l)-berni(ij,l)        &
480                  + 0.5*(theta(ij,l,1)+theta(ij+t_ldown,l,1))   &
481                       *(pk(ij+t_ldown,l)-pk(ij,l))             &
482                  + 0.5*(theta(ij,l,2)+theta(ij+t_ldown,l,2))   &
483                       *(berniv(ij+t_ldown,l)-berniv(ij,l))
484             
485             du(ij+u_right,l) = du(ij+u_right,l) - ne_right*due_right
486             du(ij+u_lup,l)   = du(ij+u_lup,l)   - ne_lup*due_lup
487             du(ij+u_ldown,l) = du(ij+u_ldown,l) - ne_ldown*due_ldown
488             u(ij+u_right,l) = u(ij+u_right,l) + tau*du(ij+u_right,l)
489             u(ij+u_lup,l)   = u(ij+u_lup,l)   + tau*du(ij+u_lup,l)
490             u(ij+u_ldown,l) = u(ij+u_ldown,l) + tau*du(ij+u_ldown,l)
491          END DO
492       ELSE
493          !DIR$ SIMD
494          DO ij=ij_begin,ij_end         
495             due_right =  0.5*(theta(ij,l,1)+theta(ij+t_right,l,1))  &
496                  *(pk(ij+t_right,l)-pk(ij,l))        &
497                  +  berni(ij+t_right,l)-berni(ij,l)
498             due_lup = 0.5*(theta(ij,l,1)+theta(ij+t_lup,l,1))    &
499                  *(pk(ij+t_lup,l)-pk(ij,l))          &
500                  +  berni(ij+t_lup,l)-berni(ij,l)
501             due_ldown = 0.5*(theta(ij,l,1)+theta(ij+t_ldown,l,1)) &
502                  *(pk(ij+t_ldown,l)-pk(ij,l))      &
503                  +   berni(ij+t_ldown,l)-berni(ij,l)
504             du(ij+u_right,l) = du(ij+u_right,l) - ne_right*due_right
505             du(ij+u_lup,l)   = du(ij+u_lup,l)   - ne_lup*due_lup
506             du(ij+u_ldown,l) = du(ij+u_ldown,l) - ne_ldown*due_ldown
507             u(ij+u_right,l) = u(ij+u_right,l) + tau*du(ij+u_right,l)
508             u(ij+u_lup,l)   = u(ij+u_lup,l)   + tau*du(ij+u_lup,l)
509             u(ij+u_ldown,l) = u(ij+u_ldown,l) + tau*du(ij+u_ldown,l)
510          END DO
511       END IF
512    END DO
513
514    END IF ! dysl
515    CALL trace_end("compute_caldyn_fast")
516
517  END SUBROUTINE compute_caldyn_fast
518
519  SUBROUTINE compute_caldyn_Coriolis(hflux,theta,qu, convm,dtheta_rhodz,du)
520    REAL(rstd),INTENT(IN)  :: hflux(3*iim*jjm,llm)  ! hflux in kg/s
521    REAL(rstd),INTENT(IN)  :: theta(iim*jjm,llm,nqdyn) ! active scalars
522    REAL(rstd),INTENT(IN)  :: qu(3*iim*jjm,llm)
523    REAL(rstd),INTENT(OUT) :: convm(iim*jjm,llm)  ! mass flux convergence
524    REAL(rstd),INTENT(OUT) :: dtheta_rhodz(iim*jjm,llm,nqdyn)
525    REAL(rstd),INTENT(INOUT) :: du(3*iim*jjm,llm)
526   
527    REAL(rstd) :: Ftheta(3*iim*jjm,llm)  ! potential temperature flux
528    REAL(rstd) :: uu_right, uu_lup, uu_ldown, du_trisk, divF
529    INTEGER :: ij,iq,l,kdown
530
531    CALL trace_start("compute_caldyn_Coriolis")
532
533    IF(dysl_caldyn_coriolis) THEN
534#ifdef CPP_DYSL
535#include "../kernels/coriolis.k90"
536#else
537    STOP 'dysl_caldyn_coriolis is .TRUE. but DYNAMICO is compiled without the -dysl option'
538#endif
539
540    ELSE
541#define FTHETA(ij) Ftheta(ij,1)
542
543    DO l=ll_begin, ll_end
544       ! compute theta flux
545       DO iq=1,nqdyn
546       !DIR$ SIMD
547          DO ij=ij_begin_ext,ij_end_ext     
548             FTHETA(ij+u_right) = 0.5*(theta(ij,l,iq)+theta(ij+t_right,l,iq)) &
549                                  * hflux(ij+u_right,l)
550             FTHETA(ij+u_lup)   = 0.5*(theta(ij,l,iq)+theta(ij+t_lup,l,iq)) &
551                  * hflux(ij+u_lup,l)
552             FTHETA(ij+u_ldown) = 0.5*(theta(ij,l,iq)+theta(ij+t_ldown,l,iq)) &
553                  * hflux(ij+u_ldown,l)
554          END DO
555          ! horizontal divergence of fluxes
556       !DIR$ SIMD
557          DO ij=ij_begin,ij_end         
558             ! dtheta_rhodz =  -div(flux.theta)
559             dtheta_rhodz(ij,l,iq)= &
560                  -1./Ai(ij)*(ne_right*FTHETA(ij+u_right)    +  &
561                  ne_rup*FTHETA(ij+u_rup)        +  & 
562                  ne_lup*FTHETA(ij+u_lup)        +  & 
563                  ne_left*FTHETA(ij+u_left)      +  & 
564                  ne_ldown*FTHETA(ij+u_ldown)    +  &
565                  ne_rdown*FTHETA(ij+u_rdown) )
566          END DO
567       END DO
568
569       !DIR$ SIMD
570       DO ij=ij_begin,ij_end         
571          ! convm = -div(mass flux), sign convention as in Ringler et al. 2012, eq. 21
572          convm(ij,l)= -1./Ai(ij)*(ne_right*hflux(ij+u_right,l)   +  &
573               ne_rup*hflux(ij+u_rup,l)       +  & 
574               ne_lup*hflux(ij+u_lup,l)       +  & 
575               ne_left*hflux(ij+u_left,l)     +  & 
576               ne_ldown*hflux(ij+u_ldown,l)   +  & 
577               ne_rdown*hflux(ij+u_rdown,l))
578       END DO ! ij
579    END DO ! llm
580
581!!! Compute potential vorticity (Coriolis) contribution to du
582    SELECT CASE(caldyn_conserv)
583
584    CASE(energy) ! energy-conserving TRiSK
585
586       DO l=ll_begin,ll_end
587          !DIR$ SIMD
588          DO ij=ij_begin,ij_end         
589             uu_right = &
590                  wee(ij+u_right,1,1)*hflux(ij+u_rup,l)*(qu(ij+u_right,l)+qu(ij+u_rup,l))+                             &
591                  wee(ij+u_right,2,1)*hflux(ij+u_lup,l)*(qu(ij+u_right,l)+qu(ij+u_lup,l))+                             &
592                  wee(ij+u_right,3,1)*hflux(ij+u_left,l)*(qu(ij+u_right,l)+qu(ij+u_left,l))+                           &
593                  wee(ij+u_right,4,1)*hflux(ij+u_ldown,l)*(qu(ij+u_right,l)+qu(ij+u_ldown,l))+                         &
594                  wee(ij+u_right,5,1)*hflux(ij+u_rdown,l)*(qu(ij+u_right,l)+qu(ij+u_rdown,l))+                         & 
595                  wee(ij+u_right,1,2)*hflux(ij+t_right+u_ldown,l)*(qu(ij+u_right,l)+qu(ij+t_right+u_ldown,l))+         &
596                  wee(ij+u_right,2,2)*hflux(ij+t_right+u_rdown,l)*(qu(ij+u_right,l)+qu(ij+t_right+u_rdown,l))+         &
597                  wee(ij+u_right,3,2)*hflux(ij+t_right+u_right,l)*(qu(ij+u_right,l)+qu(ij+t_right+u_right,l))+         &
598                  wee(ij+u_right,4,2)*hflux(ij+t_right+u_rup,l)*(qu(ij+u_right,l)+qu(ij+t_right+u_rup,l))+             &
599                  wee(ij+u_right,5,2)*hflux(ij+t_right+u_lup,l)*(qu(ij+u_right,l)+qu(ij+t_right+u_lup,l))
600             uu_lup = &
601                  wee(ij+u_lup,1,1)*hflux(ij+u_left,l)*(qu(ij+u_lup,l)+qu(ij+u_left,l)) +                        &
602                  wee(ij+u_lup,2,1)*hflux(ij+u_ldown,l)*(qu(ij+u_lup,l)+qu(ij+u_ldown,l)) +                      &
603                  wee(ij+u_lup,3,1)*hflux(ij+u_rdown,l)*(qu(ij+u_lup,l)+qu(ij+u_rdown,l)) +                      &
604                  wee(ij+u_lup,4,1)*hflux(ij+u_right,l)*(qu(ij+u_lup,l)+qu(ij+u_right,l)) +                      &
605                  wee(ij+u_lup,5,1)*hflux(ij+u_rup,l)*(qu(ij+u_lup,l)+qu(ij+u_rup,l)) +                          & 
606                  wee(ij+u_lup,1,2)*hflux(ij+t_lup+u_right,l)*(qu(ij+u_lup,l)+qu(ij+t_lup+u_right,l)) +          &
607                  wee(ij+u_lup,2,2)*hflux(ij+t_lup+u_rup,l)*(qu(ij+u_lup,l)+qu(ij+t_lup+u_rup,l)) +              &
608                  wee(ij+u_lup,3,2)*hflux(ij+t_lup+u_lup,l)*(qu(ij+u_lup,l)+qu(ij+t_lup+u_lup,l)) +              &
609                  wee(ij+u_lup,4,2)*hflux(ij+t_lup+u_left,l)*(qu(ij+u_lup,l)+qu(ij+t_lup+u_left,l)) +            &
610                  wee(ij+u_lup,5,2)*hflux(ij+t_lup+u_ldown,l)*(qu(ij+u_lup,l)+qu(ij+t_lup+u_ldown,l))
611             uu_ldown = &
612                  wee(ij+u_ldown,1,1)*hflux(ij+u_rdown,l)*(qu(ij+u_ldown,l)+qu(ij+u_rdown,l)) +                      &
613                  wee(ij+u_ldown,2,1)*hflux(ij+u_right,l)*(qu(ij+u_ldown,l)+qu(ij+u_right,l)) +                      &
614                  wee(ij+u_ldown,3,1)*hflux(ij+u_rup,l)*(qu(ij+u_ldown,l)+qu(ij+u_rup,l)) +                          &
615                  wee(ij+u_ldown,4,1)*hflux(ij+u_lup,l)*(qu(ij+u_ldown,l)+qu(ij+u_lup,l)) +                          &
616                  wee(ij+u_ldown,5,1)*hflux(ij+u_left,l)*(qu(ij+u_ldown,l)+qu(ij+u_left,l)) +                        & 
617                  wee(ij+u_ldown,1,2)*hflux(ij+t_ldown+u_lup,l)*(qu(ij+u_ldown,l)+qu(ij+t_ldown+u_lup,l)) +          &
618                  wee(ij+u_ldown,2,2)*hflux(ij+t_ldown+u_left,l)*(qu(ij+u_ldown,l)+qu(ij+t_ldown+u_left,l)) +        &
619                  wee(ij+u_ldown,3,2)*hflux(ij+t_ldown+u_ldown,l)*(qu(ij+u_ldown,l)+qu(ij+t_ldown+u_ldown,l)) +      &
620                  wee(ij+u_ldown,4,2)*hflux(ij+t_ldown+u_rdown,l)*(qu(ij+u_ldown,l)+qu(ij+t_ldown+u_rdown,l)) +      &
621                  wee(ij+u_ldown,5,2)*hflux(ij+t_ldown+u_right,l)*(qu(ij+u_ldown,l)+qu(ij+t_ldown+u_right,l))
622             du(ij+u_right,l) = du(ij+u_right,l) + .5*uu_right
623             du(ij+u_lup,l)   = du(ij+u_lup,l)   + .5*uu_lup
624             du(ij+u_ldown,l) = du(ij+u_ldown,l)   + .5*uu_ldown
625          ENDDO
626       ENDDO
627
628    CASE(enstrophy) ! enstrophy-conserving TRiSK
629
630       DO l=ll_begin,ll_end
631          !DIR$ SIMD
632          DO ij=ij_begin,ij_end         
633             uu_right = &
634                  wee(ij+u_right,1,1)*hflux(ij+u_rup,l)+                           &
635                  wee(ij+u_right,2,1)*hflux(ij+u_lup,l)+                           &
636                  wee(ij+u_right,3,1)*hflux(ij+u_left,l)+                          &
637                  wee(ij+u_right,4,1)*hflux(ij+u_ldown,l)+                         &
638                  wee(ij+u_right,5,1)*hflux(ij+u_rdown,l)+                         & 
639                  wee(ij+u_right,1,2)*hflux(ij+t_right+u_ldown,l)+                 &
640                  wee(ij+u_right,2,2)*hflux(ij+t_right+u_rdown,l)+                 &
641                  wee(ij+u_right,3,2)*hflux(ij+t_right+u_right,l)+                 &
642                  wee(ij+u_right,4,2)*hflux(ij+t_right+u_rup,l)+                   &
643                  wee(ij+u_right,5,2)*hflux(ij+t_right+u_lup,l)
644             uu_lup = &
645                  wee(ij+u_lup,1,1)*hflux(ij+u_left,l)+                        &
646                  wee(ij+u_lup,2,1)*hflux(ij+u_ldown,l)+                       &
647                  wee(ij+u_lup,3,1)*hflux(ij+u_rdown,l)+                       &
648                  wee(ij+u_lup,4,1)*hflux(ij+u_right,l)+                       &
649                  wee(ij+u_lup,5,1)*hflux(ij+u_rup,l)+                         & 
650                  wee(ij+u_lup,1,2)*hflux(ij+t_lup+u_right,l)+                 &
651                  wee(ij+u_lup,2,2)*hflux(ij+t_lup+u_rup,l)+                   &
652                  wee(ij+u_lup,3,2)*hflux(ij+t_lup+u_lup,l)+                   &
653                  wee(ij+u_lup,4,2)*hflux(ij+t_lup+u_left,l)+                  &
654                  wee(ij+u_lup,5,2)*hflux(ij+t_lup+u_ldown,l)
655             uu_ldown = &
656                  wee(ij+u_ldown,1,1)*hflux(ij+u_rdown,l)+                      &
657                  wee(ij+u_ldown,2,1)*hflux(ij+u_right,l)+                      &
658                  wee(ij+u_ldown,3,1)*hflux(ij+u_rup,l)+                        &
659                  wee(ij+u_ldown,4,1)*hflux(ij+u_lup,l)+                        &
660                  wee(ij+u_ldown,5,1)*hflux(ij+u_left,l)+                       & 
661                  wee(ij+u_ldown,1,2)*hflux(ij+t_ldown+u_lup,l)+                &
662                  wee(ij+u_ldown,2,2)*hflux(ij+t_ldown+u_left,l)+               &
663                  wee(ij+u_ldown,3,2)*hflux(ij+t_ldown+u_ldown,l)+              &
664                  wee(ij+u_ldown,4,2)*hflux(ij+t_ldown+u_rdown,l)+              &
665                  wee(ij+u_ldown,5,2)*hflux(ij+t_ldown+u_right,l)
666
667             du(ij+u_right,l) = du(ij+u_right,l) + .5*uu_right
668             du(ij+u_lup,l)   = du(ij+u_lup,l)   + .5*uu_lup
669             du(ij+u_ldown,l) = du(ij+u_ldown,l)   + .5*uu_ldown
670          END DO
671       END DO
672    CASE DEFAULT
673       STOP
674    END SELECT
675#undef FTHETA
676
677    END IF ! dysl
678
679    CALL trace_end("compute_caldyn_Coriolis")
680
681  END SUBROUTINE compute_caldyn_Coriolis
682
683  SUBROUTINE compute_caldyn_slow_hydro(u,rhodz,hflux,du, zero)
684    LOGICAL, INTENT(IN) :: zero
685    REAL(rstd),INTENT(IN)  :: u(3*iim*jjm,llm)    ! prognostic "velocity"
686    REAL(rstd),INTENT(IN)  :: rhodz(iim*jjm,llm)
687    REAL(rstd),INTENT(OUT) :: hflux(3*iim*jjm,llm) ! hflux in kg/s
688    REAL(rstd),INTENT(INOUT) :: du(3*iim*jjm,llm)
689   
690    REAL(rstd) :: berni(iim*jjm,llm)  ! Bernoulli function
691    REAL(rstd) :: uu_right, uu_lup, uu_ldown, ke, uu
692    INTEGER :: ij,l
693
694    CALL trace_start("compute_caldyn_slow_hydro")
695
696    IF(dysl_slow_hydro) THEN
697#ifdef CPP_DYSL
698#define BERNI(ij,l) berni(ij,l)
699#include "../kernels/caldyn_slow_hydro.k90"
700#undef BERNI
701#else
702        STOP 'dysl_slow_hydro=.TRUE. but DYNAMICO is compiled without the -dysl option'
703#endif
704
705     ELSE
706
707#define BERNI(ij) berni(ij,1)
708
709    DO l = ll_begin, ll_end
710       !  Compute mass fluxes
711       IF (caldyn_conserv==energy) CALL test_message(req_qu) 
712       !DIR$ SIMD
713       DO ij=ij_begin_ext,ij_end_ext
714          uu_right=0.5*(rhodz(ij,l)+rhodz(ij+t_right,l))*u(ij+u_right,l)
715          uu_lup=0.5*(rhodz(ij,l)+rhodz(ij+t_lup,l))*u(ij+u_lup,l)
716          uu_ldown=0.5*(rhodz(ij,l)+rhodz(ij+t_ldown,l))*u(ij+u_ldown,l)
717          uu_right= uu_right*le_de(ij+u_right)
718          uu_lup  = uu_lup  *le_de(ij+u_lup)
719          uu_ldown= uu_ldown*le_de(ij+u_ldown)
720          hflux(ij+u_right,l)=uu_right
721          hflux(ij+u_lup,l)  =uu_lup
722          hflux(ij+u_ldown,l)=uu_ldown
723       ENDDO
724       ! Compute Bernoulli=kinetic energy
725       !DIR$ SIMD
726       DO ij=ij_begin,ij_end         
727          BERNI(ij) = &
728               1/(4*Ai(ij))*(le_de(ij+u_right)*u(ij+u_right,l)**2 +    &
729               le_de(ij+u_rup)*u(ij+u_rup,l)**2 +          &
730               le_de(ij+u_lup)*u(ij+u_lup,l)**2 +          &
731               le_de(ij+u_left)*u(ij+u_left,l)**2 +       &
732               le_de(ij+u_ldown)*u(ij+u_ldown,l)**2 +    &
733               le_de(ij+u_rdown)*u(ij+u_rdown,l)**2 ) 
734       ENDDO
735       ! Compute du=-grad(Bernoulli)
736       IF(zero) THEN
737          !DIR$ SIMD
738          DO ij=ij_begin,ij_end
739             du(ij+u_right,l) = ne_right*(BERNI(ij)-BERNI(ij+t_right))
740             du(ij+u_lup,l)   = ne_lup*(BERNI(ij)-BERNI(ij+t_lup))
741             du(ij+u_ldown,l) = ne_ldown*(BERNI(ij)-BERNI(ij+t_ldown))
742          END DO
743       ELSE
744          !DIR$ SIMD
745          DO ij=ij_begin,ij_end
746             du(ij+u_right,l) = du(ij+u_right,l) + &
747                  ne_right*(BERNI(ij)-BERNI(ij+t_right))
748             du(ij+u_lup,l)   = du(ij+u_lup,l) + &
749                  ne_lup*(BERNI(ij)-BERNI(ij+t_lup))
750             du(ij+u_ldown,l) = du(ij+u_ldown,l) + &
751                  ne_ldown*(BERNI(ij)-BERNI(ij+t_ldown))
752          END DO
753       END IF
754    END DO
755#undef BERNI
756    END IF ! dysl
757    CALL trace_end("compute_caldyn_slow_hydro")   
758  END SUBROUTINE compute_caldyn_slow_hydro
759
760  SUBROUTINE compute_caldyn_slow_NH(u,rhodz,Phi,W, F_el,gradPhi2,w_il, hflux,du,dPhi,dW)
761    REAL(rstd),INTENT(IN)  :: u(3*iim*jjm,llm)    ! prognostic "velocity"
762    REAL(rstd),INTENT(IN)  :: rhodz(iim*jjm,llm)  ! rho*dz
763    REAL(rstd),INTENT(IN)  :: Phi(iim*jjm,llm+1)  ! prognostic geopotential
764    REAL(rstd),INTENT(IN)  :: W(iim*jjm,llm+1)    ! prognostic vertical momentum
765
766    REAL(rstd),INTENT(OUT) :: hflux(3*iim*jjm,llm) ! hflux in kg/s
767    REAL(rstd),INTENT(OUT) :: du(3*iim*jjm,llm)
768    REAL(rstd),INTENT(OUT) :: dW(iim*jjm,llm+1)
769    REAL(rstd),INTENT(OUT) :: dPhi(iim*jjm,llm+1)
770
771    REAL(rstd) :: w_il(iim*jjm,llm+1) ! Wil/mil
772    REAL(rstd) :: F_el(3*iim*jjm,llm+1) ! NH mass flux
773    REAL(rstd) :: gradPhi2(iim*jjm,llm+1) ! grad_Phi**2
774    REAL(rstd) :: DePhil(3*iim*jjm,llm+1) ! grad(Phi)
775   
776    INTEGER :: ij,l,kdown,kup
777    REAL(rstd) :: W_el, W2_el, uu_right, uu_lup, uu_ldown, gPhi2, dP, divG, u2, uu
778
779#ifdef CPP_DYSL
780    REAL(rstd) :: berni(iim*jjm,llm)  ! Bernoulli function
781    REAL(rstd) :: G_el(3*iim*jjm,llm+1) ! horizontal flux of W
782    REAL(rstd) :: v_el(3*iim*jjm,llm+1)
783#else
784    REAL(rstd) :: berni(iim*jjm)  ! Bernoulli function
785    REAL(rstd) :: G_el(3*iim*jjm) ! horizontal flux of W
786    REAL(rstd) :: v_el(3*iim*jjm)
787#endif
788
789    CALL trace_start("compute_caldyn_slow_NH")
790
791#ifdef CPP_DYSL
792!$OMP BARRIER
793#include "../kernels/caldyn_slow_NH.k90"
794!$OMP BARRIER
795#else
796    DO l=ll_begin, ll_endp1 ! compute on l levels (interfaces)
797       IF(l==1) THEN
798          kdown=1
799       ELSE
800          kdown=l-1
801       END IF
802       IF(l==llm+1) THEN
803          kup=llm
804       ELSE
805          kup=l
806       END IF
807       ! below : "checked" means "formula also valid when kup=kdown (top/bottom)"
808       ! compute mil, wil=Wil/mil
809       DO ij=ij_begin_ext, ij_end_ext
810          w_il(ij,l) = 2.*W(ij,l)/(rhodz(ij,kdown)+rhodz(ij,kup)) ! checked
811       END DO
812       ! compute DePhi, v_el, G_el, F_el
813       ! v_el, W2_el and therefore G_el incorporate metric factor le_de
814       ! while DePhil, W_el and F_el don't
815       DO ij=ij_begin_ext, ij_end_ext
816          ! Compute on edge 'right'
817          W_el  = .5*( W(ij,l)+W(ij+t_right,l) )
818          DePhil(ij+u_right,l) = ne_right*(Phi(ij+t_right,l)-Phi(ij,l))
819          F_el(ij+u_right,l)   = DePhil(ij+u_right,l)*W_el
820          W2_el = .5*le_de(ij+u_right) * &
821               ( W(ij,l)*w_il(ij,l) + W(ij+t_right,l)*w_il(ij+t_right,l) )
822          v_el(ij+u_right) = .5*le_de(ij+u_right)*(u(ij+u_right,kup)+u(ij+u_right,kdown)) ! checked
823          G_el(ij+u_right) = v_el(ij+u_right)*W_el - DePhil(ij+u_right,l)*W2_el
824          ! Compute on edge 'lup'
825          W_el  = .5*( W(ij,l)+W(ij+t_lup,l) )
826          DePhil(ij+u_lup,l) = ne_lup*(Phi(ij+t_lup,l)-Phi(ij,l))
827          F_el(ij+u_lup,l)   = DePhil(ij+u_lup,l)*W_el
828          W2_el = .5*le_de(ij+u_lup) * &
829               ( W(ij,l)*w_il(ij,l) + W(ij+t_lup,l)*w_il(ij+t_lup,l) )
830          v_el(ij+u_lup) = .5*le_de(ij+u_lup)*( u(ij+u_lup,kup) + u(ij+u_lup,kdown)) ! checked
831          G_el(ij+u_lup) = v_el(ij+u_lup)*W_el - DePhil(ij+u_lup,l)*W2_el
832          ! Compute on edge 'ldown'
833          W_el  = .5*( W(ij,l)+W(ij+t_ldown,l) )
834          DePhil(ij+u_ldown,l) = ne_ldown*(Phi(ij+t_ldown,l)-Phi(ij,l))
835          F_el(ij+u_ldown,l) = DePhil(ij+u_ldown,l)*W_el
836          W2_el = .5*le_de(ij+u_ldown) * &
837               ( W(ij,l)*w_il(ij,l) + W(ij+t_ldown,l)*w_il(ij+t_ldown,l) )
838          v_el(ij+u_ldown) = .5*le_de(ij+u_ldown)*( u(ij+u_ldown,kup) + u(ij+u_ldown,kdown)) ! checked
839          G_el(ij+u_ldown) = v_el(ij+u_ldown)*W_el - DePhil(ij+u_ldown,l)*W2_el
840       END DO
841       ! compute GradPhi2, dPhi, dW
842       DO ij=ij_begin_ext, ij_end_ext
843          gradPhi2(ij,l) = &
844               1/(2*Ai(ij))*(le_de(ij+u_right)*DePhil(ij+u_right,l)**2 + &
845               le_de(ij+u_rup)*DePhil(ij+u_rup,l)**2 +      &
846               le_de(ij+u_lup)*DePhil(ij+u_lup,l)**2 +      &
847               le_de(ij+u_left)*DePhil(ij+u_left,l)**2 +    &
848               le_de(ij+u_ldown)*DePhil(ij+u_ldown,l)**2 +  &
849               le_de(ij+u_rdown)*DePhil(ij+u_rdown,l)**2 )
850!          gradPhi2(ij,l) = 0. ! FIXME !!
851
852          dPhi(ij,l) = gradPhi2(ij,l)*w_il(ij,l) -1/(2*Ai(ij))* & 
853               ( DePhil(ij+u_right,l)*v_el(ij+u_right) + & ! -v.gradPhi,
854                 DePhil(ij+u_rup,l)*v_el(ij+u_rup) +     & ! v_el already has le_de
855                 DePhil(ij+u_lup,l)*v_el(ij+u_lup) +     &
856                 DePhil(ij+u_left,l)*v_el(ij+u_left) +   &
857                 DePhil(ij+u_ldown,l)*v_el(ij+u_ldown) + &
858                 DePhil(ij+u_rdown,l)*v_el(ij+u_rdown) )
859
860          dW(ij,l) = -1./Ai(ij)*(           & ! -div(G_el),
861               ne_right*G_el(ij+u_right) +  & ! G_el already has le_de
862               ne_rup*G_el(ij+u_rup) +      &
863               ne_lup*G_el(ij+u_lup) +      & 
864               ne_left*G_el(ij+u_left) +    &
865               ne_ldown*G_el(ij+u_ldown) +  &
866               ne_rdown*G_el(ij+u_rdown))
867       END DO
868    END DO
869
870    DO l=ll_begin, ll_end ! compute on k levels (layers)
871       ! Compute berni at scalar points
872       DO ij=ij_begin_ext, ij_end_ext
873          berni(ij) = &
874               1/(4*Ai(ij))*( &
875                    le_de(ij+u_right)*u(ij+u_right,l)**2 +    &
876                    le_de(ij+u_rup)*u(ij+u_rup,l)**2 +          &
877                    le_de(ij+u_lup)*u(ij+u_lup,l)**2 +          &
878                    le_de(ij+u_left)*u(ij+u_left,l)**2 +       &
879                    le_de(ij+u_ldown)*u(ij+u_ldown,l)**2 +    &
880                    le_de(ij+u_rdown)*u(ij+u_rdown,l)**2 ) &
881               - .25*( gradPhi2(ij,l)  *w_il(ij,l)**2 +   &
882                      gradPhi2(ij,l+1)*w_il(ij,l+1)**2 )
883       END DO
884       ! Compute mass flux and grad(berni) at edges
885       DO ij=ij_begin_ext, ij_end_ext
886          ! Compute on edge 'right'
887          uu_right = 0.5*(rhodz(ij,l)+rhodz(ij+t_right,l))*u(ij+u_right,l) &
888                    -0.5*(F_el(ij+u_right,l)+F_el(ij+u_right,l+1))
889          hflux(ij+u_right,l) = uu_right*le_de(ij+u_right)
890          du(ij+u_right,l) = ne_right*(berni(ij)-berni(ij+t_right))
891          ! Compute on edge 'lup'
892          uu_lup = 0.5*(rhodz(ij,l)+rhodz(ij+t_lup,l))*u(ij+u_lup,l) &
893                  -0.5*(F_el(ij+u_lup,l)+F_el(ij+u_lup,l+1))
894          hflux(ij+u_lup,l) = uu_lup*le_de(ij+u_lup)
895          du(ij+u_lup,l) = ne_lup*(berni(ij)-berni(ij+t_lup))
896          ! Compute on edge 'ldown'
897          uu_ldown = 0.5*(rhodz(ij,l)+rhodz(ij+t_ldown,l))*u(ij+u_ldown,l) &
898                    -0.5*(F_el(ij+u_ldown,l)+F_el(ij+u_ldown,l+1))
899          hflux(ij+u_ldown,l) = uu_ldown*le_de(ij+u_ldown)
900          du(ij+u_ldown,l) = ne_ldown*(berni(ij)-berni(ij+t_ldown))
901       END DO
902    END DO
903#endif
904
905    CALL trace_end("compute_caldyn_slow_NH")
906
907  END SUBROUTINE compute_caldyn_slow_NH
908
909END MODULE caldyn_kernels_hevi_mod
Note: See TracBrowser for help on using the repository browser.