source: trunk/SRC/Computation/div.pro @ 327

Last change on this file since 327 was 327, checked in by pinsard, 17 years ago

modification of headers : mainly blanks around = sign for keywords in declaration of function and pro

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 13.5 KB
Line 
1;+
2;
3; @file_comments
4; compute the horizontal divergence of a vectors field located on Arakawa C-grid.
5;
6; @categories
7; Calculation
8;
9; @param UU
10; Matrix representing the zonal coordinates (at U point) of a field of vectors
11; A 2D (xy), 3D (xyz or yt) or a structure readable by <pro>litchamp</pro> and containing
12; a 2D (xy), 3D (xyz or yt) array (4D case is not coded yet).
13; note that the dimension of the array must suit the domain dimension.
14;
15; @param VV
16; Matrix representing the meridional coordinates (at V point) of a field of vectors
17; A 2D (xy), 3D (xyz or yt) or a structure readable by <pro>litchamp</pro> and containing
18; a 2D (xy), 3D (xyz or yt) array (4D case is not coded yet).
19; note that the dimension of the array must suit the domain dimension.
20;
21; @keyword DIREC {type=scalar string}
22; Use if you want to call <pro>moyenne</pro> or
23; <pro>grossemoyenne</pro> after the div computation
24; (stupid ?) with a mean done in the DIREC direction
25;
26; @keyword MILLION {default=0}{type=scalar: 0 or 1}
27; Activate to multiply returned array by 1.e6
28;
29; @keyword _EXTRA
30; Used to declare that this routine accepts inherited keywords
31;
32; @returns
33; the divergence of the input data (with the same size) located at T
34;point (see restrictions).
35;
36; @uses
37; cm_4cal
38; cm_4data
39; cm_4mmesh
40;
41; @restrictions
42;
43; - Works only for Arakawa C-grid.
44; - UU must be on U grid, VV must be on V grid
45; - 4D case is not coded yet
46; - the common variable jpt is used to differ xyz (jpt=1) and xyt (jpt\=1) cases.
47; - U and V arrays are cut in the same geographic domain. Because of the shift between
48;   T, U, V and F grids, it is possible that these two arrays do not have the same
49;   size and refer to different indexes. In this case, arrays are re-cut on
50;   common indexes. To avoid these re-cuts, use the keyword /memeindice in
51; <pro>domdef</pro>
52; - When computing the divergence, we update, vargrid, varname, varunits and the
53;   grid position parameters (firstxt, lastxt, nxt, firstyt, lastyt, nyt).
54; - points that cannot be computed (domain boundaries, coastline) are set to NaN
55;
56; @examples
57; IDL> \@tst_initorca2
58; IDL> plt, div(dist(jpi,jpj), dist(jpi,jpj))
59;
60; @history
61; Guillaume Roullet (grlod\@ipsl.jussieu.fr): creation; spring 1998
62; Sebastien Masson (smasson\@lodyc.jussieu.fr)
63; adaptation to work with a reduce domain; 12/1/2000
64;
65; @version
66; $Id$
67;
68; @todo
69; code the 4D case
70;
71;-
72FUNCTION div, uu, vv, DIREC=direc, MILLION=million, _EXTRA=ex
73;
74  compile_opt idl2, strictarrsubs
75;
76@cm_4cal                        ; for jpt
77@cm_4data                       ; for varname, vargrid, vardate, varunit, valmask
78@cm_4mesh
79;
80  time1 = systime(1)          ; for key_performance
81;
82  IF finite(glamu[0])*finite(gphiu[0])*finite(glamv[0])*finite(gphiv[0]) EQ 0 THEN $
83     return, report(['This version of div is based on Arakawa C-grid.' $
84                     , 'U and V grids must therefore be defined'])
85;
86  gr = litchamp(uu, /grid)
87  IF gr NE '' THEN BEGIN
88    IF gr NE 'U' THEN return, report('the first parameter is not located on U grid, but on '+ strtrim(gr, 2) +'grid')
89  ENDIF
90  gr = litchamp(vv, /grid)
91  IF gr NE '' THEN BEGIN
92    IF gr NE 'V' THEN return, report('the second parameter is not located on V grid, but on '+ strtrim(gr, 2) +'grid')
93  ENDIF
94  u = litchamp(uu)
95  v = litchamp(vv)
96;
97  szu = size(u)
98  szv = size(v)
99
100  if szu[0] NE szv[0] then return, report('U and V input data must have the same number of dimensions')
101
102;------------------------------------------------------------
103; We find common points between U and V
104;------------------------------------------------------------
105  indicexu = (lindgen(jpi))[firstxu:firstxu+nxu-1]
106  indicexv = (lindgen(jpi))[firstxv:firstxv+nxv-1]
107  indicex = inter(indicexu, indicexv)
108  indiceyu = (lindgen(jpj))[firstyu:firstyu+nyu-1]
109  indiceyv = (lindgen(jpj))[firstyv:firstyv+nyv-1]
110  indicey = inter(indiceyu, indiceyv)
111  nx = n_elements(indicex)
112  ny = n_elements(indicey)
113  indice2d = lindgen(jpi, jpj)
114  indice2d = indice2d[indicex[0]:indicex[0]+nx-1, indicey[0]:indicey[0]+ny-1]
115;----------------------------------------------------------------------------
116  vargrid = 'T'
117  varname = 'div'
118  IF keyword_set(million) THEN varunits = '1.e6*'+varunit+'/m' ELSE varunits = varunit+'/m'
119  IF keyword_set(million) THEN scale = 1.e6 ELSE scale = 1.
120  if n_elements(valmask) EQ 0 THEN valmask = 1.e20
121  firstxt = indicex[0] & lastxt = indicex[0]+nx-1 & nxt = nx
122  firstyt = indicey[0] & lastyt = indicey[0]+ny-1 & nyt = ny
123;----------------------------------------------------------------------------
124;----------------------------------------------------------------------------
125  case 1 of
126;----------------------------------------------------------------------------
127;xyz
128;----------------------------------------------------------------------------
129    szu[0] EQ 3 AND jpt EQ 1:BEGIN
130;------------------------------------------------------------
131; extraction of U and V on the appropriated domain
132;------------------------------------------------------------
133      case 1 of
134        szu[1] EQ nxu AND szu[2] EQ nyu AND $
135           szv[1] EQ nxv AND szv[2] EQ nyv:BEGIN
136          case 1 of
137            nxu NE nx:if indicex[0] EQ firstxu then u = u[0:nx-1, *, *] ELSE u = u[1: nx, *, *]
138            nxv NE nx:if indicex[0] EQ firstxv then v = v[0:nx-1, *, *] ELSE v = v[1: nx, *, *]
139            nyu NE ny:if indicey[0] EQ firstyu then u = u[*, 0:ny-1, *] ELSE u = u[*, 1: ny, *]
140            nyv NE ny:if indicey[0] EQ firstyv then v = v[*, 0:ny-1, *] ELSE v = v[*, 1: ny, *]
141            ELSE :
142          endcase
143        END
144        szu[1] EQ jpi AND szu[2] EQ jpj AND $
145           szv[1] EQ jpi AND szv[2] EQ jpj:BEGIN
146          u = u[indicex[0]:indicex[0]+nx-1, indicey[0]:indicey[0]+ny-1, *]
147          v = v[indicex[0]:indicex[0]+nx-1, indicey[0]:indicey[0]+ny-1, *]
148        END
149        ELSE:return $
150           , report(['We cannot find re-cut on common indexes (see restriction un the header.).' $
151                     , 'To avoid this problem, read the full domain' $
152                     , 'or use the keyword /memeindice in domdef when defining the zoom area'])
153      ENDCASE
154;------------------------------------------------------------
155; divergence computation
156;------------------------------------------------------------
157      zu = (e2u[indice2d])[*]#replicate(1., nzt)
158      landu = where((umask())[indicex[0]:indicex[0]+nx-1, indicey[0]:indicey[0]+ny-1, firstzt:lastzt] EQ 0)
159      if landu[0] NE -1 then zu[temporary(landu)] = !values.f_nan
160      zu = temporary(u) * temporary(zu)
161;
162      zv = (e1v[indice2d])[*]#replicate(1., nzt)
163      landv = where((vmask())[indicex[0]:indicex[0]+nx-1, indicey[0]:indicey[0]+ny-1, firstzt:lastzt] EQ 0)
164      if landv[0] NE -1 then zv[temporary(landv)] = !values.f_nan
165      zv = temporary(v) * temporary(zv)
166;
167      zdiv = (scale / (e1t[indice2d]*e2t[indice2d]))[*]#replicate(1., nzt)
168      zdiv = ( zu - shift(zu, 1, 0, 0) + zv - shift(zv, 0, 1, 0) ) * temporary(zdiv)
169;------------------------------------------------------------
170; Edging put at !values.f_nan
171;------------------------------------------------------------
172      if  NOT keyword_set(key_periodic) OR nx NE jpi then begin
173        zdiv[0, *, *] = !values.f_nan
174        zdiv[nx-1, *, *] = !values.f_nan
175      endif
176      zdiv[*, 0, *] = !values.f_nan
177      zdiv[*, ny-1, *] = !values.f_nan
178;
179      land = where(tmask[indicex[0]:indicex[0]+nx-1, indicey[0]:indicey[0]+ny-1, firstzt:lastzt] EQ 0)
180      if land[0] NE -1 then zdiv[temporary(land)] = valmask
181      if keyword_set(direc) then  zdiv = moyenne(zdiv, direc, /nan)
182    END
183;----------------------------------------------------------------------------
184;----------------------------------------------------------------------------
185;xyt
186;----------------------------------------------------------------------------
187;----------------------------------------------------------------------------
188    szu[0] EQ 3 AND jpt GT 1:BEGIN
189;------------------------------------------------------------
190; extraction of U and V on the appropriated domain
191;------------------------------------------------------------
192      case 1 of
193        szu[1] EQ nxu AND szu[2] EQ nyu AND $
194           szv[1] EQ nxv AND szv[2] EQ nyv:BEGIN
195          case 1 of
196            nxu NE nx:if indicex[0] EQ firstxu then u = u[0:nx-1, *, *] ELSE u = u[1: nx, *, *]
197            nxv NE nx:if indicex[0] EQ firstxv then v = v[0:nx-1, *, *] ELSE v = v[1: nx, *, *]
198            nyu NE ny:if indicey[0] EQ firstyu then u = u[*, 0:ny-1, *] ELSE u = u[*, 1: ny, *]
199            nyv NE ny:if indicey[0] EQ firstyv then v = v[*, 0:ny-1, *] ELSE v = v[*, 1: ny, *]
200            ELSE :
201          endcase
202        END
203        szu[1] EQ jpi AND szu[2] EQ jpj AND $
204           szv[1] EQ jpi AND szv[2] EQ jpj:BEGIN
205          u = u[indicex[0]:indicex[0]+nx-1, indicey[0]:indicey[0]+ny-1, *]
206          v = v[indicex[0]:indicex[0]+nx-1, indicey[0]:indicey[0]+ny-1, *]
207        END
208        ELSE:return, -1
209      endcase
210;------------------------------------------------------------
211; divergence computation
212;------------------------------------------------------------
213      zu = e2u[indice2d]
214      landu = where((umask())[indice2d+jpi*jpj*firstzt] EQ 0)
215      if landu[0] NE -1 then zu[temporary(landu)] = !values.f_nan
216      zu = (temporary(zu))[*]#replicate(1., jpt)
217      zu = temporary(u) * temporary(zu)
218;
219      zv = e1v[indice2d]
220      landv = where((vmask())[indice2d+jpi*jpj*firstzt] EQ 0)
221      if landv[0] NE -1 then zv[temporary(landv)] = !values.f_nan
222      zv = (temporary(zv))[*]#replicate(1., jpt)
223      zv = temporary(v) * temporary(zv)
224;
225      zdiv = (scale / (e1t[indice2d]*e2t[indice2d]))[*]#replicate(1., jpt)
226      zdiv = ( zu - shift(zu, 1, 0, 0) + zv - shift(zv, 0, 1, 0) ) * temporary(zdiv)
227;------------------------------------------------------------
228; Edging put at !values.f_nan
229;------------------------------------------------------------
230      if  NOT keyword_set(key_periodic) OR nx NE jpi then begin
231        zdiv[0, *, *] = !values.f_nan
232        zdiv[nx-1, *, *] = !values.f_nan
233      endif
234      zdiv[*, 0, *] = !values.f_nan
235      zdiv[*, ny-1, *] = !values.f_nan
236;
237      land = where(tmask[indice2d+jpi*jpj*firstzt] EQ 0, cnt)
238      if land[0] NE -1 then BEGIN
239        land = (temporary(land))#replicate(1L, jpt) + replicate(1L, cnt)#(nx*ny*lindgen(jpt))
240        zdiv[temporary(land)] = valmask
241      ENDIF
242      if keyword_set(direc) then  zdiv = grossemoyenne(zdiv, direc, /nan)
243    END
244;----------------------------------------------------------------------------
245;----------------------------------------------------------------------------
246;xyzt
247;----------------------------------------------------------------------------
248;----------------------------------------------------------------------------
249    szu[0] EQ 4:BEGIN
250      return, report('Case not coded contact saxo team or make a do loop!')
251    END
252;----------------------------------------------------------------------------
253;----------------------------------------------------------------------------
254;xy
255;----------------------------------------------------------------------------
256;----------------------------------------------------------------------------
257    szu[0] EQ 2:BEGIN
258;------------------------------------------------------------
259; extraction of U and V on the appropriated domain
260;------------------------------------------------------------
261      case 1 of
262        szu[1] EQ nxu AND szu[2] EQ nyu AND $
263           szv[1] EQ nxv AND szv[2] EQ nyv:BEGIN
264          case 1 of
265            nxu NE nx:if indicex[0] EQ firstxu then u = u[0:nx-1, *] ELSE u = u[1: nx, *]
266            nxv NE nx:if indicex[0] EQ firstxv then v = v[0:nx-1, *] ELSE v = v[1: nx, *]
267            nyu NE ny:if indicey[0] EQ firstyu then u = u[*, 0:ny-1] ELSE u = u[*, 1: ny]
268            nyv NE ny:if indicey[0] EQ firstyv then v = v[*, 0:ny-1] ELSE v = v[*, 1: ny]
269            ELSE :
270          endcase
271        END
272        szu[1] EQ jpi AND szu[2] EQ jpj AND $
273           szv[1] EQ jpi AND szv[2] EQ jpj:BEGIN
274          u = u[indice2d]
275          v = v[indice2d]
276        END
277        ELSE:return, -1
278      endcase
279;------------------------------------------------------------
280; divergence computation
281;------------------------------------------------------------
282      zu = e2u[indice2d]
283      landu = where((umask())[indice2d+jpi*jpj*firstzt] EQ 0)
284      if landu[0] NE -1 then zu[temporary(landu)] = !values.f_nan
285      zu = temporary(u) * temporary(zu)
286
287      zv = e1v[indice2d]
288      landv = where((vmask())[indice2d+jpi*jpj*firstzt] EQ 0)
289      if landv[0] NE -1 then zv[temporary(landv)] = !values.f_nan
290      zv = temporary(v) * temporary(zv)
291
292      zdiv = scale / (e1t[indice2d]*e2t[indice2d])
293      zdiv = ( zu - shift(zu, 1, 0) + zv - shift(zv, 0, 1) ) * temporary(zdiv)
294;------------------------------------------------------------
295; Edging put at !values.f_nan
296;------------------------------------------------------------
297      if  NOT keyword_set(key_periodic) OR nx NE jpi then begin
298        zdiv[0, *] = !values.f_nan
299        zdiv[nx-1, *] = !values.f_nan
300      endif
301      zdiv[*, 0] = !values.f_nan
302      zdiv[*, ny-1] = !values.f_nan
303;
304      land =  where(tmask[indice2d+jpi*jpj*firstzt] EQ 0)
305      if land[0] NE -1 then zdiv[temporary(land)] = valmask
306      if keyword_set(direc) then zdiv = moyenne(zdiv, direc, /nan)
307    END
308;----------------------------------------------------------------------------
309;----------------------------------------------------------------------------
310    ELSE:return, report('U and V input arrays must have 2, 3 or 4 dimensions')
311  ENDCASE
312;------------------------------------------------------------
313  if keyword_set(key_performance) THEN print, 'time div', systime(1)-time1
314
315  return, zdiv
316end
Note: See TracBrowser for help on using the repository browser.