source: trunk/SRC/Computation/curl.pro @ 168

Last change on this file since 168 was 168, checked in by pinsard, 18 years ago

Main document available on top directory, Source links available in idldoc html output

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