SURFEX  V8_0
Surfex V8_0 release
 All Classes Files Functions Variables
sso.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 sso (UG, USS, &
7  osso,osso_anis,psea)
8 ! #########################
9 !
10 !!*SSO computes the SSO anisotropy, direction and slope
11 !!
12 !!
13 !! METHOD
14 !! ------
15 !! See Lott and Miller, 1997, QJRMS 101-127
16 !!
17 !! AUTHOR
18 !! ------
19 !!
20 !! V.Masson Meteo-France
21 !!
22 !! MODIFICATION
23 !! ------------
24 !!
25 !! Original 23/05/97
26 !!
27 !----------------------------------------------------------------------------
28 !
29 !* 0. DECLARATION
30 ! -----------
31 !
32 !
35 !
36 USE modi_get_mesh_dim
37 USE modi_get_adjacent_meshes
38 !
39 USE modd_csts, ONLY : xpi
40 USE modd_pgdwork, ONLY : nsso, xssqo, lssqo
41 USE modd_pgd_grid, ONLY : nl, cgrid, xgrid_par, ngrid_par
42 !
43 !
44 USE yomhook ,ONLY : lhook, dr_hook
45 USE parkind1 ,ONLY : jprb
46 !
47 IMPLICIT NONE
48 !
49 !* 0.1 Declaration of dummy arguments
50 ! ------------------------------
51 !
52 !
53 TYPE(surf_atm_grid_t), INTENT(INOUT) :: ug
54 TYPE(surf_atm_sso_t), INTENT(INOUT) :: uss
55 !
56 LOGICAL, DIMENSION(:), INTENT(OUT) :: osso ! .T. : the SSO coefficients
57 ! ! are computed at grid point
58 ! ! .F. : not enough sub-grid
59 ! ! information avalaible to
60 ! ! compute the coefficients
61 LOGICAL, DIMENSION(:), INTENT(OUT) :: osso_anis ! .T. : the SSO anisotropy
62 ! ! are computed at grid point
63 ! ! .F. : not enough sub-grid
64 ! ! information avalaible to
65 ! ! compute the coefficients
66 REAL, DIMENSION(:), INTENT(IN) :: psea ! sea fraction
67 !
68 !* 0.2 Declaration of indexes
69 ! ----------------------
70 !
71 INTEGER :: jl ! loop index on grid meshs
72 INTEGER :: il ! grid mesh index of second subgrid point used
73 INTEGER :: jiss, jjss ! loop indexes for subsquares arrays
74 INTEGER :: jnext ! loop index on subgrid meshes
75 INTEGER :: jprev ! loop index on subgrid meshes
76 INTEGER :: inext ! index to add to JISS or JJSS to obtain the following
77 ! ! point containing a data in a segment
78 INTEGER :: iprev ! index to remove from JISS or JJSS to obtain the
79 ! ! previous point containing a data in a segment
80 !
81 INTEGER :: imaxi ! index of the next subsquare with data along I axis,
82  ! or last subsquare inside grid mesh along I axis
83 INTEGER :: imaxj ! index of the next subsquare with data along J axis,
84  ! or last subsquare inside grid mesh along J axis
85 INTEGER, DIMENSION(NL) :: ileft ! index of left grid mesh
86 INTEGER, DIMENSION(NL) :: iright ! index of right grid mesh
87 INTEGER, DIMENSION(NL) :: itop ! index of top grid mesh
88 INTEGER, DIMENSION(NL) :: ibottom ! index of bottom grid mesh
89 !
90 !* 0.3 Declaration of working arrays inside a MESONH grid (JI,JJ)
91 ! -----------------------------
92 !
93 REAL, DIMENSION(NSSO,NSSO) :: zdzsdx ! topographic gradient along x
94 REAL, DIMENSION(NSSO,NSSO) :: zdzsdy ! topographic gradient along y
95 LOGICAL, DIMENSION(NSSO,NSSO) :: gdzsdx ! occurence of gradient along x
96 LOGICAL, DIMENSION(NSSO,NSSO) :: gdzsdy ! occurence of gradient along y
97 REAL :: zdxeff ! width of a subsquare along I axis
98 REAL :: zdyeff ! width of a subsquare along J axis
99 LOGICAL :: gbound ! .T.: first left (for dzs/dx) or first bottom (for dzs/dy)
100  ! sub-square gradients is being computed
101 !
102 !* 0.4 Declaration of other local variables
103 ! ------------------------------------
104 !
105 REAL, DIMENSION(NL) :: zdx ! grid mesh size in x direction
106 REAL, DIMENSION(NL) :: zdy ! grid mesh size in y direction
107 REAL, DIMENSION(NL) :: zhxx ! topographic gradient correlation tensor: x,x
108 REAL, DIMENSION(NL) :: zhxy ! topographic gradient correlation tensor: x,y
109 REAL, DIMENSION(NL) :: zhyy ! topographic gradient correlation tensor: y,y
110 REAL, DIMENSION(NL) :: zk, zl, zm ! diagonalised terms of the tensor
111 REAL(KIND=JPRB) :: zhook_handle
112 !
113 !----------------------------------------------------------------------------
114 !
115 !* 1. Initializations
116 ! ---------------
117 !
118 IF (lhook) CALL dr_hook('SSO',0,zhook_handle)
119 zk=0.
120 zl=0.
121 zm=0.
122 !
123 !* 1.1 Occurence of computation of the coefficients
124 ! --------------------------------------------
125 !
126 osso(:)=.false.
127 osso_anis(:)=.false.
128 !
129 !
130 !* 1.2 Grid dimension (meters)
131 ! -----------------------
132 !
133  CALL get_mesh_dim(cgrid,ngrid_par,nl,xgrid_par,zdx,zdy,ug%XMESH_SIZE)
134 !
135 !
136 !* 1.3 Left, top, right and bottom adjacent gris meshes
137 ! ------------------------------------------------
138 !
139  CALL get_adjacent_meshes(cgrid,ngrid_par,nl,xgrid_par,ileft,iright,itop,ibottom)
140 !
141 !----------------------------------------------------------------------------
142 !
143 !* 2. Loop on MESONH grid points
144 ! --------------------------
145 !
146 zhyy(:) = 0.
147 zhxx(:) = 0.
148 zhxy(:) = 0.
149 !
150 DO jl=1,nl
151 !
152 !
153 !* 2.1 No land in grid mesh
154 ! --------------------
155 !
156  IF (psea(jl)==1.) cycle
157 !
158  zdxeff=zdx(jl)/float(nsso)
159  zdyeff=zdy(jl)/float(nsso)
160 !
161 !* 2.3 Not enough data for computation
162 ! -------------------------------
163 !
164 ! 1st step: removes points where orography data is not present at all.
165 !
166  IF ( count( lssqo(:,:,jl)) == 0 ) cycle
167 !
168 !----------------------------------------------------------------------------
169 !
170 !* 3. Computations of the gradients along x
171 ! -------------------------------------
172 !
173  gdzsdx(:,:)=.false.
174  zdzsdx(:,:)= 0.
175 !
176 !* 3.1 loop on jss index (there is no specific computation along j)
177 ! -----------------
178 !
179  DO jjss=1,nsso
180 !
181 !* left point mark initialization
182 !
183  gbound=.true.
184 !
185 !* 3.2 loop on iss index
186 ! -----------------
187 !
188  DO jiss=1,nsso
189 !
190 !
191 !* 3.3 search for two consecutive grid points
192 ! --------------------------------------
193 !
194 !* 3.3.1 first one
195 !
196  IF (.NOT. lssqo(jiss,jjss,jl) ) cycle
197 !
198 !* 3.3.2 second one (up to one grid mesh further)
199 !
200  DO jnext=1,nsso
201  IF (jiss+jnext>nsso) THEN
202  il = iright(jl)
203  inext = jiss+jnext-nsso
204  ELSE
205  il = jl
206  inext = jiss+jnext
207  END IF
208  ! no right point
209  IF (il==0) EXIT
210  ! subgrid data found
211  IF (lssqo(inext,jjss,il)) EXIT
212  END DO
213 !
214 !* 3.3.3 none found: end of loop along jss
215 ! ---------------------
216 !
217  IF (jnext>=nsso+1) EXIT
218 !
219 !* 3.3.4 second point outside of the domain: end of loop along iss
220 ! ---------------------
221 !
222  IF (il==0) EXIT
223 !
224 !* 3.4 dzs/dx term
225 ! -----------
226 !
227  imaxi = min(jiss+jnext-1,nsso)
228 !
229  zdzsdx(jiss:imaxi,jjss) = ( xssqo(inext,jjss,il) - xssqo(jiss,jjss,jl)) &
230  / float(jnext) / zdxeff
231 !
232  gdzsdx(jiss:imaxi,jjss) = .true.
233 !
234 !
235 !* 3.5 left data point not on the left of the grid mesh (one more computation)
236 ! ------------------------------------------------
237 !
238  IF (gbound .AND. jiss/=1) THEN
239  DO jprev=1,nsso
240  IF (jiss-jprev<1) THEN
241  il = ileft(jl)
242  iprev = jiss-jprev+nsso
243  ELSE
244  il = jl
245  iprev = jiss-jprev
246  END IF
247  ! no left point
248  IF (il==0) EXIT
249  ! subgrid data found
250  IF (lssqo(iprev,jjss,il)) EXIT
251  END DO
252 
253  IF (.NOT. (jprev>=nsso+1 .OR. il==0)) THEN
254  zdzsdx(1:jiss,jjss) = ( xssqo(jiss,jjss,jl) - xssqo(iprev,jjss,il)) &
255  / float(jprev) / zdxeff
256 !
257  gdzsdx(1:jiss,jjss) = .true.
258  END IF
259  END IF
260 !
261 !
262  gbound=.false.
263 !
264 !
265 !* 3.6 end of loop on iss index
266 ! ------------------------
267 !
268  END DO
269 !
270 !* 3.7 end of loop on jss index
271 ! ------------------------
272 !
273  END DO
274 !
275 !----------------------------------------------------------------------------
276 !
277 !* 4. Computations of the gradients along y
278 ! -------------------------------------
279 !
280  gdzsdy(:,:)=.false.
281  zdzsdy(:,:)= 0.
282 !
283 !* 4.1 loop on iss index (there is no specific computation along i)
284 ! -----------------
285 !
286  DO jiss=1,nsso
287 !
288 !* bottom point mark initialization
289 !
290  gbound=.true.
291 !
292 !* 4.2 loop on jss index
293 ! -----------------
294 !
295  DO jjss=1,nsso
296 !
297 !
298 !* 4.3 search for two consecutive grid points
299 ! --------------------------------------
300 !
301 !* 4.3.1 first one
302 !
303  IF (.NOT. lssqo(jiss,jjss,jl) ) cycle
304 !
305 !* 4.3.2 second one (up to one grid mesh further)
306 !
307  DO jnext=1,nsso
308  IF (jjss+jnext>nsso) THEN
309  il = itop(jl)
310  inext = jjss+jnext-nsso
311  ELSE
312  il = jl
313  inext = jjss+jnext
314  END IF
315  ! no top point
316  IF (il==0) EXIT
317  ! subgrid data found
318  IF (lssqo(jiss,inext,il)) EXIT
319  END DO
320 !
321 !* 4.3.3 none found: end of loop along iss
322 ! ---------------------
323 !
324  IF (jnext>=nsso+1) EXIT
325 !
326 !* 3.3.4 second point outside of the domain: end of loop along iss
327 ! ---------------------
328 !
329  IF (il==0) EXIT
330 !
331 !* 4.4 dzs/dy term
332 ! -----------
333 !
334  imaxj = min(jjss+jnext-1,nsso)
335 !
336  zdzsdy(jiss,jjss:imaxj) = ( xssqo(jiss,inext,il) - xssqo(jiss,jjss,jl)) &
337  / float(jnext) / zdyeff
338  !
339  gdzsdy(jiss,jjss:imaxj) = .true.
340 !
341 !
342 !* 4.5 bottom data point not on the bottom of the grid mesh (one more computation)
343 ! ----------------------------------------------------
344 !
345  IF (gbound .AND. jjss/=1) THEN
346  DO jprev=1,nsso
347  IF (jjss-jprev<1) THEN
348  il = ibottom(jl)
349  iprev = jjss-jprev+nsso
350  ELSE
351  il = jl
352  iprev = jjss-jprev
353  END IF
354  ! no left point
355  IF (il==0) EXIT
356  ! subgrid data found
357  IF (lssqo(jiss,iprev,il)) EXIT
358  END DO
359 
360  IF (.NOT. (jprev>=nsso+1 .OR. il==0)) THEN
361  zdzsdy(jiss,1:jjss) = ( xssqo(jiss,jjss,jl) - xssqo(jiss,iprev,il)) &
362  / float(jprev) / zdyeff
363 !
364  gdzsdy(jiss,1:jjss) = .true.
365  END IF
366  END IF
367 !
368 !
369  gbound=.false.
370 !
371 !
372 !
373 !* 4.6 end of loop on jss index
374 ! ------------------------
375 !
376  END DO
377 !
378 !* 4.7 end of loop on iss index
379 ! ------------------------
380 !
381  END DO
382 !----------------------------------------------------------------------------
383 !
384 !* 5. Computations of tensor terms
385 ! ----------------------------
386 !
387 !
388 !* 5.1 test to know if term Hxy is computable
389 ! --------------------------------------
390 !
391 !* 2 values are necessary in the grid point to compute anisotropy
392 !
393  IF ( count(gdzsdx(:,:).AND.gdzsdy(:,:)) ==0 ) cycle
394 !
395 !
396 !* 5.2 SSO quantities are computable
397 ! -----------------------------
398 
399  osso(jl)=.true.
400  osso_anis(jl)=count(gdzsdx(:,:).AND.gdzsdy(:,:))>1
401 !
402 !
403 !* 5.3 term Hxx
404 ! --------
405 !
406  zhxx(jl) = sum(zdzsdx(:,:)*zdzsdx(:,:),mask=gdzsdx(:,:).AND.gdzsdy(:,:))&
407  /count(gdzsdx(:,:).AND.gdzsdy(:,:))
408 !
409 !* 5.4 term Hyy
410 ! --------
411 !
412  zhyy(jl) = sum(zdzsdy(:,:)*zdzsdy(:,:),mask=gdzsdx(:,:).AND.gdzsdy(:,:))&
413  /count(gdzsdx(:,:).AND.gdzsdy(:,:))
414 !
415 !* 5.5 term Hxy
416 ! --------
417 !
418  zhxy(jl) = sum(zdzsdx(:,:)*zdzsdy(:,:),mask=gdzsdx(:,:).AND.gdzsdy(:,:))&
419  /count(gdzsdx(:,:).AND.gdzsdy(:,:))
420 !
421 !-------------------------------------------------------------------------------
422 !
423 !* 6. Next MESONH grid point
424 ! ----------------------
425 !
426 END DO
427 !
428 !-------------------------------------------------------------------------------
429 !
430 !* 7. Diagonalization of the tensor
431 ! -----------------------------
432 !
433 WHERE (osso(:))
434  zk(:)=0.5*(zhxx(:)+zhyy(:))
435  zl(:)=0.5*(zhxx(:)-zhyy(:))
436  zm(:)= zhxy(:)
437 END WHERE
438 !
439 !-------------------------------------------------------------------------------
440 !
441 !* 8. S.S.O. characteristics
442 ! ----------------------
443 !
444 !* 8.1 S.S.O. direction of main axis
445 ! -----------------------------
446 !
447 WHERE (osso(:) .AND. zl(:)>1.e-30 )
448  uss%XSSO_DIR(:) = 0.5* atan(zm/zl) * (180./xpi)
449 END WHERE
450 !
451 WHERE (osso(:) .AND. zl(:)<-1.e-30 )
452  uss%XSSO_DIR(:) = 0.5* atan(zm/zl) * (180./xpi) + 90.
453 END WHERE
454 !
455 WHERE (osso(:) .AND. abs(zl(:))<=1.e-30 )
456  uss%XSSO_DIR(:) = 45.
457 END WHERE
458 !
459 WHERE (osso(:) .AND. uss%XSSO_DIR(:)>90. )
460  uss%XSSO_DIR(:) = uss%XSSO_DIR(:) - 180.
461 END WHERE
462 !
463 !* 8.2 S.S.O. slope
464 ! ------------
465 !
466 WHERE (osso(:))
467  uss%XSSO_SLOPE(:) = sqrt( zk+sqrt(zl*zl+zm*zm) )
468 END WHERE
469 !
470 !* 8.3 S.S.O. anisotropy
471 ! -----------------
472 !
473 WHERE (osso_anis(:) .AND. (zk+sqrt(zl*zl+zm*zm)) >0. )
474  uss%XSSO_ANIS(:)=sqrt( max(zk-sqrt(zl*zl+zm*zm),0.) / (zk+sqrt(zl*zl+zm*zm)))
475 END WHERE
476 !
477 WHERE (osso_anis(:) .AND. (zk+sqrt(zl*zl+zm*zm))==0. )
478  uss%XSSO_ANIS(:)=1.
479 END WHERE
480 IF (lhook) CALL dr_hook('SSO',1,zhook_handle)
481 !
482 !-------------------------------------------------------------------------------
483 !
484 END SUBROUTINE sso
subroutine sso(UG, USS, OSSO, OSSO_ANIS, PSEA)
Definition: sso.F90:6
subroutine get_adjacent_meshes(HGRID, KGRID_PAR, KL, PGRID_PAR, KLEFT, KRIGHT, KTOP, KBOTTOM)
subroutine get_mesh_dim(HGRID, KGRID_PAR, KL, PGRID_PAR, PDX, PDY, PMESHSIZE)
Definition: get_mesh_dim.F90:6