LMDZ
climb_wind_mod.F90
Go to the documentation of this file.
1 !
3 !
4 ! Module to solve the verctical diffusion of the wind components "u" and "v".
5 !
6  USE dimphy
7 
8  IMPLICIT NONE
9 
10  SAVE
11  PRIVATE
12 
13  REAL, DIMENSION(:), ALLOCATABLE :: alf1, alf2
14  !$OMP THREADPRIVATE(alf1,alf2)
15  REAL, DIMENSION(:,:), ALLOCATABLE :: kcoefm
16  !$OMP THREADPRIVATE(Kcoefm)
17  REAL, DIMENSION(:,:), ALLOCATABLE :: ccoef_u, dcoef_u
18  !$OMP THREADPRIVATE(Ccoef_U, Dcoef_U)
19  REAL, DIMENSION(:,:), ALLOCATABLE :: ccoef_v, dcoef_v
20  !$OMP THREADPRIVATE(Ccoef_V, Dcoef_V)
21  REAL, DIMENSION(:), ALLOCATABLE :: acoef_u, bcoef_u
22  !$OMP THREADPRIVATE(Acoef_U, Bcoef_U)
23  REAL, DIMENSION(:), ALLOCATABLE :: acoef_v, bcoef_v
24  !$OMP THREADPRIVATE(Acoef_V, Bcoef_V)
25  LOGICAL :: firstcall=.true.
26  !$OMP THREADPRIVATE(firstcall)
27 
28 
30 
31 CONTAINS
32 !
33 !****************************************************************************************
34 !
35  SUBROUTINE climb_wind_init
36 
37  INTEGER :: ierr
38  CHARACTER(len = 20) :: modname = 'climb_wind_init'
39 
40 !****************************************************************************************
41 ! Allocation of global module variables
42 !
43 !****************************************************************************************
44 
45  ALLOCATE(alf1(klon), stat=ierr)
46  IF (ierr /= 0) CALL abort_physic(modname,'Pb in allocate alf1',1)
47 
48  ALLOCATE(alf2(klon), stat=ierr)
49  IF (ierr /= 0) CALL abort_physic(modname,'Pb in allocate alf2',1)
50 
51  ALLOCATE(kcoefm(klon,klev), stat=ierr)
52  IF (ierr /= 0) CALL abort_physic(modname,'Pb in allocate Kcoefm',1)
53 
54  ALLOCATE(ccoef_u(klon,klev), stat=ierr)
55  IF (ierr /= 0) CALL abort_physic(modname,'Pb in allocate Ccoef_U',1)
56 
57  ALLOCATE(dcoef_u(klon,klev), stat=ierr)
58  IF (ierr /= 0) CALL abort_physic(modname,'Pb in allocation Dcoef_U',1)
59 
60  ALLOCATE(ccoef_v(klon,klev), stat=ierr)
61  IF (ierr /= 0) CALL abort_physic(modname,'Pb in allocation Ccoef_V',1)
62 
63  ALLOCATE(dcoef_v(klon,klev), stat=ierr)
64  IF (ierr /= 0) CALL abort_physic(modname,'Pb in allocation Dcoef_V',1)
65 
66  ALLOCATE(acoef_u(klon), bcoef_u(klon), acoef_v(klon), bcoef_v(klon), stat=ierr)
67  IF ( ierr /= 0 ) print*,' pb in allloc Acoef_U and Bcoef_U, ierr=', ierr
68 
70 
71  END SUBROUTINE climb_wind_init
72 !
73 !****************************************************************************************
74 !
75  SUBROUTINE climb_wind_down(knon, dtime, coef_in, pplay, paprs, temp, delp, u_old, v_old, &
76 !!! nrlmd le 02/05/2011
77  ccoef_u_out, ccoef_v_out, dcoef_u_out, dcoef_v_out, &
78  kcoef_m_out, alf_1_out, alf_2_out, &
79 !!!
80  acoef_u_out, acoef_v_out, bcoef_u_out, bcoef_v_out)
81 !
82 ! This routine calculates for the wind components u and v,
83 ! recursivly the coefficients C and D in equation
84 ! X(k) = C(k) + D(k)*X(k-1), X=[u,v], k=[1,klev] is the vertical layer.
85 !
86 !
87 
88 ! Input arguments
89 !****************************************************************************************
90  INTEGER, INTENT(IN) :: knon
91  REAL, INTENT(IN) :: dtime
92  REAL, DIMENSION(klon,klev), INTENT(IN) :: coef_in
93  REAL, DIMENSION(klon,klev), INTENT(IN) :: pplay ! pres au milieu de couche (Pa)
94  REAL, DIMENSION(klon,klev+1), INTENT(IN) :: paprs ! pression a inter-couche (Pa)
95  REAL, DIMENSION(klon,klev), INTENT(IN) :: temp ! temperature
96  REAL, DIMENSION(klon,klev), INTENT(IN) :: delp
97  REAL, DIMENSION(klon,klev), INTENT(IN) :: u_old
98  REAL, DIMENSION(klon,klev), INTENT(IN) :: v_old
99 
100 ! Output arguments
101 !****************************************************************************************
102  REAL, DIMENSION(klon), INTENT(OUT) :: Acoef_U_out
103  REAL, DIMENSION(klon), INTENT(OUT) :: Acoef_V_out
104  REAL, DIMENSION(klon), INTENT(OUT) :: Bcoef_U_out
105  REAL, DIMENSION(klon), INTENT(OUT) :: Bcoef_V_out
106 
107 !!! nrlmd le 02/05/2011
108  REAL, DIMENSION(klon,klev), INTENT(OUT) :: Ccoef_U_out
109  REAL, DIMENSION(klon,klev), INTENT(OUT) :: Ccoef_V_out
110  REAL, DIMENSION(klon,klev), INTENT(OUT) :: Dcoef_U_out
111  REAL, DIMENSION(klon,klev), INTENT(OUT) :: Dcoef_V_out
112  REAL, DIMENSION(klon,klev), INTENT(OUT) :: Kcoef_m_out
113  REAL, DIMENSION(klon), INTENT(OUT) :: alf_1_out
114  REAL, DIMENSION(klon), INTENT(OUT) :: alf_2_out
115 !!!
116 
117 ! Local variables
118 !****************************************************************************************
119  REAL, DIMENSION(klon) :: u1lay, v1lay
120  INTEGER :: k, i
121 
122 ! Include
123 !****************************************************************************************
124  include "YOMCST.h"
125  include "compbl.h"
126 
127 !****************************************************************************************
128 ! Initialize module
129  IF (firstcall) CALL climb_wind_init
130 
131 !****************************************************************************************
132 ! Calculate the coefficients C and D in : u(k) = C(k) + D(k)*u(k-1)
133 !
134 !****************************************************************************************
135 ! - Define alpha (alf1 and alf2)
136  alf1(:) = 1.0
137  alf2(:) = 1.0 - alf1(:)
138 
139 ! - Calculate the coefficients K
140  kcoefm(:,:) = 0.0
141  DO k = 2, klev
142  DO i=1,knon
143  kcoefm(i,k) = coef_in(i,k)*rg*rg*dtime/(pplay(i,k-1)-pplay(i,k)) &
144  *(paprs(i,k)*2/(temp(i,k)+temp(i,k-1))/rd)**2
145  END DO
146  END DO
147 
148 ! - Calculate the coefficients C and D, component "u"
149  CALL calc_coef(knon, kcoefm(:,:), delp(:,:), &
150  u_old(:,:), alf1(:), alf2(:), &
151  ccoef_u(:,:), dcoef_u(:,:), acoef_u(:), bcoef_u(:))
152 
153 ! - Calculate the coefficients C and D, component "v"
154  CALL calc_coef(knon, kcoefm(:,:), delp(:,:), &
155  v_old(:,:), alf1(:), alf2(:), &
156  ccoef_v(:,:), dcoef_v(:,:), acoef_v(:), bcoef_v(:))
157 
158 !****************************************************************************************
159 ! 6)
160 ! Return the first layer in output variables
161 !
162 !****************************************************************************************
163  acoef_u_out = acoef_u
164  bcoef_u_out = bcoef_u
165  acoef_v_out = acoef_v
166  bcoef_v_out = bcoef_v
167 
168 !****************************************************************************************
169 ! 7)
170 ! If Pbl is split, return also the other layers in output variables
171 !
172 !****************************************************************************************
173 !!! jyg le 07/02/2012
174  IF (mod(iflag_pbl_split,2) .eq.1) THEN
175 !!! nrlmd le 02/05/2011
176  DO k= 1, klev
177  DO i= 1, klon
178  ccoef_u_out(i,k) = ccoef_u(i,k)
179  ccoef_v_out(i,k) = ccoef_v(i,k)
180  dcoef_u_out(i,k) = dcoef_u(i,k)
181  dcoef_v_out(i,k) = dcoef_v(i,k)
182  kcoef_m_out(i,k) = kcoefm(i,k)
183  ENDDO
184  ENDDO
185  DO i= 1, klon
186  alf_1_out(i) = alf1(i)
187  alf_2_out(i) = alf2(i)
188  ENDDO
189 !!!
190  ENDIF ! (mod(iflag_pbl_split,2) .eq.1)
191 !!!
192 
193  END SUBROUTINE climb_wind_down
194 !
195 !****************************************************************************************
196 !
197  SUBROUTINE calc_coef(knon, Kcoef, delp, X, alfa1, alfa2, Ccoef, Dcoef, Acoef, Bcoef)
198 !
199 ! Find the coefficients C and D in fonction of alfa, K and delp
200 !
201 ! Input arguments
202 !****************************************************************************************
203  INTEGER, INTENT(IN) :: knon
204  REAL, DIMENSION(klon,klev), INTENT(IN) :: Kcoef, delp
205  REAL, DIMENSION(klon,klev), INTENT(IN) :: X
206  REAL, DIMENSION(klon), INTENT(IN) :: alfa1, alfa2
207 
208 ! Output arguments
209 !****************************************************************************************
210  REAL, DIMENSION(klon), INTENT(OUT) :: Acoef, Bcoef
211  REAL, DIMENSION(klon,klev), INTENT(OUT) :: Ccoef, Dcoef
212 
213 ! local variables
214 !****************************************************************************************
215  INTEGER :: k, i
216  REAL :: buf
217 
218  include "YOMCST.h"
219 !****************************************************************************************
220 !
221 
222 ! Calculate coefficients C and D at top level, k=klev
223 !
224  ccoef(:,:) = 0.0
225  dcoef(:,:) = 0.0
226 
227  DO i = 1, knon
228  buf = delp(i,klev) + kcoef(i,klev)
229 
230  ccoef(i,klev) = x(i,klev)*delp(i,klev)/buf
231  dcoef(i,klev) = kcoef(i,klev)/buf
232  END DO
233 
234 !
235 ! Calculate coefficients C and D at top level (klev-1) <= k <= 2
236 !
237  DO k=(klev-1),2,-1
238  DO i = 1, knon
239  buf = delp(i,k) + kcoef(i,k) + kcoef(i,k+1)*(1.-dcoef(i,k+1))
240 
241  ccoef(i,k) = (x(i,k)*delp(i,k) + kcoef(i,k+1)*ccoef(i,k+1))/buf
242  dcoef(i,k) = kcoef(i,k)/buf
243  END DO
244  END DO
245 
246 !
247 ! Calculate coeffiecent A and B at surface
248 !
249  DO i = 1, knon
250  buf = delp(i,1) + kcoef(i,2)*(1-dcoef(i,2))
251  acoef(i) = (x(i,1)*delp(i,1) + kcoef(i,2)*ccoef(i,2))/buf
252  bcoef(i) = -rg/buf
253  END DO
254 
255  END SUBROUTINE calc_coef
256 !
257 !****************************************************************************************
258 !
259 
260  SUBROUTINE climb_wind_up(knon, dtime, u_old, v_old, flx_u1, flx_v1, &
261 !!! nrlmd le 02/05/2011
262  acoef_u_in, acoef_v_in, bcoef_u_in, bcoef_v_in, &
263  ccoef_u_in, ccoef_v_in, dcoef_u_in, dcoef_v_in, &
264  kcoef_m_in, &
265 !!!
266  flx_u_new, flx_v_new, d_u_new, d_v_new)
267 !
268 ! Diffuse the wind components from the surface layer and up to the top layer.
269 ! Coefficents A, B, C and D are known from before. Start values for the diffusion are the
270 ! momentum fluxes at surface.
271 !
272 ! u(k=1) = A + B*flx*dtime
273 ! u(k) = C(k) + D(k)*u(k-1) [2 <= k <= klev]
274 !
275 !****************************************************************************************
276 
277 ! Input arguments
278 !****************************************************************************************
279  INTEGER, INTENT(IN) :: knon
280  REAL, INTENT(IN) :: dtime
281  REAL, DIMENSION(klon,klev), INTENT(IN) :: u_old
282  REAL, DIMENSION(klon,klev), INTENT(IN) :: v_old
283  REAL, DIMENSION(klon), INTENT(IN) :: flx_u1, flx_v1 ! momentum flux
284 
285 !!! nrlmd le 02/05/2011
286  REAL, DIMENSION(klon), INTENT(IN) :: Acoef_U_in,Acoef_V_in, Bcoef_U_in, Bcoef_V_in
287  REAL, DIMENSION(klon,klev), INTENT(IN) :: Ccoef_U_in, Ccoef_V_in, Dcoef_U_in, Dcoef_V_in
288  REAL, DIMENSION(klon,klev), INTENT(IN) :: Kcoef_m_in
289 !!!
290 
291 ! Output arguments
292 !****************************************************************************************
293  REAL, DIMENSION(klon,klev), INTENT(OUT) :: flx_u_new, flx_v_new
294  REAL, DIMENSION(klon,klev), INTENT(OUT) :: d_u_new, d_v_new
295 
296 ! Local variables
297 !****************************************************************************************
298  REAL, DIMENSION(klon,klev) :: u_new, v_new
299  INTEGER :: k, i
300 
301 ! Include
302 !****************************************************************************************
303  include "YOMCST.h"
304  include "compbl.h"
305 
306 !
307 !****************************************************************************************
308 
309 !!! jyg le 07/02/2012
310  IF (mod(iflag_pbl_split,2) .eq.1) THEN
311 !!! nrlmd le 02/05/2011
312  DO i = 1, knon
313  acoef_u(i)=acoef_u_in(i)
314  acoef_v(i)=acoef_v_in(i)
315  bcoef_u(i)=bcoef_u_in(i)
316  bcoef_v(i)=bcoef_v_in(i)
317  ENDDO
318  DO k = 1, klev
319  DO i = 1, knon
320  ccoef_u(i,k)=ccoef_u_in(i,k)
321  ccoef_v(i,k)=ccoef_v_in(i,k)
322  dcoef_u(i,k)=dcoef_u_in(i,k)
323  dcoef_v(i,k)=dcoef_v_in(i,k)
324  kcoefm(i,k)=kcoef_m_in(i,k)
325  ENDDO
326  ENDDO
327 !!!
328  ENDIF ! (mod(iflag_pbl_split,2) .eq.1)
329 !!!
330 
331 ! Niveau 1
332  DO i = 1, knon
333  u_new(i,1) = acoef_u(i) + bcoef_u(i)*flx_u1(i)*dtime
334  v_new(i,1) = acoef_v(i) + bcoef_v(i)*flx_v1(i)*dtime
335  END DO
336 
337 ! Niveau 2 jusqu'au sommet klev
338  DO k = 2, klev
339  DO i=1, knon
340  u_new(i,k) = ccoef_u(i,k) + dcoef_u(i,k) * u_new(i,k-1)
341  v_new(i,k) = ccoef_v(i,k) + dcoef_v(i,k) * v_new(i,k-1)
342  END DO
343  END DO
344 
345 !****************************************************************************************
346 ! Calcul flux
347 !
348 !== flux_u/v est le flux de moment angulaire (positif vers bas)
349 !== dont l'unite est: (kg m/s)/(m**2 s)
350 !
351 !****************************************************************************************
352 !
353  flx_u_new(:,:) = 0.0
354  flx_v_new(:,:) = 0.0
355 
356  flx_u_new(1:knon,1)=flx_u1(1:knon)
357  flx_v_new(1:knon,1)=flx_v1(1:knon)
358 
359 ! Niveau 2->klev
360  DO k = 2, klev
361  DO i = 1, knon
362  flx_u_new(i,k) = kcoefm(i,k)/rg/dtime * &
363  (u_new(i,k)-u_new(i,k-1))
364 
365  flx_v_new(i,k) = kcoefm(i,k)/rg/dtime * &
366  (v_new(i,k)-v_new(i,k-1))
367  END DO
368  END DO
369 
370 !****************************************************************************************
371 ! Calcul tendances
372 !
373 !****************************************************************************************
374  d_u_new(:,:) = 0.0
375  d_v_new(:,:) = 0.0
376  DO k = 1, klev
377  DO i = 1, knon
378  d_u_new(i,k) = u_new(i,k) - u_old(i,k)
379  d_v_new(i,k) = v_new(i,k) - v_old(i,k)
380  END DO
381  END DO
382 
383  END SUBROUTINE climb_wind_up
384 !
385 !****************************************************************************************
386 !
387 END MODULE climb_wind_mod
real, dimension(:,:), allocatable ccoef_v
integer, save klon
Definition: dimphy.F90:3
subroutine calc_coef(knon, Kcoef, delp, X, alfa1, alfa2, Ccoef, Dcoef, Acoef, Bcoef)
integer, save klev
Definition: dimphy.F90:7
real, dimension(:), allocatable acoef_u
!$Id itapm1 ENDIF!IM on interpole les champs sur les niveaux STD de pression!IM a chaque pas de temps de la physique c!positionnement de l argument logique a false c!pour ne pas recalculer deux fois la meme chose!c!a cet effet un appel a plevel_new a ete deplace c!a la fin de la serie d appels c!la boucle DO nlevSTD a ete internalisee c!dans d ou la creation de cette routine c c!CALL false
Definition: calcul_STDlev.h:26
subroutine, public climb_wind_up(knon, dtime, u_old, v_old, flx_u1, flx_v1,
real, dimension(:), allocatable bcoef_u
subroutine climb_wind_init
real, dimension(:,:), allocatable kcoefm
real, dimension(:,:), allocatable dcoef_v
real, dimension(:,:), allocatable dcoef_u
real, dimension(:), allocatable alf2
real, dimension(:), allocatable bcoef_v
!$Id itapm1 ENDIF!IM on interpole les champs sur les niveaux STD de pression!IM a chaque pas de temps de la physique c!positionnement de l argument logique a false c!pour ne pas recalculer deux fois la meme chose!c!a cet effet un appel a plevel_new a ete deplace c!a la fin de la serie d appels c!la boucle DO nlevSTD a ete internalisee c!dans d ou la creation de cette routine c c!CALL ulevSTD CALL &zphi philevSTD CALL &zx_rh rhlevSTD!DO klev DO klon klev DO klon klev DO klon klev DO klon klev DO klon klev DO klon klev DO klon klev DO klon klev DO klon klev DO klon du jour ou toutes les read_climoz CALL true
real, dimension(:), allocatable acoef_v
subroutine abort_physic(modname, message, ierr)
Definition: abort_physic.F90:3
subroutine, public climb_wind_down(knon, dtime, coef_in, pplay, paprs, temp, delp, u_old, v_old,
Definition: dimphy.F90:1
real, dimension(:), allocatable alf1
real, dimension(:,:), allocatable ccoef_u
real rg
Definition: comcstphy.h:1