source: trunk/SRC/Computation/curl.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.8 KB
Line 
1;+
2;
3; @file_comments
4; Calculate the vertical component of the curl of a field of horizontal vectors
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; with a mean done in the DIREC direction
24;
25; @returns RES
26; the vertical component of the curl 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 (firstxf, lastxf, nxf, firstyf, lastyf, nyf).
44; - points that cannot be computed (domain boundaries, coastline) are set to NaN
45;
46; @examples
47; IDL> \@tst_initorca2
48; IDL> plt, curl(dist(jpi,jpj), dist(jpi,jpj))
49;
50; @history
51; Guillaume Roullet (grlod\@ipsl.jussieu.fr)
52; Sebastien Masson (smasson\@lodyc.jussieu.fr)
53; adaptation to work with a reduce domain
54; 21/5/1999: missing values at !values.f_nan
55;
56; @version
57; $Id$
58;
59; @todo
60; code the 4d case
61;-
62;
63FUNCTION curl, uu, vv, DIREC = DIREC
64;
65  compile_opt idl2, strictarrsubs
66;
67@cm_4cal                        ; for jpt
68@cm_4data                       ; for varname, vargrid, vardate, varunit, valmask
69@cm_4mesh
70;
71  tempsun = systime(1)          ; To key_performance
72;
73  IF finite(glamu[0])*finite(gphiu[0])*finite(glamv[0])*finite(gphiv[0]) EQ 0 THEN $
74     return, report(['This version of curl is based on Arakawa C-grid.' $
75                     , 'U and V grids must therefore be defined'])
76;
77  u = litchamp(uu)
78  v = litchamp(vv)
79
80  szu = size(u)
81  szv = size(v)
82
83  if szu[0] NE szv[0] then return, report('U and V input data must have the same number of dimensions')
84
85;------------------------------------------------------------
86; We find common points between U and V
87;------------------------------------------------------------
88  indicexu = (lindgen(jpi))[firstxu:firstxu+nxu-1]
89  indicexv = (lindgen(jpi))[firstxv:firstxv+nxv-1]
90  indicex = inter(indicexu, indicexv)
91  indiceyu = (lindgen(jpj))[firstyu:firstyu+nyu-1]
92  indiceyv = (lindgen(jpj))[firstyv:firstyv+nyv-1]
93  indicey = inter(indiceyu, indiceyv)
94  nx = n_elements(indicex)
95  ny = n_elements(indicey)
96  indice2d = lindgen(jpi, jpj)
97  indice2d = indice2d[indicex[0]:indicex[0]+nx-1, indicey[0]:indicey[0]+ny-1]
98;----------------------------------------------------------------------------
99  vargrid = 'F'
100  varname = 'vorticity'
101  varunits = 's-1'
102  if n_elements(valmask) EQ 0 THEN valmask = 1e20
103  firstxt = indicex[0] & lastxt = indicex[0]+nx-1 & nxt = nx
104  firstyt = indicey[0] & lastyt = indicey[0]+ny-1 & nyt = ny
105;----------------------------------------------------------------------------
106;----------------------------------------------------------------------------
107  case 1 of
108;----------------------------------------------------------------------------
109;xyz
110;----------------------------------------------------------------------------
111    szu[0] EQ 3 AND jpt EQ 1:BEGIN
112;------------------------------------------------------------
113; extraction of U and V on the appropriated domain
114;------------------------------------------------------------
115      case 1 of
116        szu[1] EQ nxu AND szu[2] EQ nyu AND $
117           szv[1] EQ nxv AND szv[2] EQ nyv:BEGIN
118          case 1 of
119            nxu NE nx:if indicex[0] EQ firstxu then u = u[0:nx-1, *, *] ELSE u = u[1: nx, *, *]
120            nxv NE nx:if indicex[0] EQ firstxv then v = v[0:nx-1, *, *] ELSE v = v[1: nx, *, *]
121            nyu NE ny:if indicey[0] EQ firstyu then u = u[*, 0:ny-1, *] ELSE u = u[*, 1: ny, *]
122            nyv NE ny:if indicey[0] EQ firstyv then v = v[*, 0:ny-1, *] ELSE v = v[*, 1: ny, *]
123            ELSE :
124          endcase
125        END
126        szu[1] EQ jpi AND szu[2] EQ jpj AND $
127           szv[1] EQ jpi AND szv[2] EQ jpj:BEGIN
128          u = u[indicex[0]:indicex[0]+nx-1, indicey[0]:indicey[0]+ny-1, *]
129          v = v[indicex[0]:indicex[0]+nx-1, indicey[0]:indicey[0]+ny-1, *]
130        END
131        ELSE:return,  -1
132      endcase
133;------------------------------------------------------------
134; curl computation
135;------------------------------------------------------------
136      coefu = ((e1u[indice2d])[*]#replicate(1., nzt)) $
137              * (umask())[indicex[0]:indicex[0]+nx-1, indicey[0]:indicey[0]+ny-1, firstzt:lastzt]
138      landu = where(coefu EQ 0)
139      if landu[0] NE -1 then coefu[temporary(landu)] = !values.f_nan
140
141      coefv = ((e2v[indice2d])[*]#replicate(1., nzt)) $
142              *(vmask())[indicex[0]:indicex[0]+nx-1, indicey[0]:indicey[0]+ny-1, firstzt:lastzt]
143      landv = where(coefv EQ 0)
144      if landv[0] NE -1 then coefv[temporary(landv)] = !values.f_nan
145
146      tabf = (fmask())[indicex[0]:indicex[0]+nx-1, indicey[0]:indicey[0]+ny-1, firstzt:lastzt] $
147             / ((e1f[indice2d]*e2f[indice2d])[*]#replicate(1., nzt))
148      landf =  where(tabf EQ 0)
149;
150      zu = temporary(u) * temporary(coefu)
151      zv = temporary(v) * temporary(coefv)
152
153      psi = (shift(zv, -1, 0, 0)-zv) + (zu-shift(zu, 0, -1, 0))
154      psi = temporary(tabf) * temporary(psi)
155;------------------------------------------------------------
156; Edging put at !values.f_nan
157;------------------------------------------------------------
158      if NOT keyword_set(key_periodic)  OR nx NE jpi then begin
159        psi[0, *, *] = !values.f_nan
160        psi[nx-1, *, *] = !values.f_nan
161      endif
162      psi[*, 0, *] = !values.f_nan
163      psi[*, ny-1, *] = !values.f_nan
164;
165      if landf[0] NE -1 then psi[temporary(landf)] = valmask
166      if keyword_set(direc) then psi = moyenne(psi, direc, /nan)
167    END
168;----------------------------------------------------------------------------
169;----------------------------------------------------------------------------
170;xyt
171;----------------------------------------------------------------------------
172;----------------------------------------------------------------------------
173    szu[0] EQ 3 AND jpt GT 1:BEGIN
174;------------------------------------------------------------
175; extraction of U and V on the appropriated domain
176;------------------------------------------------------------
177      case 1 of
178        szu[1] EQ nxu AND szu[2] EQ nyu AND $
179           szv[1] EQ nxv AND szv[2] EQ nyv:BEGIN
180          if nxu NE nx then $
181             if indicex[0] EQ firstxu then u = u[0:nx-1, *, *] ELSE u = u[1: nx, *, *]
182          IF nxv NE nx THEN $
183             if indicex[0] EQ firstxv then v = v[0:nx-1, *, *] ELSE v = v[1: nx, *, *]
184          IF nyu NE ny THEN $
185             if indicey[0] EQ firstyu then u = u[*, 0:ny-1, *] ELSE u = u[*, 1: ny, *]
186          IF nyv NE ny THEN $
187             if indicey[0] EQ firstyv then v = v[*, 0:ny-1, *] ELSE v = v[*, 1: ny, *]
188        END
189        szu[1] EQ jpi AND szu[2] EQ jpj AND $
190           szv[1] EQ jpi AND szv[2] EQ jpj:BEGIN
191          u = u[indicex[0]:indicex[0]+nx-1, indicey[0]:indicey[0]+ny-1, *]
192          v = v[indicex[0]:indicex[0]+nx-1, indicey[0]:indicey[0]+ny-1, *]
193        END
194        ELSE:BEGIN
195          print, 'problemes d''adequation entre la taille du domaine et la taille des matrices necessaires a tracer des vecteurs'
196          return, -1
197        end
198      endcase
199;----------------------------------------------------------------------------
200; curl computation
201;----------------------------------------------------------------------------
202      coefu = e1u[indice2d]*(umask())[indice2d+jpi*jpj*firstzt]
203      landu = where(coefu EQ 0)
204      if landu[0] NE -1 then coefu[temporary(landu)] = !values.f_nan
205      coefu = temporary(coefu[*])#replicate(1., jpt)
206;
207      coefv = e2v[indice2d]*(vmask())[indice2d+jpi*jpj*firstzt]
208      landv = where(coefv EQ 0)
209      if landv[0] NE -1 then coefv[temporary(landv)] = !values.f_nan
210      coefv = temporary(coefv[*])#replicate(1., jpt)
211;
212      tabf = (fmask())[indice2d+jpi*jpj*firstzt]/(e1f[indice2d]*e2f[indice2d])
213      tabf = temporary(tabf[*])#replicate(1., jpt)
214      landf = where(tabf EQ 0)
215;
216      zu = temporary(u) * temporary(coefu)
217      zv = temporary(v) * temporary(coefv)
218;
219      psi = (shift(zv, -1, 0, 0)-zv) + (zu-shift(zu, 0, -1, 0))
220      psi = temporary(tabf) * temporary(psi)
221;------------------------------------------------------------
222; extraction of U and V on the appropriated domain
223;------------------------------------------------------------
224      if NOT keyword_set(key_periodic) OR nx NE jpi then begin
225        psi[0, *, *] = !values.f_nan
226        psi[nx-1, *, *] = !values.f_nan
227      endif
228      psi[*, 0, *] = !values.f_nan
229      psi[*, ny-1, *] = !values.f_nan
230      if landf[0] NE -1 then psi[temporary(landf)] = valmask
231      if keyword_set(direc) then psi = grossemoyenne(psi, direc, /nan)
232    END
233;----------------------------------------------------------------------------
234;----------------------------------------------------------------------------
235;xyzt
236;----------------------------------------------------------------------------
237;----------------------------------------------------------------------------
238    szu[0] EQ 4:BEGIN
239      return, report('Case not coded contact saxo team or make a do loop!')
240    END
241;----------------------------------------------------------------------------
242;----------------------------------------------------------------------------
243;xy
244;----------------------------------------------------------------------------
245;----------------------------------------------------------------------------
246    szu[0] EQ 2:BEGIN
247;------------------------------------------------------------
248;------------------------------------------------------------
249      case 1 of
250        szu[1] EQ nxu AND szu[2] EQ nyu AND $
251           szv[1] EQ nxv AND szv[2] EQ nyv:BEGIN
252          if nxu NE nx then $
253             if indicex[0] EQ firstxu then u = u[0:nx-1, *] ELSE u = u[1: nx, *]
254          IF nxv NE nx THEN $
255             if indicex[0] EQ firstxv then v = v[0:nx-1, *] ELSE v = v[1: nx, *]
256          IF nyu NE ny THEN $
257             if indicey[0] EQ firstyu then u = u[*, 0:ny-1] ELSE u = u[*, 1: ny]
258          IF nyv NE ny THEN $
259             if indicey[0] EQ firstyv then v = v[*, 0:ny-1] ELSE v = v[*, 1: ny]
260        END
261        szu[1] EQ jpi AND szu[2] EQ jpj AND $
262           szv[1] EQ jpi AND szv[2] EQ jpj:BEGIN
263          u = u[indice2d]
264          v = v[indice2d]
265        END
266        ELSE:return,  -1
267      endcase
268;------------------------------------------------------------
269; curl computation
270;------------------------------------------------------------
271      coefu = e1u[indice2d]*(umask())[indice2d+jpi*jpj*firstzt]
272      landu = where(coefu EQ 0)
273      if landu[0] NE -1 then coefu[temporary(landu)] = !values.f_nan
274      coefv = e2v[indice2d]*(vmask())[indice2d+jpi*jpj*firstzt]
275      landv = where(coefv EQ 0)
276      if landv[0] NE -1 then coefv[temporary(landv)] = !values.f_nan
277      tabf = (fmask())[indice2d+jpi*jpj*firstzt]/(e1f[indice2d]*e2f[indice2d])
278      landf =  where(tabf EQ 0)
279;
280      zu = temporary(u) * temporary(coefu)
281      zv = temporary(v) * temporary(coefv)
282
283      psi = (shift(zv, -1, 0)-zv) + (zu-shift(zu, 0, -1))
284      psi = temporary(tabf) * temporary(psi)
285;------------------------------------------------------------
286; Edging put at !values.f_nan
287;------------------------------------------------------------
288      if  NOT keyword_set(key_periodic) OR nx NE jpi then begin
289        psi[0, *] = !values.f_nan
290        psi[nx-1, *] = !values.f_nan
291      endif
292      psi[*, 0] = !values.f_nan
293      psi[*, ny-1] = !values.f_nan
294;
295      if landf[0] NE -1 then psi[temporary(landf)] = valmask
296      if keyword_set(direc) then psi = moyenne(psi, direc, /nan)
297    END
298;----------------------------------------------------------------------------
299;----------------------------------------------------------------------------
300    ELSE:return, report('U and V input arrays must have 2, 3 or 4 dimensions')
301  ENDCASE
302;------------------------------------------------------------
303  if keyword_set(key_performance) THEN print, 'temps curl', systime(1)-tempsun
304
305  return, psi
306end
Note: See TracBrowser for help on using the repository browser.