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

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

improvements/corrections of some *.pro headers + replace some message by some report

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