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

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

improvements/corrections of some *.pro headers

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