source: codes/icosagcm/trunk/src/caldyn_kernels.f90 @ 521

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

Cleanup after fixing RK2.5

File size: 16.1 KB
Line 
1MODULE caldyn_kernels_mod
2  USE icosa
3  USE transfert_mod
4  USE caldyn_kernels_base_mod
5  IMPLICIT NONE
6  PRIVATE
7
8  PUBLIC :: compute_planetvel, compute_pvort, compute_geopot, &
9       compute_caldyn_horiz, compute_caldyn_vert
10CONTAINS
11
12  SUBROUTINE compute_planetvel(planetvel)
13    USE wind_mod
14    REAL(rstd),INTENT(OUT)  :: planetvel(iim*3*jjm)
15    REAL(rstd) :: ulon(iim*3*jjm)
16    REAL(rstd) :: ulat(iim*3*jjm)
17    REAL(rstd) :: lon,lat
18    INTEGER :: ij
19    DO ij=ij_begin_ext,ij_end_ext
20       ulon(ij+u_right)=radius*omega*cos(lat_e(ij+u_right))
21       ulat(ij+u_right)=0
22
23       ulon(ij+u_lup)=radius*omega*cos(lat_e(ij+u_lup))
24       ulat(ij+u_lup)=0
25
26       ulon(ij+u_ldown)=radius*omega*cos(lat_e(ij+u_ldown))
27       ulat(ij+u_ldown)=0
28    END DO
29    CALL compute_wind2D_perp_from_lonlat_compound(ulon, ulat, planetvel)
30  END SUBROUTINE compute_planetvel
31
32  SUBROUTINE compute_pvort(ps,u,theta_rhodz, rhodz,theta,qu,qv)
33    USE icosa
34    USE disvert_mod, ONLY : mass_dak, mass_dbk, caldyn_eta, eta_mass, ptop
35    USE trace
36    USE omp_para
37    IMPLICIT NONE
38    REAL(rstd),INTENT(IN)  :: u(iim*3*jjm,llm)
39    REAL(rstd),INTENT(IN)  :: ps(iim*jjm)
40    REAL(rstd),INTENT(IN)  :: theta_rhodz(iim*jjm,llm)
41    REAL(rstd),INTENT(INOUT) :: rhodz(iim*jjm,llm)
42    REAL(rstd),INTENT(OUT) :: theta(iim*jjm,llm)
43    REAL(rstd),INTENT(OUT) :: qu(iim*3*jjm,llm)
44    REAL(rstd),INTENT(OUT) :: qv(iim*2*jjm,llm)
45
46    INTEGER :: i,j,ij,l
47    REAL(rstd) :: etav,hv, m
48    CALL trace_start("compute_pvort") 
49
50!    IF(caldyn_eta==eta_mass) THEN
51!       CALL wait_message(req_ps)  ! COM00
52!    ELSE
53!       CALL wait_message(req_mass) ! COM00
54!    END IF
55!    CALL wait_message(req_theta_rhodz) ! COM01
56
57    IF(caldyn_eta==eta_mass) THEN ! Compute mass & theta
58       DO l = ll_begin,ll_end
59!          CALL test_message(req_u)
60          !DIR$ SIMD
61          DO ij=ij_begin_ext,ij_end_ext
62             m = mass_dak(l)+(ps(ij)*g+ptop)*mass_dbk(l) ! ps is actually Ms
63             rhodz(ij,l) = m/g
64             theta(ij,l) = theta_rhodz(ij,l)/rhodz(ij,l)
65          ENDDO
66       ENDDO
67    ELSE ! Compute only theta
68       DO l = ll_begin,ll_end
69 !         CALL test_message(req_u)
70          !DIR$ SIMD
71          DO ij=ij_begin_ext,ij_end_ext
72             theta(ij,l) = theta_rhodz(ij,l)/rhodz(ij,l)
73          ENDDO
74       ENDDO
75    END IF
76
77 !   CALL wait_message(req_u) ! COM02
78
79!!! Compute shallow-water potential vorticity
80    DO l = ll_begin,ll_end
81       !DIR$ SIMD
82       DO ij=ij_begin_ext,ij_end_ext
83          etav= 1./Av(ij+z_up)*(  ne_rup  * u(ij+u_rup,l)    &
84               + ne_left * u(ij+t_rup+u_left,l)              &
85               - ne_lup  * u(ij+u_lup,l) )                               
86          hv =   Riv2(ij,vup)          * rhodz(ij,l)         &
87               + Riv2(ij+t_rup,vldown) * rhodz(ij+t_rup,l)   &
88               + Riv2(ij+t_lup,vrdown) * rhodz(ij+t_lup,l)
89          qv(ij+z_up,l) = ( etav+fv(ij+z_up) )/hv
90         
91          etav = 1./Av(ij+z_down)*(  ne_ldown * u(ij+u_ldown,l)  &
92               + ne_right * u(ij+t_ldown+u_right,l)              &
93               - ne_rdown * u(ij+u_rdown,l) )
94          hv =   Riv2(ij,vdown)        * rhodz(ij,l)          &
95               + Riv2(ij+t_ldown,vrup) * rhodz(ij+t_ldown,l)  &
96               + Riv2(ij+t_rdown,vlup) * rhodz(ij+t_rdown,l)
97          qv(ij+z_down,l) =( etav+fv(ij+z_down) )/hv
98       ENDDO
99
100       !DIR$ SIMD
101       DO ij=ij_begin,ij_end
102          qu(ij+u_right,l) = 0.5*(qv(ij+z_rdown,l)+qv(ij+z_rup,l)) 
103          qu(ij+u_lup,l) = 0.5*(qv(ij+z_up,l)+qv(ij+z_lup,l)) 
104          qu(ij+u_ldown,l) = 0.5*(qv(ij+z_ldown,l)+qv(ij+z_down,l)) 
105       END DO
106
107    ENDDO
108
109    CALL trace_end("compute_pvort")
110  END SUBROUTINE compute_pvort
111
112  !************** caldyn_horiz = caldyn_fast + caldyn_slow + caldyn_coriolis ***************
113
114  SUBROUTINE compute_caldyn_horiz(u,rhodz,qu,theta,pk,geopot, hflux,convm, dtheta_rhodz, du)
115    USE icosa
116    USE disvert_mod
117    USE trace
118    USE omp_para
119    IMPLICIT NONE
120    REAL(rstd),INTENT(IN)  :: u(iim*3*jjm,llm)    ! prognostic "velocity"
121    REAL(rstd),INTENT(IN)  :: rhodz(iim*jjm,llm)
122    REAL(rstd),INTENT(IN)  :: qu(iim*3*jjm,llm)
123    REAL(rstd),INTENT(IN)  :: theta(iim*jjm,llm)  ! potential temperature
124    REAL(rstd),INTENT(INOUT) :: pk(iim*jjm,llm) ! Exner function
125    REAL(rstd),INTENT(IN)  :: geopot(iim*jjm,llm+1)    ! geopotential
126
127    REAL(rstd),INTENT(OUT) :: hflux(iim*3*jjm,llm) ! hflux in kg/s
128    REAL(rstd),INTENT(OUT) :: convm(iim*jjm,llm)  ! mass flux convergence
129    REAL(rstd),INTENT(OUT) :: dtheta_rhodz(iim*jjm,llm)
130    REAL(rstd),INTENT(OUT) :: du(iim*3*jjm,llm)
131
132    REAL(rstd) :: cor_NT(iim*jjm,llm)  ! NT coriolis force u.(du/dPhi)
133    REAL(rstd) :: urel(3*iim*jjm,llm)  ! relative velocity
134    REAL(rstd) :: Ftheta(3*iim*jjm,llm) ! theta flux
135    REAL(rstd) :: berni(iim*jjm,llm)  ! Bernoulli function
136    REAL(rstd) :: uu_right, uu_lup, uu_ldown
137
138    INTEGER :: i,j,ij,l
139    REAL(rstd) :: ww,uu
140
141    CALL trace_start("compute_caldyn_horiz")
142
143    !    CALL wait_message(req_theta_rhodz)
144
145    DO l = ll_begin, ll_end
146!!!  Compute mass and theta fluxes
147!       IF (caldyn_conserv==energy) CALL test_message(req_qu)
148       !DIR$ SIMD
149       DO ij=ij_begin_ext,ij_end_ext         
150          uu_right=0.5*(rhodz(ij,l)+rhodz(ij+t_right,l))*u(ij+u_right,l)
151          uu_lup=0.5*(rhodz(ij,l)+rhodz(ij+t_lup,l))*u(ij+u_lup,l)
152          uu_ldown=0.5*(rhodz(ij,l)+rhodz(ij+t_ldown,l))*u(ij+u_ldown,l)
153          uu_right= uu_right*le_de(ij+u_right)
154          uu_lup  = uu_lup  *le_de(ij+u_lup)
155          uu_ldown= uu_ldown*le_de(ij+u_ldown)
156          hflux(ij+u_right,l)=uu_right
157          hflux(ij+u_lup,l)  =uu_lup
158          hflux(ij+u_ldown,l)=uu_ldown
159!          hflux(ij+u_right,l)=0.5*(rhodz(ij,l)+rhodz(ij+t_right,l))*u(ij+u_right,l)*le(ij+u_right)
160!          hflux(ij+u_lup,l)=0.5*(rhodz(ij,l)+rhodz(ij+t_lup,l))*u(ij+u_lup,l)*le(ij+u_lup)
161!          hflux(ij+u_ldown,l)=0.5*(rhodz(ij,l)+rhodz(ij+t_ldown,l))*u(ij+u_ldown,l)*le(ij+u_ldown)
162          Ftheta(ij+u_right,l)=0.5*(theta(ij,l)+theta(ij+t_right,l))*hflux(ij+u_right,l)
163          Ftheta(ij+u_lup,l)=0.5*(theta(ij,l)+theta(ij+t_lup,l))*hflux(ij+u_lup,l)
164          Ftheta(ij+u_ldown,l)=0.5*(theta(ij,l)+theta(ij+t_ldown,l))*hflux(ij+u_ldown,l)
165       ENDDO
166
167!!! compute horizontal divergence of fluxes
168       !DIR$ SIMD
169       DO ij=ij_begin,ij_end         
170          ! convm = -div(mass flux), sign convention as in Ringler et al. 2012, eq. 21
171          convm(ij,l)= -1./Ai(ij)*(ne_right*hflux(ij+u_right,l)   +  &
172               ne_rup*hflux(ij+u_rup,l)       +  & 
173               ne_lup*hflux(ij+u_lup,l)       +  & 
174               ne_left*hflux(ij+u_left,l)     +  & 
175               ne_ldown*hflux(ij+u_ldown,l)   +  & 
176               ne_rdown*hflux(ij+u_rdown,l))   
177
178          ! signe ? attention d (rho theta dz)
179          ! dtheta_rhodz =  -div(flux.theta)
180          dtheta_rhodz(ij,l)=-1./Ai(ij)*(ne_right*Ftheta(ij+u_right,l)    +  &
181               ne_rup*Ftheta(ij+u_rup,l)        +  & 
182               ne_lup*Ftheta(ij+u_lup,l)        +  & 
183               ne_left*Ftheta(ij+u_left,l)      +  & 
184               ne_ldown*Ftheta(ij+u_ldown,l)    +  & 
185               ne_rdown*Ftheta(ij+u_rdown,l))
186       ENDDO
187
188    END DO
189
190!!! Compute potential vorticity (Coriolis) contribution to du
191
192    SELECT CASE(caldyn_conserv)
193    CASE(energy) ! energy-conserving TRiSK
194
195!       CALL wait_message(req_qu) ! COM03
196
197       DO l=ll_begin,ll_end
198          !DIR$ SIMD
199          DO ij=ij_begin,ij_end         
200
201             uu = wee(ij+u_right,1,1)*hflux(ij+u_rup,l)*(qu(ij+u_right,l)+qu(ij+u_rup,l))+                             &
202                  wee(ij+u_right,2,1)*hflux(ij+u_lup,l)*(qu(ij+u_right,l)+qu(ij+u_lup,l))+                             &
203                  wee(ij+u_right,3,1)*hflux(ij+u_left,l)*(qu(ij+u_right,l)+qu(ij+u_left,l))+                           &
204                  wee(ij+u_right,4,1)*hflux(ij+u_ldown,l)*(qu(ij+u_right,l)+qu(ij+u_ldown,l))+                         &
205                  wee(ij+u_right,5,1)*hflux(ij+u_rdown,l)*(qu(ij+u_right,l)+qu(ij+u_rdown,l))+                         & 
206                  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))+         &
207                  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))+         &
208                  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))+         &
209                  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))+             &
210                  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))
211             du(ij+u_right,l) = .5*uu
212
213             uu = wee(ij+u_lup,1,1)*hflux(ij+u_left,l)*(qu(ij+u_lup,l)+qu(ij+u_left,l)) +                        &
214                  wee(ij+u_lup,2,1)*hflux(ij+u_ldown,l)*(qu(ij+u_lup,l)+qu(ij+u_ldown,l)) +                      &
215                  wee(ij+u_lup,3,1)*hflux(ij+u_rdown,l)*(qu(ij+u_lup,l)+qu(ij+u_rdown,l)) +                      &
216                  wee(ij+u_lup,4,1)*hflux(ij+u_right,l)*(qu(ij+u_lup,l)+qu(ij+u_right,l)) +                      &
217                  wee(ij+u_lup,5,1)*hflux(ij+u_rup,l)*(qu(ij+u_lup,l)+qu(ij+u_rup,l)) +                          & 
218                  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)) +          &
219                  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)) +              &
220                  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)) +              &
221                  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)) +            &
222                  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))
223             du(ij+u_lup,l) = .5*uu
224
225             uu = wee(ij+u_ldown,1,1)*hflux(ij+u_rdown,l)*(qu(ij+u_ldown,l)+qu(ij+u_rdown,l)) +                      &
226                  wee(ij+u_ldown,2,1)*hflux(ij+u_right,l)*(qu(ij+u_ldown,l)+qu(ij+u_right,l)) +                      &
227                  wee(ij+u_ldown,3,1)*hflux(ij+u_rup,l)*(qu(ij+u_ldown,l)+qu(ij+u_rup,l)) +                          &
228                  wee(ij+u_ldown,4,1)*hflux(ij+u_lup,l)*(qu(ij+u_ldown,l)+qu(ij+u_lup,l)) +                          &
229                  wee(ij+u_ldown,5,1)*hflux(ij+u_left,l)*(qu(ij+u_ldown,l)+qu(ij+u_left,l)) +                        & 
230                  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)) +          &
231                  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)) +        &
232                  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)) +      &
233                  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)) +      &
234                  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))
235             du(ij+u_ldown,l) = .5*uu
236
237          ENDDO
238       ENDDO
239
240    CASE(enstrophy) ! enstrophy-conserving TRiSK
241
242       DO l=ll_begin,ll_end
243          !DIR$ SIMD
244          DO ij=ij_begin,ij_end         
245
246             uu = wee(ij+u_right,1,1)*hflux(ij+u_rup,l)+                           &
247                  wee(ij+u_right,2,1)*hflux(ij+u_lup,l)+                           &
248                  wee(ij+u_right,3,1)*hflux(ij+u_left,l)+                          &
249                  wee(ij+u_right,4,1)*hflux(ij+u_ldown,l)+                         &
250                  wee(ij+u_right,5,1)*hflux(ij+u_rdown,l)+                         & 
251                  wee(ij+u_right,1,2)*hflux(ij+t_right+u_ldown,l)+                 &
252                  wee(ij+u_right,2,2)*hflux(ij+t_right+u_rdown,l)+                 &
253                  wee(ij+u_right,3,2)*hflux(ij+t_right+u_right,l)+                 &
254                  wee(ij+u_right,4,2)*hflux(ij+t_right+u_rup,l)+                   &
255                  wee(ij+u_right,5,2)*hflux(ij+t_right+u_lup,l)
256             du(ij+u_right,l) = qu(ij+u_right,l)*uu
257
258
259             uu = wee(ij+u_lup,1,1)*hflux(ij+u_left,l)+                        &
260                  wee(ij+u_lup,2,1)*hflux(ij+u_ldown,l)+                       &
261                  wee(ij+u_lup,3,1)*hflux(ij+u_rdown,l)+                       &
262                  wee(ij+u_lup,4,1)*hflux(ij+u_right,l)+                       &
263                  wee(ij+u_lup,5,1)*hflux(ij+u_rup,l)+                         & 
264                  wee(ij+u_lup,1,2)*hflux(ij+t_lup+u_right,l)+                 &
265                  wee(ij+u_lup,2,2)*hflux(ij+t_lup+u_rup,l)+                   &
266                  wee(ij+u_lup,3,2)*hflux(ij+t_lup+u_lup,l)+                   &
267                  wee(ij+u_lup,4,2)*hflux(ij+t_lup+u_left,l)+                  &
268                  wee(ij+u_lup,5,2)*hflux(ij+t_lup+u_ldown,l)
269             du(ij+u_lup,l) = qu(ij+u_lup,l)*uu
270
271             uu = wee(ij+u_ldown,1,1)*hflux(ij+u_rdown,l)+                      &
272                  wee(ij+u_ldown,2,1)*hflux(ij+u_right,l)+                      &
273                  wee(ij+u_ldown,3,1)*hflux(ij+u_rup,l)+                        &
274                  wee(ij+u_ldown,4,1)*hflux(ij+u_lup,l)+                        &
275                  wee(ij+u_ldown,5,1)*hflux(ij+u_left,l)+                       & 
276                  wee(ij+u_ldown,1,2)*hflux(ij+t_ldown+u_lup,l)+                &
277                  wee(ij+u_ldown,2,2)*hflux(ij+t_ldown+u_left,l)+               &
278                  wee(ij+u_ldown,3,2)*hflux(ij+t_ldown+u_ldown,l)+              &
279                  wee(ij+u_ldown,4,2)*hflux(ij+t_ldown+u_rdown,l)+              &
280                  wee(ij+u_ldown,5,2)*hflux(ij+t_ldown+u_right,l)
281             du(ij+u_ldown,l) = qu(ij+u_ldown,l)*uu
282
283          ENDDO
284       ENDDO
285
286    CASE DEFAULT
287       STOP
288    END SELECT
289
290!!! Compute bernouilli term = Kinetic Energy + geopotential
291    IF(boussinesq) THEN
292       DO l=ll_begin,ll_end
293          !DIR$ SIMD
294          DO ij=ij_begin,ij_end         
295             berni(ij,l) = pk(ij,l) + 1/(4*Ai(ij))*( &
296                  le_de(ij+u_right)*u(ij+u_right,l)**2 +    &
297                  le_de(ij+u_rup)*u(ij+u_rup,l)**2 +          &
298                  le_de(ij+u_lup)*u(ij+u_lup,l)**2 +          &
299                  le_de(ij+u_left)*u(ij+u_left,l)**2 +       &
300                  le_de(ij+u_ldown)*u(ij+u_ldown,l)**2 +    &
301                  le_de(ij+u_rdown)*u(ij+u_rdown,l)**2 ) 
302             ! from now on pk contains the vertically-averaged geopotential
303             pk(ij,l) = .5*(geopot(ij,l)+geopot(ij,l+1))
304          ENDDO
305       ENDDO
306
307    ELSE ! compressible
308
309       DO l=ll_begin,ll_end
310          !DIR$ SIMD
311          DO ij=ij_begin,ij_end         
312             berni(ij,l) = .5*(geopot(ij,l)+geopot(ij,l+1)) &
313                  + 1/(4*Ai(ij))*( &
314                  le_de(ij+u_right)*u(ij+u_right,l)**2 +    &
315                  le_de(ij+u_rup)*u(ij+u_rup,l)**2 +          &
316                  le_de(ij+u_lup)*u(ij+u_lup,l)**2 +          &
317                  le_de(ij+u_left)*u(ij+u_left,l)**2 +       &
318                  le_de(ij+u_ldown)*u(ij+u_ldown,l)**2 +    &
319                  le_de(ij+u_rdown)*u(ij+u_rdown,l)**2 ) 
320          ENDDO
321       ENDDO
322
323    END IF ! Boussinesq/compressible
324
325!!! Add gradients of Bernoulli and Exner functions to du
326    DO l=ll_begin,ll_end
327       !DIR$ SIMD
328       DO ij=ij_begin,ij_end         
329
330          du(ij+u_right,l) = du(ij+u_right,l) + (             &
331               0.5*(theta(ij,l)+theta(ij+t_right,l))                &
332               *( ne_right*pk(ij,l)+ne_left*pk(ij+t_right,l))    &
333               + ne_right*berni(ij,l)+ne_left*berni(ij+t_right,l) )
334
335
336          du(ij+u_lup,l) = du(ij+u_lup,l) +  (                  &
337               0.5*(theta(ij,l)+theta(ij+t_lup,l))                  &
338               *( ne_lup*pk(ij,l)+ne_rdown*pk(ij+t_lup,l))       &
339               + ne_lup*berni(ij,l)+ne_rdown*berni(ij+t_lup,l) )
340
341          du(ij+u_ldown,l) = du(ij+u_ldown,l) + (             &
342               0.5*(theta(ij,l)+theta(ij+t_ldown,l))                &
343               *( ne_ldown*pk(ij,l)+ne_rup*pk(ij+t_ldown,l))     &
344               + ne_ldown*berni(ij,l)+ne_rup*berni(ij+t_ldown,l) )
345
346       ENDDO
347    ENDDO
348
349    CALL trace_end("compute_caldyn_horiz")
350
351  END SUBROUTINE compute_caldyn_horiz
352
353END MODULE caldyn_kernels_mod
Note: See TracBrowser for help on using the repository browser.