SURFEX v8.1
General documentation of Surfex
subscale_aos.F90
Go to the documentation of this file.
1 !SFX_LIC Copyright 1994-2014 CNRS, Meteo-France and Universite Paul Sabatier
2 !SFX_LIC This is part of the SURFEX software governed by the CeCILL-C licence
3 !SFX_LIC version 1. See LICENSE, CeCILL-C_V1-en.txt and CeCILL-C_V1-fr.txt
4 !SFX_LIC for details. version 1.
5 ! #########
6  SUBROUTINE subscale_aos (U, UG, USS, OZ0EFFI, OZ0EFFJ)
7 ! #############################################
8 !
9 !!*SUBSCALE_AOS computes the sum of the ratio: (h'-h)/L when h'/L >h/L
10 !! the ' is for subgrid scale orography
11 !!
12 !!
13 !! METHOD
14 !! ------
15 !! See M.Georgelin and al. July 1994, Monthly Weather Review.
16 !!
17 !! EXTERNAL
18 !! --------
19 !!
20 !! AUTHOR
21 !! ------
22 !!
23 !! M. Georgelin Laboratoire d'Aerologie
24 !!
25 !! MODIFICATION
26 !! ------------
27 !!
28 !! Original 18/12/95
29 !! (V. Masson) 10/03/97 rewrites the routine in doctor norm.
30 !! computations are made even if a only a few subsquares
31 !! contains data points.
32 !! returns to the calling routine the localization of
33 !! the points where the z0 coefficients are available.
34 !! (V. Masson) 03/2004 externalization
35 !!
36 !----------------------------------------------------------------------------
37 !
38 !* 0. DECLARATION
39 ! -----------
40 !
41 USE modd_surf_atm_n, ONLY : surf_atm_t
43 USE modd_sso_n, ONLY : sso_t
44 !
45 USE modd_surfex_mpi, ONLY : nrank, npio
46 USE modd_pgdwork, ONLY : nsso, xssqo, lssqo
47 USE modd_pgd_grid, ONLY : nl
48 !
49 USE modi_get_adjacent_meshes
52 !
53 USE yomhook ,ONLY : lhook, dr_hook
54 USE parkind1 ,ONLY : jprb
55 !
56 USE modi_get_mesh_dim
57 IMPLICIT NONE
58 !
59 !* 0.1 Declaration of dummy arguments
60 ! ------------------------------
61 !
62 TYPE(surf_atm_t), INTENT(INOUT) :: U
63 TYPE(surf_atm_grid_t), INTENT(INOUT) :: UG
64 TYPE(sso_t), INTENT(INOUT) :: USS
65 !
66 LOGICAL, DIMENSION(:), INTENT(OUT) :: OZ0EFFI! .T. : the z0eff coefficients
67 ! ! are computed at grid point
68 ! ! .F. : not enough sub-grid
69 ! ! information avalaible to
70 ! ! compute the coefficients
71 LOGICAL, DIMENSION(:), INTENT(OUT) :: OZ0EFFJ! .T. : the z0eff coefficients
72 ! ! are computed at grid point
73 ! ! .F. : not enough sub-grid
74 ! ! information avalaible to
75 ! ! compute the coefficients
76 !
77 !* 0.2 Declaration of indexes
78 ! ----------------------
79 !
80 INTEGER :: JS1, JS2
81 INTEGER :: JL ! loop index on grid meshs
82 INTEGER :: IL ! grid mesh index of second subgrid point used
83 INTEGER :: JISS, JJSS ! loop indexes for subsquares arrays
84 INTEGER :: JNEXT ! loop index on subgrid meshes
85 INTEGER :: INEXT ! index to add to JISS or JJSS to obtain the following
86 ! ! point containing a data in a segment
87 INTEGER, DIMENSION(:), ALLOCATABLE :: ILEFT ! index of left grid mesh
88 INTEGER, DIMENSION(:), ALLOCATABLE :: IRIGHT ! index of right grid mesh
89 INTEGER, DIMENSION(:), ALLOCATABLE :: ITOP ! index of top grid mesh
90 INTEGER, DIMENSION(:), ALLOCATABLE :: IBOTTOM ! index of bottom grid mesh
91 !
92 !* 0.3 Declaration of counters inside a grid (JL)
93 ! -----------------------
94 !
95 INTEGER :: IHO2COUNTERJP ! number of times where h/2 has been summed for JP coef
96 INTEGER :: IHO2COUNTERJM ! number of times where h/2 has been summed for JM coef
97 INTEGER :: IHO2COUNTERIP ! number of times where h/2 has been summed for IP coef
98 INTEGER :: IHO2COUNTERIM ! number of times where h/2 has been summed for IM coef
99 INTEGER :: IAOSCOUNTER ! number of segments where A/S has been summed
100 INTEGER :: IAOSDIST ! distance between first and last subsquares used in
101 ! ! computation of A/S in a subsegment of the grid
102 LOGICAL :: GFIRST ! T indicates the first point has been found for this segment.
103 !
104 !* 0.4 Declaration of working arrays inside a grid (JL)
105 ! -----------------------------
106 !
107 REAL, DIMENSION(NSSO) :: ZAOSIP ! A/S in each subsegment for IP coef.
108 REAL, DIMENSION(NSSO) :: ZAOSIM ! A/S in each subsegment for IM coef.
109 REAL, DIMENSION(NSSO) :: ZAOSJP ! A/S in each subsegment for JP coef.
110 REAL, DIMENSION(NSSO) :: ZAOSJM ! A/S in each subsegment for JM coef.
111 REAL :: ZAIP ! Area in a subsegment for IP coef.
112 REAL :: ZAIM ! Area in a subsegment for IM coef.
113 REAL :: ZAJP ! Area in a subsegment for JP coef.
114 REAL :: ZAJM ! Area in a subsegment for JM coef.
115 REAL :: ZSUMHO2IP ! sum of h/2 in the grid for IP coef.
116 REAL :: ZSUMHO2IM ! sum of h/2 in the grid for IM coef.
117 REAL :: ZSUMHO2JP ! sum of h/2 in the grid for JP coef.
118 REAL :: ZSUMHO2JM ! sum of h/2 in the grid for JM coef.
119 REAL :: ZSSAOS ! A/S between 2 following points along a subsegment
120 REAL :: ZSLOPE ! slope between 2 following points along a subsegment
121 REAL :: ZDXEFF ! width of a subsquare along I axis
122 REAL :: ZDYEFF ! width of a subsquare along J axis
123 !
124 !* 0.5 Declaration of other local variables
125 ! ------------------------------------
126 !
127 INTEGER, DIMENSION(:), ALLOCATABLE :: ISSO, ISSOT
128 INTEGER, DIMENSION(:,:,:), ALLOCATABLE :: ISSQOT, ISSQO
129 REAL, DIMENSION(:,:,:), ALLOCATABLE :: ZSSQO
130 LOGICAL, DIMENSION(:), ALLOCATABLE :: GZ0EFFI, GZ0EFFJ
131 REAL, DIMENSION(:), ALLOCATABLE :: ZDX, ZDY, ZSEA, ZAVG_ZS, ZMESH_SIZE ! grid mesh size in x direction
132 REAL, DIMENSION(:), ALLOCATABLE :: ZAOSIP_ALL, ZAOSIM_ALL, ZAOSJP_ALL, ZAOSJM_ALL
133 REAL, DIMENSION(:), ALLOCATABLE :: ZHO2IP_ALL, ZHO2IM_ALL, ZHO2JP_ALL, ZHO2JM_ALL
134 REAL :: ZSLOPEIP ! x mean slope
135 REAL :: ZSLOPEJP ! y mean slope
136 REAL(KIND=JPRB) :: ZHOOK_HANDLE
137 !----------------------------------------------------------------------------
138 !
139 !* 1. Initializations
140 ! ---------------
141 !
142 !* 1.1 Occurence of computation of the coefficients
143 ! --------------------------------------------
144 !
145 IF (lhook) CALL dr_hook('SUBSCALE_AOS',0,zhook_handle)
146 oz0effi(:)=.false.
147 oz0effj(:)=.false.
148 !
149 IF (nrank==npio) THEN
150  ALLOCATE(zsea(u%NDIM_FULL))
151  ALLOCATE(zavg_zs(u%NDIM_FULL))
152  ALLOCATE(zmesh_size(u%NDIM_FULL))
153  ALLOCATE(issqot(u%NDIM_FULL,nsso,nsso))
154  ALLOCATE(zssqo(u%NDIM_FULL,nsso,nsso))
155 ELSE
156  ALLOCATE(zsea(0))
157  ALLOCATE(zavg_zs(0))
158  ALLOCATE(issqot(0,0,0))
159  ALLOCATE(zssqo(0,0,0))
160 ENDIF
161 !
162  CALL gather_and_write_mpi(u%XSEA,zsea)
163  CALL gather_and_write_mpi(uss%XAVG_ZS,zavg_zs)
164  CALL gather_and_write_mpi(ug%G%XMESH_SIZE,zmesh_size)
165  CALL gather_and_write_mpi(xssqo,zssqo)
166 !
167 ALLOCATE(issqo(SIZE(xssqo,1),nsso,nsso))
168 issqo(:,:,:) = 0
169 WHERE (lssqo(:,:,:)) issqo(:,:,:) = 1
170  CALL gather_and_write_mpi(issqo,issqot)
171 DEALLOCATE(issqo)
172 !
173 !* 1.2 Grid dimension (meters)
174 ! -----------------------
175 !
176 IF (nrank==npio) THEN
177  !
178  ALLOCATE(zdx(u%NDIM_FULL),zdy(u%NDIM_FULL))
179  CALL get_mesh_dim(ug%G%CGRID,ug%NGRID_FULL_PAR,u%NDIM_FULL,ug%XGRID_FULL_PAR,zdx,zdy,zmesh_size)
180  DEALLOCATE(zmesh_size)
181  !
182  !
183  !* 1.3 Left, top, right and bottom adjacent gris meshes
184  ! ------------------------------------------------
185  !
186  ALLOCATE(ileft(u%NDIM_FULL),iright(u%NDIM_FULL),itop(u%NDIM_FULL),ibottom(u%NDIM_FULL))
187  CALL get_adjacent_meshes(ug%G%CGRID,ug%NGRID_FULL_PAR,u%NDIM_FULL,ug%XGRID_FULL_PAR,&
188  ileft,iright,itop,ibottom)
189  !
190  ALLOCATE(gz0effi(u%NDIM_FULL),gz0effj(u%NDIM_FULL))
191  ALLOCATE(zho2im_all(u%NDIM_FULL),zho2ip_all(u%NDIM_FULL),&
192  zaosim_all(u%NDIM_FULL),zaosip_all(u%NDIM_FULL))
193  ALLOCATE(zho2jm_all(u%NDIM_FULL),zho2jp_all(u%NDIM_FULL),&
194  zaosjm_all(u%NDIM_FULL),zaosjp_all(u%NDIM_FULL))
195  gz0effi(:) = .false.
196  gz0effj(:) = .false.
197  !
198  !* 1.4 Mean slopes between 2 grid meshes
199  ! -----------
200  !
201  !
202  DO jl=1,u%NDIM_FULL
203  !
204  zslopeip = 0.
205  zslopejp = 0.
206  !
207  IF (iright(jl)/=0 .AND. ileft(jl)/=0) THEN
208  zslopeip = 0.5 * ( zavg_zs(iright(jl)) - zavg_zs(jl) ) &
209  / ( 0.5 * (zdx(iright(jl)) + zdx(jl)) ) &
210  + 0.5 * ( zavg_zs(jl) - zavg_zs(ileft(jl)) ) &
211  / ( 0.5 * (zdx(jl) + zdx(ileft(jl))) )
212  ELSE
213  zslopeip = 0.
214  END IF
215  IF (itop(jl)/=0 .AND. ibottom(jl)/=0) THEN
216  zslopejp = 0.5 * ( zavg_zs(itop(jl)) - zavg_zs(jl) ) &
217  / ( 0.5 * (zdy(itop(jl)) + zdy(jl)) ) &
218  + 0.5 * ( zavg_zs(jl) - zavg_zs(ibottom(jl)) ) &
219  / ( 0.5 * (zdy(jl) + zdy(ibottom(jl))) )
220  ELSE
221  zslopejp = 0.
222  END IF
223 !
224 !----------------------------------------------------------------------------
225 !
226 !* 2. Loop on grid points
227 ! -------------------
228 !!
229 !* 2.1 No land in grid mesh
230 ! --------------------
231 !
232  IF (zsea(jl)==1.) cycle
233 !
234 !* 2.2 Index Initializations
235 ! ---------------------
236 !
237  zdxeff=zdx(jl)/float(nsso)
238  zdyeff=zdy(jl)/float(nsso)
239 !
240 !----------------------------------------------------------------------------
241 !
242 !* 3. Computations for IP and IM fields
243 ! ---------------------------------
244 !
245  zaosip(:)=0.
246  zaosim(:)=0.
247  zsumho2ip=0.
248  zsumho2im=0.
249  iho2counterip=0
250  iho2counterim=0
251  iaoscounter=0
252 !
253 !* 3.1 loop on jss index (there is no specific computation along j)
254 ! -----------------
255 !
256  DO jjss=1,nsso
257 !
258 !* 3.1.1 initializes counters for the A/S subscale segment computation
259 !
260  gfirst = .true.
261  iaosdist=0
262  zaip=0.
263  zaim=0.
264 !
265 !* 3.2 loop on iss index
266 ! -----------------
267 !
268  DO jiss=1,nsso
269 !
270 !* 3.3 search for two consecutive grid points
271 ! --------------------------------------
272 !
273 !* 3.3.1 first one
274 !
275  IF (issqot(jl,jiss,jjss)==0 ) cycle
276 !
277 !* 3.3.2 second one (up to one grid mesh further)
278 !
279  DO jnext=1,nsso
280  IF (jiss+jnext>nsso) THEN
281  il = iright(jl)
282  inext = jiss+jnext-nsso
283  ELSE
284  il = jl
285  inext = jiss+jnext
286  END IF
287  ! no right point
288  IF (il==0) EXIT
289  ! subgrid data found
290  IF (issqot(il,inext,jjss)==1) EXIT
291  END DO
292 !
293 !* 3.3.3 none found: end of loop along jss
294 ! ---------------------
295 !
296  IF (jnext>=nsso+1) EXIT
297 !
298 !* 3.3.4 second point outside of the domain: end of loop along iss
299 ! ---------------------
300 !
301  IF (il==0) EXIT
302 !
303 !* 3.4 add terms to sums of A/S and h/2
304 ! --------------------------------
305 !
306  IF (gfirst) iaoscounter=iaoscounter+1
307  gfirst = .false.
308  iaosdist =iaosdist+jnext
309 !
310 !* 3.4.1 mean slope
311 !
312  zslope=zslopeip
313 !
314 !* 3.4.2 A/S term
315 !
316  zssaos = zssqo(il,inext,jjss) - zssqo(jl,jiss,jjss) &
317  - zslope * zdxeff * jnext
318  IF (zssaos>0.) zaip=zaip+zssaos
319  IF (zssaos<0.) zaim=zaim-zssaos
320 !
321 !* 3.4.3 h/2 term
322 !
323  IF (zssaos>0.) THEN
324  zsumho2ip = zsumho2ip + 0.5 * zssaos
325  iho2counterip=iho2counterip+1
326  END IF
327  IF (zssaos<0.) THEN
328  zsumho2im = zsumho2im - 0.5 * zssaos
329  iho2counterim=iho2counterim+1
330  END IF
331 !
332 !* 3.5 end of loop on iss index
333 ! ------------------------
334 !
335  END DO
336  IF (iaosdist>0) THEN
337  zaosip(jjss)=zaip/(zdxeff*iaosdist)
338  zaosim(jjss)=zaim/(zdxeff*iaosdist)
339  END IF
340 !
341 !* 3.6 end of loop on jss index
342 ! ------------------------
343 !
344  END DO
345 !
346 !* 3.7 end of IP and IM coefficients
347 ! -----------------------------
348 !
349  IF (iaoscounter>0) THEN
350  zaosip_all(jl)=sum(zaosip) / iaoscounter
351  zaosim_all(jl)=sum(zaosim) / iaoscounter
352  IF (iho2counterip>0) THEN
353  zho2ip_all(jl)=zsumho2ip / iho2counterip
354  ELSE
355  zho2ip_all(jl)=0.
356  END IF
357  IF (iho2counterim>0) THEN
358  zho2im_all(jl)=zsumho2im / iho2counterim
359  ELSE
360  zho2im_all(jl)=0.
361  END IF
362  gz0effi(jl)=.true.
363  END IF
364 !
365 !----------------------------------------------------------------------------
366 !
367 !* 4. Computations for JP and JM fields
368 ! ---------------------------------
369 !
370  zaosjp(:)=0.
371  zaosjm(:)=0.
372  zsumho2jp=0.
373  zsumho2jm=0.
374  iho2counterjp=0
375  iho2counterjm=0
376  iaoscounter=0
377 !
378 !* 4.1 loop on iss index (there is no specific computation along i)
379 ! -----------------
380 !
381  DO jiss=1,nsso
382 !
383 !* 4.1.1 initializes counters for the A/S subscale segment computation
384 !
385  gfirst = .true.
386  iaosdist=0
387  zajp=0.
388  zajm=0.
389 !
390 !* 4.2 loop on jss index
391 ! -----------------
392 !
393  DO jjss=1,nsso
394 !
395 !* 4.3 search for two consecutive grid points
396 ! --------------------------------------
397 !
398 !* 4.3.1 first one
399 !
400  IF (issqot(jl,jiss,jjss)==0 ) cycle
401 !
402 !* 4.3.2 second one (up to one grid mesh further)
403 !
404  DO jnext=1,nsso
405  IF (jjss+jnext>nsso) THEN
406  il = itop(jl)
407  inext = jjss+jnext-nsso
408  ELSE
409  il = jl
410  inext = jjss+jnext
411  END IF
412  ! no right point
413  IF (il==0) EXIT
414  ! subgrid data found
415  IF (issqot(il,jiss,inext)==1) EXIT
416  END DO
417 !
418 !* 4.3.3 none found: end of loop along jss
419 ! ---------------------
420 !
421  IF (jnext>=nsso+1) EXIT
422 !
423 !* 4.3.4 second point outside of the domain: end of loop along iss
424 ! ---------------------
425 !
426  IF (il==0) EXIT
427 !
428 !
429 !* 4.4 add terms to sums of A/S and h/2
430 ! --------------------------------
431 !
432  IF (gfirst) iaoscounter=iaoscounter+1
433  gfirst = .false.
434  iaosdist =iaosdist+jnext
435 !
436 !* 4.4.1 mean slope
437 !
438  zslope=zslopejp
439 !
440 !* 4.4.2 A/S term
441 !
442  zssaos = zssqo(il,jiss,inext) - zssqo(jl,jiss,jjss) &
443  - zslope * zdyeff * jnext
444  IF (zssaos>0.) zajp=zajp+zssaos
445  IF (zssaos<0.) zajm=zajm-zssaos
446 !
447 !* 4.4.3 h/2 term
448 !
449  IF (zssaos>0.) THEN
450  zsumho2jp = zsumho2jp + 0.5 * zssaos
451  iho2counterjp=iho2counterjp+1
452  END IF
453  IF (zssaos<0.) THEN
454  zsumho2jm = zsumho2jm - 0.5 * zssaos
455  iho2counterjm=iho2counterjm+1
456  END IF
457 !
458 !* 4.5 end of loop on jss index
459 ! ------------------------
460 !
461  END DO
462  IF (iaosdist>0) THEN
463  zaosjp(jiss)=zajp/(zdyeff*iaosdist)
464  zaosjm(jiss)=zajm/(zdyeff*iaosdist)
465  END IF
466 !
467 !* 4.6 end of loop on iss index
468 ! ------------------------
469 !
470  END DO
471 !
472 !* 4.7 end of JP and JM coefficients
473 ! -----------------------------
474 !
475  IF (iaoscounter>0) THEN
476  zaosjp_all(jl)=sum(zaosjp) /iaoscounter
477  zaosjm_all(jl)=sum(zaosjm) /iaoscounter
478  IF (iho2counterjp>0) THEN
479  zho2jp_all(jl)=zsumho2jp /iho2counterjp
480  ELSE
481  zho2jp_all(jl)=0.
482  END IF
483  IF (iho2counterjm>0) THEN
484  zho2jm_all(jl)=zsumho2jm /iho2counterjm
485  ELSE
486  zho2jm_all(jl)=0.
487  END IF
488  gz0effj(jl)=.true.
489  END IF
490 !
491  END DO
492  !
493 ELSE
494  ALLOCATE(zho2im_all(0),zho2ip_all(0),zaosim_all(0),zaosip_all(0))
495  ALLOCATE(zho2jm_all(0),zho2jp_all(0),zaosjm_all(0),zaosjp_all(0))
496 ENDIF
497 !
498 DEALLOCATE(zssqo,issqot)
499 DEALLOCATE(zsea)
500 DEALLOCATE(zavg_zs)
501 !
502  CALL read_and_send_mpi(zaosip_all,uss%XAOSIP)
503  CALL read_and_send_mpi(zaosim_all,uss%XAOSIM)
504  CALL read_and_send_mpi(zho2ip_all,uss%XHO2IP)
505  CALL read_and_send_mpi(zho2im_all,uss%XHO2IM)
506 DEALLOCATE(zho2im_all,zho2ip_all,zaosim_all,zaosip_all)
507 !
508  CALL read_and_send_mpi(zaosjp_all,uss%XAOSJP)
509  CALL read_and_send_mpi(zaosjm_all,uss%XAOSJM)
510  CALL read_and_send_mpi(zho2jp_all,uss%XHO2JP)
511  CALL read_and_send_mpi(zho2jm_all,uss%XHO2JM)
512 DEALLOCATE(zho2jm_all,zho2jp_all,zaosjm_all,zaosjp_all)
513 !
514 IF (nrank==npio) THEN
515  ALLOCATE(issot(u%NDIM_FULL))
516  issot(:) = 0
517  WHERE (gz0effi(:)) issot(:) = 1
518  DEALLOCATE(gz0effi)
519 ELSE
520  ALLOCATE(issot(0))
521 ENDIF
522 ALLOCATE(isso(nl))
523  CALL read_and_send_mpi(issot,isso)
524 WHERE(isso(:)==1) oz0effi(:) = .true.
525 !
526 IF (nrank==npio) THEN
527  issot(:) = 0
528  WHERE (gz0effj(:)) issot(:) = 1
529  DEALLOCATE(gz0effj)
530 ENDIF
531  CALL read_and_send_mpi(issot,isso)
532 WHERE(isso(:)==1) oz0effj(:) = .true.
533 DEALLOCATE(isso)
534 !
535 DEALLOCATE(issot)
536 !
537 !-------------------------------------------------------------------------------
538 !
539 !* 5. Next grid point
540 ! ---------------
541 !
542 
543 IF (lhook) CALL dr_hook('SUBSCALE_AOS',1,zhook_handle)
544 !
545 !-------------------------------------------------------------------------------
546 !
547 END SUBROUTINE subscale_aos
logical, dimension(:,:,:), allocatable lssqo
integer, parameter jprb
Definition: parkind1.F90:32
subroutine get_adjacent_meshes(HGRID, KGRID_PAR, KL, PGRID_PAR, KLEFT,
subroutine subscale_aos(U, UG, USS, OZ0EFFI, OZ0EFFJ)
Definition: subscale_aos.F90:7
real, dimension(:,:,:), allocatable xssqo
intent(out) overrides sub arrays one Sort by the least significant key first sum(iindex(1:n))
logical lhook
Definition: yomhook.F90:15
subroutine get_mesh_dim(HGRID, KGRID_PAR, KL, PGRID_PAR, PDX, PDY, PMESH
Definition: get_mesh_dim.F90:7