source: trunk/SRC/Grid/computegrid.pro @ 421

Last change on this file since 421 was 421, checked in by smasson, 14 years ago

make sure that x[y]min[max]mesh are properly used

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 48.6 KB
Line 
1;+
2;
3; @file_comments
4; compute the grid parameters (cm_4mesh) common
5;
6; domains sizes:
7; ---------------
8; jpi, jpj, jpk, jpiglo, jpjglo, jpkglo, jpidta, jpjdta, jpkdta
9;
10; domains positions regarding to the original grid:
11; --------------------------------------------------
12; ixminmesh, ixmaxmesh, iyminmesh, iymaxmesh, izminmesh, izmaxmesh
13; ixmindta, ixmaxdta, iymindta, iymaxdta, izmindta, izmaxdta
14;
15; horizontal parameters:
16; ----------------------
17; glamt, glamf, gphit, gphit, e1t, e2t
18;
19; additional horizontal parameters if FULLCGRID keyword is defined:
20; -----------------------------------------------------------------
21; glamu, glamv, gphiu, gphiv, e1u, e1v, e1f, e2u, e2v, e2f
22;
23; verticals parameters:
24; ---------------------
25; gdept, gdepw, e3t, e3w
26;
27; masks:
28; ------
29; tmask
30;
31; additional masks if FULLCGRID keyword is defined:
32; -------------------------------------------------
33; umaskred, vmaskred, fmaskredx, fmaskredy
34;
35; triangles_list:
36; ---------------
37; triangulation
38;
39; key_* variables:
40; ----------------
41; key_onearth, key_periodic, key_shift, key_stride, key_partialstep,
42; key_yreverse, key_zreverse, key_gridtype
43;
44; xxx related variables:
45; ----------------------
46; ccmeshparameters, ccreadparameters
47;
48; @categories
49; Grid
50;
51; @param startx {in}{optional}{type=scalar}
52;       x starting point, optional if [XY]AXIS keyword is used
53;
54; @param starty {in}{optional}{type=scalar}
55;       y starting point, optional if [XY]AXIS keyword is used
56;
57; @param stepxin {in}{optional}{type=scalar or vector}
58;       x direction step, optional if [XY]AXIS keyword is used, must be > 0
59;       if stepxin is a vector nx is not used
60;
61; @param stepyin {in}{optional}{type=scalar or vector}
62;       y direction step, optional if [XY]AXIS keyword is used,
63;       could be > 0 (south to north) or < 0 (north to south)
64;       if stepyin is a vector ny is not used
65;
66; @param nxin {in}{optional}{type=scalar}
67;       number of points in x direction,
68;       optional if [XY]AXIS keyword is used or stepxin is a vector
69;
70; @param nyin {in}{optional}{type=scalar}
71;       number of points in y direction,
72;       optional if [XY]AXIS keyword is used or stepyin is a vector
73;
74; @keyword FULLCGRID {default=0}{type=scalar: 0 or 1}
75;       Activate to specify that you want to compute all the C grid parameters:
76;       definition of glam[uv], gphi[uv], e1[uvf], e2[uvf], [uv]maskred and
77;       fmaskred[xy] will be add to the default computations
78;
79; @keyword GLAMBOUNDARY {default=those defined in the file}{type=2 elements vector}
80;       Longitude boundaries that should be used to visualize the data.
81;         lon2 > lon1
82;         lon2 - lon1 le 360
83;       By default, the common (cm_4mesh) variable key_shift will be automatically
84;       defined according to GLAMBOUNDARY.
85;
86; @keyword MASK {default=array of 1}{type=2D or 3D array}
87;       Specify the land(0)/sea(1) mask
88;
89; @keyword ONEARTH {default=1}{type=scalar: 0 or 1}
90;       Force the manual definition of data localization on the earth or not
91;          0) if the data are not on the earth
92;          1) if the data are on earth (in that case we can for example use
93;             the labels 'longitude', 'latitude' in plots).
94;       The resulting value will be stored in the common (cm_4mesh) variable key_onearth
95;       ONEARTH=0 forces PERIODIC=0, SHIFT=0 and is cancelling GLAMBOUNDARY
96;
97; @keyword PERIODIC {default=computed by using the first line of glamt}{type=scalar: 0 or 1}
98;       Force the manual definition of the grid zonal periodicity.
99;       The resulting value will be stored in the common (cm_4mesh) variable key_periodic
100;       PERIODIC=0 forces SHIFT=0
101;
102; @keyword PLAIN {default=0}{type=scalar: 0 or 1}
103;       Force YREVERSE=0, ZREVERSE=0, PERIODIC=0, SHIFT=0, STRIDE=[1, 1, 1] and
104;       suppress the automatic redefinition of the domain in case of x periodicity overlap,
105;       y periodicity overlap (ORCA type only) and mask border to 0.
106;
107; @keyword SHIFT {default=computed according to glamboundary}{type=scalar}
108;       Force the manual definition of the zonal shift that must be apply to the data.
109;       The resulting value will be stored in the common (cm_4mesh) variable key_shift
110;       Note that if key_periodic=0 then in any case key_shift=0.
111;
112; @keyword STRCALLING {type=string}
113;       a string containing the calling command used to
114;       call computegrid (this is used by <pro>xxx</pro>)
115;
116; @keyword STRIDE {default=[1, 1, 1]}{type=3 elements vector}
117;       Specify the stride in x, y and z direction. The resulting
118;       value will be stored in the common (cm_4mesh) variable key_stride
119;
120; @keyword XAXIS {type=1D or 2D array}
121;       Specify longitudes in this case startx, stepx and nx are not used but
122;       could be necessary if the y axis is not defined with yaxis. It must be
123;       possible to sort the first line of xaxis in the increasing order by
124;       shifting its elements.
125;
126; @keyword YAXIS {type=1D or 2D array}
127;       Specify latitudes in this case starty, stepy and ny are not used but
128;       starty and stepy could be necessary if the x axis is not defined with
129;       xaxis. It must be sorted in the increasing or decreasing order (along each column if 2d array).
130;
131; @keyword XYINDEX activate to specify that the horizontal grid should
132;       be simply defined by using the index of the points
133;          (xaxis = findgen(nx) and yaxis = findgen(ny))
134;       using this keyword forces key_onearth=0
135;
136; @keyword XMINMESH {default=0L}{type=scalar}
137;       Define common (cm_4mesh) variables ixminmesh used to define the localization
138;       of the first point of the grid along the x direction in a zoom of the original grid
139;
140; @keyword YMINMESH {default=0L}{type=scalar}
141;       Define common (cm_4mesh) variables iyminmesh used to define the localization
142;       of the first point of the grid along the y direction in a zoom of the original grid
143;
144; @keyword ZMINMESH {default=0L}{type=scalar}
145;       Define common (cm_4mesh) variables izminmesh used to define the localization
146;       of the first point of the grid along the z direction in a zoom of the original grid
147;
148; @keyword XMAXMESH {default=jpiglo-1}{type=scalar}
149;       Define common (cm_4mesh) variables ixmaxmesh used to define the localization
150;       of the last point of the grid along the x direction in a zoom of the original grid
151;       Note that if XMAXMESH < 0 then ixmaxmesh is defined as ixmaxmesh = jpiglo -1 + xmaxmesh
152;
153; @keyword YMAXMESH {default=jpjglo-1}{type=scalar}
154;       Define common (cm_4mesh) variables iymaxmesh used to define the localization
155;       of the last point of the grid along the y direction in a zoom of the original grid
156;       Note that if YMAXMESH < 0 then iymaxmesh is defined as iymaxmesh = jpjglo -1 + ymaxmesh
157;
158; @keyword ZMAXMESH {default=jpkglo-1}{type=scalar}
159;       Define common (cm_4mesh) variables izmaxmesh used to define the localization
160;       of the last point of the grid along the z direction in a zoom of the original grid
161;       Note that if ZMAXMESH < 0 then izmaxmesh is defined as izmaxmesh = jpkglo -1 + maxmesh
162;
163; @keyword FBASE2TBASE
164;       Activate when the model is a C grid based on a F point
165;       (with a F point at the bottom-left corner and a T point at the
166;       upper-right corner). In this case, we ignore
167;         - the first line of F and V points
168;         - the last  line of T and U points
169;         - if the grid is not x-periodic, the first column of F and U points
170;         - if the grid is not x-periodic, the last  column of T and V points.
171;       => we are back to a C grid based on T point as for OPA model.
172;       Note that in that case, key_gridtype = 'c_f' and not 'c' (-> used in read_ncdf)
173;       Note that activate FBASE2TBASE forces FULLCGRID=1
174;
175; @keyword UBASE2TBASE
176;       Activate when the model is a C grid based on a U point
177;       (with a U point at the bottom-left corner and a T point at the
178;       upper-right corner). In this case, we ignore
179;         - if the grid is not x-periodic, the first column of F and U points
180;         - if the grid is not x-periodic, the last  column of T and V points.
181;       => we are back to a C grid based on T point as for OPA model.
182;       Note that in that case, key_gridtype = 'c_u' and not 'c' (-> used in read_ncdf)
183;       Note that activate UBASE2TBASE forces FULLCGRID=1
184;
185; @keyword VBASE2TBASE
186;       Activate when the model is a C grid based on a V point
187;       (with a V point at the bottom-left corner and a T point at the
188;       upper-right corner). In this case, we ignore
189;         - the first line of F and V points
190;         - the last  line of T and U points
191;       => we are back to a C grid based on T point as for OPA model.
192;       Note that in that case, key_gridtype = 'c_v' and not 'c' (-> used in read_ncdf)
193;       Note that activate VBASE2TBASE forces FULLCGRID=1
194;
195; @keyword ROMSH {type=2D array}
196;       This array is the final bathymetry at RHO-points. It is stored in the common
197;       variable (cm_4mesh) romszinfos.h
198;       Used when the model is a ROMS C-grid with one more point
199;       in longitude for T and V grid and one more point in latitude
200;       for T and U grid. In this case, we ignore
201;         - the last line of T and U points
202;         - the last column of T and V points.
203;      => we are back to a C grid based on T point as for OPA model.
204;       Note that activate ROMSH forces FULLCGRID=1
205;
206; @keyword STRCALLING {type=scalar string}
207;       Used by xxx...
208;
209; @keyword YREVERSE {default=computed according to gphit[0, 1:jpj-1] LT gphit[0, 0:jpj-2]}{type=scalar}
210;       Force the manual definition of the y reverse that must be apply to the data.
211;       The resulting value will be stored in the common (cm_4mesh) variable key_yreverse
212;
213; @keyword ZAXIS {type=1D}
214;       Specify the vertical axis. Must be sorted in the increasing or decreasing order
215;
216; @keyword ZREVERSE {default=computed according to gdept[0] GT gdept[1]}{type=scalar}
217;       Force the manual definition of the z reverse that must be apply to the data.
218;       The resulting value will be stored in the common (cm_4mesh) variable key_zreverse
219;
220; @keyword _EXTRA
221; not used in the present case ...
222;
223; @uses
224; <pro>cm_4mesh</pro>
225; <pro>cm_4data</pro>
226; <pro>cm_4cal</pro>
227;
228
229; @restrictions
230; if the grid has x/y periodicity overlap and/or if
231; the mask has 0 everywhere at the border (like a closed sea) and
232; if (we did not activate /plain and xminmesh, xmaxmesh, yminmesh,
233; ymaxmesh keywords are defined to their default values), we redefine
234; xminmesh, xmaxmesh, yminmesh, ymaxmesh in order to remove the
235; overlapping part and/or to open the domain (avoid it be forced
236; to use cell_fill = 1).
237;
238; FUV points definition is not exact if the grid is irregular
239;
240; @history
241; Sebastien Masson (smasson\@lodyc.jussieu.fr)
242;                      2000-04-20
243; Sept 2004, several bug fix to suit C grid type...
244; Aug 2005, rewritte almost everything...
245;
246; @version
247; $Id$
248;
249;-
250PRO computegrid, startx, starty, stepxin, stepyin, nxin, nyin $
251                 , XAXIS=xaxis, YAXIS=yaxis, ZAXIS=zaxis $
252                 , MASK=mask, GLAMBOUNDARY=glamboundary $
253                 , XMINMESH=xminmesh, XMAXMESH=xmaxmesh $
254                 , YMINMESH=yminmesh, YMAXMESH=ymaxmesh $
255                 , ZMINMESH=zminmesh, ZMAXMESH=zmaxmesh $
256                 , ONEARTH=onearth, PERIODIC=periodic $
257                 , PLAIN=plain, SHIFT=shift, STRIDE=stride $
258                 , YREVERSE=yreverse, ZREVERSE=zreverse  $
259                 , FULLCGRID=fullcgrid, XYINDEX=xyindex $
260                 , UBASE2TBASE=ubase2tbase, VBASE2TBASE=vbase2tbase $
261                 , FBASE2TBASE=fbase2tbase $
262                 , STRCALLING=strcalling, ROMSH=romsh, _EXTRA=ex
263;
264  compile_opt idl2, strictarrsubs
265;
266@cm_4mesh
267@cm_4data
268@cm_4cal
269  IF NOT keyword_set(key_forgetold) THEN BEGIN
270@updatenew
271@updatekwd
272  ENDIF
273;---------------------------------------------------------
274;------------------------------------------------------------
275  time1 = systime(1)            ; for key_performance
276;------------------------------------------------------------
277;
278;====================================================
279; Check input parameters
280;====================================================
281;
282; xaxis related parameters
283;
284  if n_elements(xaxis) NE 0 then BEGIN
285    CASE (size(xaxis))[0] OF
286      0:nx = 1L
287      1:nx = (size(xaxis))[1]
288      2:nx = (size(xaxis))[1]
289    ENDCASE
290  ENDIF ELSE BEGIN
291    IF n_elements(startx) EQ 0 THEN BEGIN
292      dummy = report('If xaxis is not given, startx must be defined')
293      return
294    ENDIF
295    CASE n_elements(stepxin) OF
296      0:BEGIN
297        dummy = report('If xaxis is not given, stepxin must be defined')
298        return
299      END
300      1:BEGIN
301        IF n_elements(nxin) EQ 0 THEN BEGIN
302          dummy = report('If xaxis is not given and stepxin has only one element, nx must be defined')
303          return
304        ENDIF ELSE nx = nxin
305      END
306      ELSE:nx = n_elements(stepxin)
307    ENDCASE
308  ENDELSE
309;
310; yaxis related parameters
311;
312  if n_elements(yaxis) NE 0 then BEGIN
313    CASE (size(yaxis))[0] OF
314      0:ny = 1L
315      1:ny = (size(yaxis))[1]
316      2:ny = (size(yaxis))[2]
317    ENDCASE
318  ENDIF ELSE BEGIN
319    IF n_elements(starty) EQ 0 THEN BEGIN
320      dummy = report('If yaxis is not given, starty must be defined')
321      return
322    ENDIF
323    CASE n_elements(stepyin) OF
324      0:BEGIN
325        dummy = report('If yaxis is not given, stepyin must be defined')
326        return
327      END
328      1:BEGIN
329        IF n_elements(nyin) EQ 0 THEN BEGIN
330          dummy = report('If yaxis is not given and stepyin has only one element, ny must be defined')
331          return
332        ENDIF ELSE ny = nyin
333      END
334      ELSE:ny = n_elements(stepyin)
335    ENDCASE
336  ENDELSE
337;
338; zaxis related parameters
339;
340  if n_elements(zaxis) NE 0 then BEGIN
341    CASE (size(zaxis))[0] OF
342      0:nz = 1L
343      1:nz = (size(zaxis))[1]
344      ELSE:BEGIN
345        ras = report( 'not coded')
346        stop
347      END
348    ENDCASE
349  ENDIF ELSE nz = 1L
350;
351;====================================================
352; Others automatic definitions...
353;====================================================
354;
355  IF keyword_set(romsh) THEN fullcgrid = 1
356  CASE 1 OF
357    keyword_set(fbase2tbase):key_gridtype = 'c_f'
358    keyword_set(ubase2tbase):key_gridtype = 'c_u'
359    keyword_set(vbase2tbase):key_gridtype = 'c_v'
360    else:key_gridtype = 'c'
361  ENDCASE
362  IF strlen(key_gridtype) EQ 3 THEN fullcgrid = 1
363;
364  IF n_elements(xminmesh) NE 0 OR n_elements(xmaxmesh) NE 0 THEN BEGIN
365    IF n_elements(xminmesh) EQ 0 THEN xminmesh = ixminmesh
366    IF n_elements(xmaxmesh) EQ 0 THEN xmaxmesh = ixmaxmesh
367    IF nx EQ jpi AND xminmesh EQ ixminmesh AND xmaxmesh EQ ixmaxmesh THEN xalreadycut = 1
368  ENDIF
369  IF keyword_set(xalreadycut) THEN BEGIN
370    xmin = 0
371    xmax = jpi - 1
372    nxx = jpi
373  ENDIF ELSE BEGIN
374    jpiglo = long(nx)
375    IF keyword_set(romsh) THEN jpiglo = jpiglo - 1   
376    IF n_elements(xminmesh) NE 0 THEN ixminmesh = long(xminmesh[0]) ELSE ixminmesh  = 0l
377    IF n_elements(xmaxmesh) NE 0 THEN ixmaxmesh = long(xmaxmesh[0]) ELSE ixmaxmesh  = jpiglo-1
378    IF ixmaxmesh LT 0 THEN ixmaxmesh = jpiglo -1 + ixmaxmesh
379    ixmaxmesh = 0 > ixmaxmesh < (jpiglo-1)
380    ixminmesh = 0 > ixminmesh < ixmaxmesh
381    jpi = ixmaxmesh-ixminmesh+1
382    xmin = ixminmesh
383    xmax = ixmaxmesh
384    nxx = jpiglo
385  ENDELSE
386
387  IF n_elements(yminmesh) NE 0 OR n_elements(ymaxmesh) NE 0 THEN BEGIN
388    IF n_elements(yminmesh) EQ 0 THEN yminmesh = iyminmesh
389    IF n_elements(ymaxmesh) EQ 0 THEN ymaxmesh = iymaxmesh
390    IF ny EQ jpj AND yminmesh EQ iyminmesh AND ymaxmesh EQ iymaxmesh THEN yalreadycut = 1
391  ENDIF
392  IF keyword_set(yalreadycut) THEN BEGIN
393    ymin = 0
394    ymax = jpj - 1
395    nyy = jpj
396  ENDIF ELSE BEGIN
397    jpjglo = long(ny)
398    IF keyword_set(romsh) THEN jpjglo = jpjglo - 1
399    IF n_elements(yminmesh) NE 0 THEN iyminmesh = long(yminmesh[0]) ELSE iyminmesh  = 0l
400    IF n_elements(ymaxmesh) NE 0 THEN iymaxmesh = long(ymaxmesh[0]) ELSE iymaxmesh  = jpjglo-1
401    IF key_gridtype EQ 'c_v' OR key_gridtype EQ 'c_f' THEN iymaxmesh = iymaxmesh-1
402    IF iymaxmesh LT 0 THEN iymaxmesh = jpjglo -1 + iymaxmesh
403    iymaxmesh = 0 > iymaxmesh < (jpjglo-1)
404    iyminmesh = 0 > iyminmesh < iymaxmesh
405    jpj = iymaxmesh-iyminmesh+1
406    ymin = iyminmesh
407    ymax = iymaxmesh
408    nyy = jpjglo
409  ENDELSE
410
411  IF n_elements(zminmesh) NE 0 AND n_elements(zmaxmesh) NE 0 THEN BEGIN
412    IF nz EQ jpk AND zminmesh EQ izminmesh AND zmaxmesh EQ izmaxmesh THEN zalreadycut = 1
413  ENDIF
414  IF keyword_set(zalreadycut) THEN BEGIN
415    zmin = 0
416    zmax = jpk - 1
417    nzz = jpk
418  ENDIF ELSE BEGIN
419   jpkglo = long(nz)
420    IF n_elements(zminmesh) NE 0 THEN izminmesh = long(zminmesh[0]) ELSE izminmesh  = 0l
421    IF n_elements(zmaxmesh) NE 0 THEN izmaxmesh = long(zmaxmesh[0]) ELSE izmaxmesh  = jpkglo-1
422    IF izmaxmesh LT 0 THEN izmaxmesh = jpkglo -1 + izmaxmesh
423    izmaxmesh = 0 > izmaxmesh < (jpkglo-1)
424    izminmesh = 0 > izminmesh < izmaxmesh
425    jpk = izmaxmesh-izminmesh+1
426    zmin = izminmesh
427    zmax = izmaxmesh
428    nzz = jpkglo
429  ENDELSE
430;
431; impact of plain keyword:
432;
433  IF keyword_set(plain) THEN BEGIN
434    yreverse = 0
435    zreverse = 0
436    periodic = 0
437    shift = 0
438    stride = [1, 1, 1]
439  ENDIF
440;
441; avoid basics errors...
442;
443  jpidta = jpiglo
444  jpjdta = jpjglo
445  jpkdta = jpkglo
446  ixmindta = 0
447  ixmaxdta = jpidta-1
448  iymindta = 0
449  iymaxdta = jpjdta-1
450  izmindta = 0
451  izmaxdta = jpkdta-1
452;
453  key_partialstep = 0
454  if n_elements(stride) eq 3 then key_stride = stride $
455  ELSE key_stride = [1, 1, 1]
456;
457; check xyindex and its consequences
458;
459  if keyword_set(xyindex) then onearth = 0
460;
461; check onearth and its consequences
462;
463  IF n_elements(onearth) EQ 0 THEN key_onearth = 1b $
464  ELSE key_onearth = keyword_set(onearth)
465  IF NOT key_onearth THEN BEGIN
466    periodic = 0
467    shift = 0
468  ENDIF
469
470  r = 6371000.
471;
472;====================================================
473; X direction : glamt
474;====================================================
475;
476; def of glamt
477;
478  if n_elements(xaxis) NE 0 then BEGIN
479    if keyword_set(xyindex) THEN glamt = findgen(jpiglo) ELSE glamt = xaxis
480  ENDIF ELSE BEGIN
481    if keyword_set(xyindex) THEN stepx = 1. ELSE stepx = stepxin
482    CASE 1 OF
483      n_elements(stepx):glamt = startx + findgen(jpiglo)*stepx
484      size(stepx, /n_dimensions):glamt = startx + total(stepx, /cumulative)
485      ELSE:BEGIN
486        dummy = report('Wrong definition of stepx...')
487        return
488      END
489    ENDCASE
490  ENDELSE
491;
492; apply glamboundary
493;
494  IF keyword_set(glamboundary) AND key_onearth THEN BEGIN
495    IF glamboundary[0] GE glamboundary[1] THEN stop
496    IF glamboundary[1]-glamboundary[0] GT 360 THEN stop
497    glamt = glamt MOD 360
498    smaller = where(glamt LT glamboundary[0])
499    if smaller[0] NE -1 then glamt[smaller] = glamt[smaller]+360.
500    bigger = where(glamt GE glamboundary[1])
501    if bigger[0] NE -1 then glamt[bigger] = glamt[bigger]-360.
502  ENDIF
503;
504; force glamt to have 2 dimensions
505;
506  IF n_elements(glamt) EQ nxx*nyy THEN glamt = reform(glamt, nxx, nyy, /over) $
507  ELSE glamt = reform(glamt, nxx, /over)
508  CASE size(glamt, /n_dimensions) OF
509    1:BEGIN
510      IF n_elements(glamt) EQ 1 THEN glamt = replicate(glamt[0], jpi, jpj) $
511      ELSE glamt = glamt[xmin:xmax]#replicate(1, jpj)
512    END
513    2:glamt = glamt[xmin:xmax, ymin:ymax]
514  ENDCASE
515; keep 2d array even with degenerated dimension
516  IF jpj EQ 1 THEN glamt = reform(glamt, jpi, jpj, /over)
517;
518;====================================================
519; Y direction : gphit
520;====================================================
521;
522; def of gphit
523;
524  if n_elements(yaxis) NE 0 THEN BEGIN
525    if keyword_set(xyindex) THEN gphit = findgen(jpjglo) ELSE gphit = yaxis
526  ENDIF ELSE BEGIN
527    if keyword_set(xyindex) THEN stepy = 1. ELSE stepy = stepyin
528    CASE 1 OF
529      n_elements(stepy):gphit = starty + findgen(jpjglo)*stepy
530      size(stepy, /n_dimensions):gphit = starty + total(stepy, /cumulative)
531      ELSE:BEGIN
532        dummy = report('Wrong definition of stepy...')
533        return
534      END
535    ENDCASE
536  ENDELSE
537;
538; force gphit to have 2 dimensions
539;
540  IF n_elements(gphit) EQ nxx*nyy THEN gphit = reform(gphit, nxx, nyy, /over) $
541  ELSE gphit = reform(gphit, nyy, /over)
542  CASE size(gphit, /n_dimensions) OF
543    1:BEGIN
544      IF n_elements(gphit) EQ 1 THEN gphit = replicate(gphit[0], jpi, jpj) $
545      ELSE gphit = replicate(1, jpi)#gphit[ymin:ymax]
546    END
547    2:gphit = gphit[xmin:xmax, ymin:ymax]
548  ENDCASE
549; keep 2d array even with degenerated dimension
550  IF jpj EQ 1 THEN gphit = reform(gphit, jpi, jpj, /over)
551;
552;====================================================
553; check y periodicity... Only according to ORCA grid
554;====================================================
555; check the periodicity if iyminmesh and iymaxmesh have the default definitions...
556  IF NOT keyword_set(plain) AND key_onearth EQ 1 $
557    AND iyminmesh EQ 0l AND iymaxmesh eq jpjglo-1 AND jpj GE 3 AND jpi GE 2 THEN BEGIN
558
559    CASE 1 OF
560      ixminmesh EQ 0l AND ixmaxmesh eq jpiglo-1 $
561        AND array_equal(gphit[1:*, jpj-1], reverse(gphit[1:*, jpj-3])) EQ 1:BEGIN
562; T pivot
563        ymaxmesh = -1
564        recall = 1
565      END
566      ixminmesh EQ 1l AND ixmaxmesh eq jpiglo-2 $
567         AND array_equal(gphit[*, jpj-1], reverse(shift(gphit[*, jpj-3], -1))) EQ 1:BEGIN
568; T pivot
569        ymaxmesh = -1
570        recall = 1
571      END
572      ixminmesh EQ 0l AND ixmaxmesh eq jpiglo-1 $
573       AND array_equal(gphit[*, jpj-1], reverse(gphit[*, jpj-2])) EQ 1:BEGIN
574; F pivot
575        ymaxmesh = -1
576        recall = 1
577      END
578      ixminmesh EQ 1l AND ixmaxmesh eq jpiglo-2 $
579         AND array_equal(gphit[*, jpj-1], reverse(gphit[*, jpj-2])) EQ 1:BEGIN
580; F pivot
581        ymaxmesh = -1
582        recall = 1
583      END
584      ELSE:
585    ENDCASE
586  ENDIF
587;
588;====================================================
589; check x periodicity...
590;====================================================
591IF n_elements(periodic) NE 0 THEN forcenoperio = 1 - keyword_set(periodic)
592; check the periodicity if ixminmesh and ixmaxmesh have the default definitions...
593  IF NOT keyword_set(plain) AND NOT keyword_set(forcenoperio) AND key_onearth EQ 1 $
594     AND ixminmesh EQ 0l AND ixmaxmesh eq jpiglo-1 AND jpi GE 3 THEN BEGIN
595    CASE 0 OF
596      total((glamt[0, *] - glamt[jpi-2, *]) MOD 360) $
597      + total((glamt[1, *] - glamt[jpi-1, *]) MOD 360):BEGIN
598        xminmesh = 1
599        xmaxmesh = -1
600        recall = 1
601      END
602      total((glamt[0, *] - glamt[jpi-2, *]) MOD 360):BEGIN
603        xminmesh = 1
604        recall = 1
605      END
606      total((glamt[1, *] - glamt[jpi-1, *]) MOD 360):BEGIN
607        xmaxmesh = -1
608        recall = 1
609      END
610      ELSE:
611    ENDCASE
612  ENDIF
613;====================================================
614; recall computegrid if needed...
615;====================================================
616  IF keyword_set(recall) THEN BEGIN
617    computegrid, XAXIS = glamt, YAXIS = gphit, ZAXIS = zaxis $
618                 , MASK = mask, GLAMBOUNDARY = glamboundary $
619                 , XMINMESH = xminmesh, XMAXMESH = xmaxmesh $
620                 , YMINMESH = yminmesh, YMAXMESH = ymaxmesh $
621                 , ZMINMESH = zminmesh, ZMAXMESH = zmaxmesh $
622                 , PERIODIC = periodic, SHIFT = shift, STRIDE = stride $
623                 , FULLCGRID = fullcgrid, XYINDEX = xyindex $
624                 , STRCALLING = strcalling $
625                 , ROMSH = romsh, _extra = ex
626    return
627  ENDIF
628;
629;====================================================
630; def key_yreverse
631;====================================================
632;
633  IF n_elements(yreverse) EQ 0 THEN BEGIN
634    IF jpj GT 1 THEN BEGIN
635      IF total(gphit[0, 1:jpj-1] LT gphit[0, 0:jpj-2]) GT jpj/2 THEN key_yreverse = 1 ELSE key_yreverse = 0
636    ENDIF ELSE key_yreverse = 0
637  ENDIF ELSE key_yreverse = yreverse
638  IF keyword_set(key_yreverse) THEN BEGIN
639    gphit = reverse(gphit, 2)
640    glamt = reverse(glamt, 2)
641  ENDIF
642;
643;====================================================
644; def of key_shift
645;====================================================
646;
647; definition of key_shift by shifting the array to have the min
648; values of glamt[*, 0] in glamt[0, 0]
649;
650  IF n_elements(shift) EQ 0 THEN BEGIN
651    IF jpi GT 1 then BEGIN
652      xtest = glamt[*, 0]
653      key_shift = (where(xtest EQ min(xtest)))[0]
654      IF key_shift NE 0 THEN key_shift = jpi - key_shift
655    ENDIF ELSE key_shift = 0
656  ENDIF ELSE key_shift = shift
657;
658;====================================================
659; def of key_periodic
660;====================================================
661;
662  IF n_elements(periodic) EQ 0 THEN BEGIN
663    IF jpi GT 1 THEN BEGIN
664      xtest = shift(glamt[*, 0], key_shift)
665; check that xtest is now sorted in the increasing order
666      IF array_equal(sort(xtest), lindgen(jpi)) EQ 0 THEN BEGIN
667        ras = report(['WARNING: we cannot sort the xaxis with a simple shift...', $
668        'we force key_periodic = 0 and key_shift = 0', $
669        'only horizontal plot may be ok...'])
670        key_periodic = 0
671        xnotsorted = 1
672      ENDIF ELSE BEGIN
673        key_periodic = (xtest[jpi-1]+2*(xtest[jpi-1]-xtest[jpi-2])) $
674                       GE (xtest[0]+360)
675      ENDELSE
676    ENDIF ELSE key_periodic = 0
677  ENDIF ELSE key_periodic = keyword_set(periodic)
678;
679; update key_shift
680;
681  key_shift = key_shift * (key_periodic EQ 1)
682;
683  IF (key_gridtype EQ 'c_u' OR key_gridtype EQ 'c_f') AND NOT keyword_set(key_periodic) THEN BEGIN
684    ixmaxmesh = ixmaxmesh-1
685    jpi = jpi-1
686  ENDIF
687;
688;====================================================
689; apply key_shift
690;====================================================
691;
692  if keyword_set(key_shift) then BEGIN
693    glamt = shift(glamt, key_shift, 0)
694    gphit = shift(gphit, key_shift, 0)
695    IF jpj EQ 1 THEN BEGIN
696      glamt = reform(glamt, jpi, jpj, /over)
697      gphit = reform(gphit, jpi, jpj, /over)
698    ENDIF
699  ENDIF
700;
701;====================================================
702; Are we using a "regular" grid (that can be described
703; with x vector and y vector)?
704;====================================================
705;
706; to get faster, we first test the most basic cases before
707; testing the full array.
708;
709  CASE 1 OF
710    keyword_set(xyindex):key_irregular = 0b
711    jpi EQ 1 OR jpj EQ 1:key_irregular = 0b
712    n_elements(xaxis) EQ 0 AND n_elements(yaxis) EQ 0:key_irregular = 0b
713    size(reform(xaxis), /n_dimensions) EQ 1 AND size(reform(xaxis), /n_dimensions) EQ 1:key_irregular = 0b
714    n_elements(xaxis) EQ 0 AND size(reform(yaxis), /n_dimensions) EQ 1:key_irregular = 0b
715    n_elements(yaxis) EQ 0 AND size(reform(xaxis), /n_dimensions) EQ 1:key_irregular = 0b
716    array_equal(glamt[*, 0], glamt[*, jpj-1]) EQ 0:key_irregular = 1b
717    array_equal(gphit[0, *], gphit[jpi-1, *]) EQ 0:key_irregular = 1b
718    array_equal(glamt, glamt[*, 0]#replicate(1, jpj)) EQ 0:key_irregular = 1b
719    array_equal(gphit, replicate(1, jpi)#(gphit[0, *])[*]) EQ 0:key_irregular = 1b
720    ELSE:key_irregular = 0b
721  ENDCASE
722;
723;====================================================
724; def of glamf: defined as the middle of T(i,j) T(i+1,j+1)
725;====================================================
726;
727  IF jpi GT 1 THEN BEGIN
728; we must compute stepxf: x distance between T(i,j) T(i+1,j+1)
729    CASE 1 OF
730      n_elements(stepx):stepxf = stepx
731      size(stepx, /n_dimensions):stepxf = stepx#replicate(1, jpj)
732      ELSE:BEGIN
733        if (keyword_set(key_onearth) AND keyword_set(xnotsorted)) $
734          OR (keyword_set(key_periodic) AND key_irregular) then BEGIN
735          stepxf = (glamt + 720) MOD 360
736          IF jpj EQ 1 THEN stepxf = reform(stepxf, jpi, jpj, /over)
737          stepxf = shift(stepxf, -1, -1) - stepxf
738          stepxf = [ [[stepxf]], [[stepxf + 360]], [[stepxf - 360]] ]
739          stepxf = min(abs(stepxf), dimension = 3)
740          IF NOT keyword_set(key_periodic) THEN $
741            stepxf[jpi-1, *] = stepxf[jpi-2, *]
742        ENDIF ELSE BEGIN
743          stepxf = shift(glamt, -1, -1) - glamt
744          IF keyword_set(key_periodic) THEN $
745            stepxf[jpi-1, *] = 360 + stepxf[jpi-1, *] $
746          ELSE stepxf[jpi-1, *] = stepxf[jpi-2, *]
747        ENDELSE
748        IF jpj GT 1 THEN BEGIN
749          stepxf[*, jpj-1] = stepxf[*, jpj-2]
750          stepxf[jpi-1, jpj-1] = stepxf[jpi-2, jpj-2]
751        ENDIF
752      END
753    ENDCASE
754    glamf = glamt + 0.5 * stepxf
755  ENDIF ELSE glamf = glamt + 0.5
756;
757  IF keyword_set(key_periodic) AND (max(glamf)-min(glamt)) GE 360 THEN BEGIN
758    IF NOT keyword_set(glamboundary) THEN BEGIN
759      bigger = where(glamf GE min(glamt)+360)
760      glamf[bigger] = glamf[bigger]-360.
761    ENDIF ELSE glamf = glamboundary[0] > temporary(glamf) < glamboundary[1]
762  ENDIF
763;
764  IF jpj EQ 1 THEN glamf = reform(glamf, jpi, jpj, /over)
765;
766;====================================================
767; def of gphif: defined as the middle of T(i,j) T(i+1,j+1)
768;====================================================
769;
770  IF jpj GT 1 THEN BEGIN
771; we must compute stepyf: y distance between T(i,j) T(i+1,j+1)
772    CASE 1 OF
773      n_elements(stepy):stepyf = stepy
774      size(stepy, /n_dimensions):stepyf = replicate(1, jpi)#stepy
775      ELSE:BEGIN
776        stepyf = shift(gphit, -1, -1) - gphit
777        stepyf[*, jpj-1] = stepyf[*, jpj-2]
778        IF jpi GT 1 THEN BEGIN
779          if NOT keyword_set(key_periodic) THEN $
780            stepyf[jpi-1, *] = stepyf[jpi-2, *]
781          stepyf[jpi-1, jpj-1] = stepyf[jpi-2, jpj-2]
782        ENDIF
783      END
784    ENDCASE
785    gphif = gphit + 0.5 * stepyf
786  ENDIF ELSE gphif = gphit + 0.5
787  IF key_onearth THEN gphif = -90. > gphif < 90.
788;
789  IF jpj EQ 1 THEN gphif = reform(gphif, jpi, jpj, /over)
790;
791;====================================================
792; e1t: x distance between U(i-1,j) and U(i,j)
793;====================================================
794;
795; *-|-*---|---*---|
796;
797  IF jpi GT 1 THEN BEGIN
798    IF n_elements(stepx) NE 1 THEN BEGIN
799      IF keyword_set(irregular) THEN BEGIN
800; we must compute stepxu: x distance between T(i,j) T(i+1,j)
801        IF keyword_set(key_periodic) THEN BEGIN
802          stepxu = (glamt + 720) MOD 360
803          stepxu = shift(stepxu, -1, 0) - stepxu
804          stepxu = [ [[stepxu]], [[stepxu + 360]], [[stepxu - 360]] ]
805          stepxu = min(abs(stepxu), dimension = 3)
806        ENDIF ELSE BEGIN
807          stepxu = shift(glamt, -1, 0) - glamt
808          stepxu[jpi-1, *] = stepxf[jpi-2, *]
809        ENDELSE
810      ENDIF ELSE stepxu = stepxf
811      IF jpj EQ 1 THEN stepxu = reform(stepxu, jpi, jpj, /over)
812      e1t = 0.5*(stepxu+shift(stepxu, 1, 0))
813      IF NOT keyword_set(key_periodic) THEN $
814        e1t[0, *] = e1t[1, *]
815    ENDIF ELSE e1t = replicate(stepx, jpi, jpj)
816  ENDIF ELSE e1t = replicate(1b, jpi, jpj)
817;
818  IF jpj EQ 1 THEN e1t = reform(e1t, jpi, jpj, /over)
819;
820;====================================================
821; e2t: y distance between V(i,j-1) and V(i,j)
822;====================================================
823;
824  IF jpj GT 1 THEN BEGIN
825; we must compute stepyv: y distance between T(i,j) T(i,j+1)
826    IF n_elements(stepy) NE 1 THEN BEGIN
827      IF keyword_set(key_irregular) THEN BEGIN
828        stepyv = shift(gphit, 0, -1) - gphit
829        stepyv[*, jpj-1] = stepyv[*, jpj-2]
830      ENDIF ELSE stepyv = stepyf
831      e2t = 0.5*(stepyv+shift(stepyv, 0, 1))
832      e2t[*, 0] = e2t[*, 1]
833    ENDIF ELSE e2t = replicate(stepy, jpi, jpj)
834  ENDIF ELSE e2t = replicate(1b, jpi, jpj)
835;
836  IF key_onearth THEN e2t = r * !pi/180. * temporary(e2t)
837;
838  IF jpj EQ 1 THEN e2t = reform(e2t, jpi, jpj, /over)
839;
840;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
841  IF keyword_set(fullcgrid) THEN BEGIN
842;
843;====================================================
844; def of glamu: defined as the middle of T(i,j) T(i+1,j)
845;====================================================
846;
847    IF keyword_set(irregular) THEN BEGIN
848      glamu = glamt + 0.5 * stepxu
849      IF keyword_set(glamboundary) AND key_onearth THEN $
850        glamu = glamboundary[0] > temporary(glamu) < glamboundary[1]
851    ENDIF ELSE glamu = glamf
852;
853    IF jpj EQ 1 THEN glamu = reform(glamu, jpi, jpj, /over)
854;
855;====================================================
856; def of gphiu: defined as the middle of T(i,j) T(i+1,j)
857;====================================================
858;
859    IF jpi GT 1 THEN BEGIN
860 ; we must compute stepyu: y distance between T(i+1,j) T(i,j)
861      IF keyword_set(key_irregular) THEN BEGIN
862       stepyu = shift(gphit, -1, 0) - gphit
863        IF NOT keyword_set(key_periodic) THEN $
864          stepyu[jpi-1, *] = stepyu[jpi-2, *]
865        gphiu = gphit + 0.5 * stepyu
866      ENDIF ELSE gphiu = gphit
867    ENDIF ELSE gphiu = gphit
868  IF key_onearth THEN gphiu = -90. > gphiu < 90.
869;
870  IF jpj EQ 1 THEN gphiu = reform(gphiu, jpi, jpj, /over)
871;
872;====================================================
873; def of glamv: defined as the middle of T(i,j) T(i,j+1)
874;====================================================
875;
876    IF jpj GT 1 THEN BEGIN
877 ; we must compute stepxv: x distance between T(i,j) T(i,j+1)
878      IF keyword_set(irregular) THEN BEGIN
879        IF keyword_set(key_periodic) THEN BEGIN
880          stepxv = (glamt + 720) MOD 360
881          stepxv = shift(stepxv, 0, -1) - stepxv
882          stepxv = [ [[stepxv]], [[stepxv + 360]], [[stepxv - 360]] ]
883          stepxv = min(abs(stepxv), dimension = 3)
884        ENDIF ELSE stepxv = shift(glamt, 0, -1) - glamt
885        stepxv[*, jpj-1] = stepxv[*, jpj-2]
886        glamv = glamt + 0.5 * stepxv
887        IF keyword_set(glamboundary) AND key_onearth THEN $
888          glamv = glamboundary[0] > temporary(glamv) < glamboundary[1]
889      ENDIF ELSE glamv = glamt
890    ENDIF ELSE glamv = glamt
891;
892;====================================================
893; def of gphiv: defined as the middle of T(i,j) T(i,j+1)
894;====================================================
895;
896    IF keyword_set(key_irregular) THEN $
897      gphiv = gphit + 0.5 * stepyv $
898    ELSE gphiv = gphif
899    IF key_onearth THEN gphiv = -90. > gphiv < 90.
900;
901    IF jpj EQ 1 THEN gphiv = reform(gphiv, jpi, jpj, /over)
902;
903;====================================================
904; e1u: x distance between T(i,j) and T(i+1,j)
905;====================================================
906;
907    IF jpi GT 1 AND n_elements(stepx) NE 1 THEN $
908      e1u = stepxu ELSE e1u = e1t
909;
910;====================================================
911; e2u: y distance between F(i,j-1) and F(i,j)
912;====================================================
913;
914    IF keyword_set(key_irregular) THEN BEGIN
915      e2u = gphif - shift(gphif, 0, 1)
916      e2u[*, 0] = e2u[*, 1]
917      IF key_onearth THEN e2u = r * !pi/180. * temporary(e2u)
918    ENDIF ELSE e2u = e2t
919;
920    IF jpj EQ 1 THEN e2u = reform(e2u, jpi, jpj, /over)
921;
922;====================================================
923; e1v: x distance between F(i-1,j) and F(i,j)
924;====================================================
925;
926    IF keyword_set(irregular) THEN BEGIN
927      IF keyword_set(key_periodic) THEN BEGIN
928        e1v = (glamf + 720) MOD 360
929        e1v = e1v - shift(e1v, 1, 0)
930        e1v = [ [[e1v]], [[e1v + 360]], [[e1v - 360]] ]
931        e1v = min(abs(e1v), dimension = 3)
932      ENDIF ELSE BEGIN
933        e1v = glamf - shift(glamf, 1, 0)
934        e1v[0, *] = stepxf[1, *]
935      ENDELSE
936    ENDIF ELSE e1v = e1t
937;
938    IF jpj EQ 1 THEN e1v = reform(e1v, jpi, jpj, /over)
939;
940;====================================================
941; e2v: y distance between T(i,j) and T(i+1,j)
942;====================================================
943;
944    IF jpj GT 1 and n_elements(stepy) NE 1 THEN BEGIN
945      e2v = stepyv
946      IF key_onearth THEN e2v = r * !pi/180. * temporary(e2v)
947    ENDIF ELSE e2v = e2t
948;
949;====================================================
950; e1f: x distance between V(i,j) and V(i+1,j)
951;====================================================
952;
953    IF keyword_set(irregular) THEN BEGIN
954      IF keyword_set(key_periodic) THEN BEGIN
955        e1f = (glamv + 720) MOD 360
956        e1f = shift(e1f, -1, 0) - e1f
957        e1f = [ [[e1f]], [[e1f + 360]], [[e1f - 360]] ]
958        e1f = min(abs(e1f), dimension = 3)
959      ENDIF ELSE BEGIN
960        e1f = shift(glamv, -1, 0) - glamt
961        e1f[jpi-1, *] = stepxf[jpi-2, *]
962      ENDELSE
963    ENDIF ELSE e1f = e1u
964;
965    IF jpj EQ 1 THEN e1f = reform(e1f, jpi, jpj, /over)
966;
967;====================================================
968; e2f: y distance between U(i,j) and U(i,j+1)
969;====================================================
970;
971    IF keyword_set(key_irregular) THEN BEGIN
972      e2f = shift(gphiu, 0, -1) - gphiu
973      e2f[*, jpj-1] = e2f[*, jpj-2]
974      IF key_onearth THEN e2f = r * !pi/180. * temporary(e2f)
975    ENDIF ELSE e2f = e2v
976;
977    IF jpj EQ 1 THEN e2f = reform(e2f, jpi, jpj, /over)
978;
979  ENDIF
980;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
981;
982;
983;====================================================
984; e1[tuvf] from degree to meters
985;====================================================
986;
987  IF keyword_set(key_onearth)  THEN BEGIN
988    e1t = r * !pi/180. * temporary(e1t) * cos(!pi/180.*gphit)
989    IF keyword_set(fullcgrid) THEN BEGIN
990      e1u = r * !pi/180. * temporary(e1u) * cos(!pi/180.*gphiu)
991      e1v = r * !pi/180. * temporary(e1v) * cos(!pi/180.*gphiv)
992      e1f = r * !pi/180. * temporary(e1f) * cos(!pi/180.*gphif)
993    ENDIF
994  ENDIF
995;
996  IF jpj EQ 1 THEN BEGIN
997    e1t = reform(e1t, jpi, jpj, /over)
998    IF keyword_set(fullcgrid) THEN BEGIN
999      e1u = reform(e1u, jpi, jpj, /over)
1000      e1v = reform(e1v, jpi, jpj, /over)
1001      e1f = reform(e1f, jpi, jpj, /over)
1002    ENDIF
1003  ENDIF
1004;
1005;====================================================
1006; if not fullcgrid: make sure we don't use glam[uv], gphi[uv], e[12][uvf]
1007;====================================================
1008;
1009  IF NOT keyword_set(fullcgrid) THEN BEGIN
1010    glamu = !values.f_nan & glamv = !values.f_nan
1011    gphiu = !values.f_nan & gphiv = !values.f_nan
1012    e1u = !values.f_nan & e1v = !values.f_nan & e1f = !values.f_nan
1013    e2u = !values.f_nan & e2v = !values.f_nan & e2f = !values.f_nan
1014    firstxu = !values.f_nan & lastxu = !values.f_nan & nxu = !values.f_nan
1015    firstyu = !values.f_nan & lastyu = !values.f_nan & nyu = !values.f_nan
1016    firstxv = !values.f_nan & lastxv = !values.f_nan & nxv = !values.f_nan
1017    firstyv = !values.f_nan & lastyv = !values.f_nan & nyv = !values.f_nan
1018  ENDIF
1019;
1020;====================================================
1021; Z direction
1022;====================================================
1023;
1024; z axis
1025;
1026    CASE n_elements(zaxis) OF
1027      0:BEGIN
1028        gdept = 0.
1029        key_zreverse = 0
1030      END
1031      1:BEGIN
1032        gdept = zaxis
1033        key_zreverse = 0
1034      END
1035      ELSE:BEGIN
1036        gdept = zaxis[zmin:zmax]
1037        IF n_elements(zreverse) EQ 0 THEN BEGIN
1038          IF jpk GT 1 THEN BEGIN
1039            if gdept[0] GT gdept[1] then key_zreverse = 1 ELSE key_zreverse = 0
1040          ENDIF ELSE key_zreverse = 0
1041        ENDIF ELSE key_zreverse = zreverse
1042        IF keyword_set(key_zreverse) THEN gdept = reverse(gdept)
1043      END
1044    ENDCASE
1045;
1046    if n_elements(gdept) GT 1 then BEGIN
1047      stepz = shift(gdept, -1)-gdept
1048      stepz[jpk-1] = stepz[jpk-2]
1049      gdepw = 0. > (gdept-stepz/2.)
1050    ENDIF ELSE BEGIN
1051      stepz = 1.
1052      gdepw = gdept
1053    ENDELSE
1054    IF keyword_set(romsh) THEN gdepw = gdept
1055;
1056;====================================================
1057; e3[tw]:
1058;====================================================
1059;
1060    e3t = stepz
1061    IF n_elements(stepz) GT 1 THEN BEGIN
1062      e3w = 0.5*(stepz+shift(stepz, 1))
1063      e3w[0] = 0.5*e3t[0]
1064    ENDIF ELSE e3w = e3t
1065;
1066;====================================================
1067; Mask
1068;====================================================
1069;
1070; default mask eq 1
1071  if NOT keyword_set(mask) then tmask = -1 ELSE tmask = mask
1072;
1073  if tmask[0] NE -1 then BEGIN
1074    tmask = byte(temporary(tmask))
1075    IF keyword_set(romsh) THEN tmask = tmask[0:jpiglo-1, 0:jpjglo-1]
1076    IF n_elements(mask) EQ nxx*nyy AND nzz GT 1 THEN BEGIN
1077      tmask = tmask[*]#replicate(1b, nzz)
1078      tmask = reform(tmask, nxx, nyy, nzz, /overwrite)
1079    ENDIF
1080    IF nxx EQ 1 OR nyy EQ 1 OR nzz EQ 1 THEN tmask = reform(tmask, nxx, nyy, nzz, /overwrite)
1081    tmask = tmask[xmin:xmax, ymin:ymax, zmin:zmax]
1082    IF jpi EQ 1 OR jpj EQ 1 OR jpk EQ 1 THEN tmask = reform(tmask, jpi, jpj, jpk, /over)
1083    if key_shift NE 0 then tmask = shift(tmask, key_shift, 0, 0)
1084; because tmask = reverse(tmask, 2) is not working if the 3rd
1085; dimension of tmask = 1, we call reform.
1086    IF jpk EQ 1 THEN tmask = reform(tmask, /over)
1087    IF key_yreverse EQ 1 THEN tmask = reverse(tmask, 2)
1088    IF jpk EQ 1 THEN tmask = reform(tmask, jpi, jpj, jpk, /over)
1089    IF key_zreverse EQ 1 THEN tmask = reverse(tmask, 3)
1090    IF jpk EQ 1 THEN tmask = reform(tmask, jpi, jpj, jpk, /over)
1091    IF keyword_set(fullcgrid) THEN BEGIN
1092      IF keyword_set(key_periodic) THEN BEGIN
1093        msk = tmask*shift(tmask, -1, 0, 0)
1094        umaskred = msk[jpi-1, *, *]
1095      ENDIF ELSE umaskred = tmask[jpi-1, *, *]
1096      vmaskred = tmask[*, jpj-1, *]
1097    ENDIF
1098    fmaskredy = tmask[jpi-1, *, *]
1099    fmaskredx = tmask[*, jpj-1, *]
1100  ENDIF ELSE BEGIN
1101    tmask = replicate(1b, jpi, jpj, jpk)
1102    IF keyword_set(fullcgrid) THEN BEGIN
1103      umaskred  = replicate(1b, jpj, jpk)
1104      vmaskred  = replicate(1b, jpi, jpk)
1105    ENDIF
1106    fmaskredy = replicate(1b, jpj, jpk)
1107    fmaskredx = replicate(1b, jpi, jpk)
1108  ENDELSE
1109;
1110  IF jpi GT 2 AND jpj GT 2 AND NOT keyword_set(plain) $
1111     AND ixminmesh EQ 0l AND ixmaxmesh eq jpiglo-1 $
1112     AND iyminmesh EQ 0l AND iymaxmesh eq jpjglo-1 $
1113     AND total(tmask[*, 0, *]) EQ 0 AND total(tmask[*, jpj-1, *]) EQ 0 $
1114     AND total(tmask[0, *, *]) EQ 0 AND total(tmask[jpi-1, *, *]) EQ 0 THEN BEGIN
1115        xminmesh = 1
1116        xmaxmesh = -1
1117        yminmesh = 1
1118        ymaxmesh = -1
1119        computegrid, XAXIS = glamt, YAXIS = gphit, ZAXIS = zaxis $
1120                     , MASK = mask, GLAMBOUNDARY = glamboundary $
1121                     , XMINMESH = xminmesh, XMAXMESH = xmaxmesh $
1122                     , YMINMESH = yminmesh, YMAXMESH = ymaxmesh $
1123                     , ZMINMESH = zminmesh, ZMAXMESH = zmaxmesh $
1124                     , ONEARTH = onearth, PERIODIC = periodic $
1125                     , PLAIN = plain, SHIFT = shift, STRIDE = stride $
1126                     , FULLCGRID = fullcgrid, XYINDEX = xyindex $
1127                     , UBASE2TBASE = ubase2tbase, VBASE2TBASE = vbase2tbase $
1128                     , FBASE2TBASE = fbase2tbase, STRCALLING = strcalling $
1129                     , ROMSH = romsh, _extra = ex
1130        return
1131  ENDIF
1132;
1133  IF NOT keyword_set(fullcgrid) THEN BEGIN
1134    umaskred = !values.f_nan
1135    vmaskred = !values.f_nan
1136  ENDIF
1137;
1138;====================================================
1139; stride...
1140;====================================================
1141;
1142  IF total(key_stride) GT 3 THEN BEGIN
1143    IF key_shift NE 0 THEN BEGIN
1144; for explanation, see header of read_ncdf_varget.pro
1145      jpiright = key_shift
1146      jpileft = jpi - key_shift - ( (key_stride[0]-1)-((key_shift-1) MOD key_stride[0]) )
1147      jpi = ((jpiright-1)/key_stride[0]+1) + ((jpileft-1)/key_stride[0]+1)
1148    ENDIF ELSE jpi = (jpi-1)/key_stride[0]+1
1149    jpj = (jpj-1)/key_stride[1]+1
1150    jpk = (jpk-1)/key_stride[2]+1
1151;
1152    glamt = (temporary(glamt))[0:*:stride[0], 0:*:stride[1]]
1153    gphit = (temporary(gphit))[0:*:stride[0], 0:*:stride[1]]
1154    e1t = (temporary(e1t))[0:*:stride[0], 0:*:stride[1]]
1155    e2t = (temporary(e2t))[0:*:stride[0], 0:*:stride[1]]
1156    tmask = (temporary(tmask))[0:*:stride[0], 0:*:stride[1], 0:*:stride[2]]
1157    gdept = gdept[0:*:stride[2]]
1158    gdepw = gdepw[0:*:stride[2]]
1159    e3t = e3t[0:*:stride[2]]
1160    e3w = e3w[0:*:stride[2]]
1161; we must recompute glamf and gphif...
1162    IF jpi GT 1 THEN BEGIN
1163      if (keyword_set(key_onearth) AND keyword_set(xnotsorted)) $
1164        OR (keyword_set(key_periodic) AND key_irregular) then BEGIN
1165        stepxf = (glamt + 720) MOD 360
1166        stepxf = shift(stepxf, -1, -1) - stepxf
1167        stepxf = [ [[stepxf]], [[stepxf + 360]], [[stepxf - 360]] ]
1168        stepxf = min(abs(stepxf), dimension = 3)
1169        IF NOT keyword_set(key_periodic) THEN $
1170          stepxf[jpi-1, *] = stepxf[jpi-2, *]
1171      ENDIF ELSE BEGIN
1172        stepxf = shift(glamt, -1, -1) - glamt
1173        IF keyword_set(key_periodic) THEN $
1174          stepxf[jpi-1, *] = 360 + stepxf[jpi-1, *] $
1175          ELSE stepxf[jpi-1, *] = stepxf[jpi-2, *]
1176      ENDELSE
1177      IF jpj GT 1 THEN BEGIN
1178        stepxf[*, jpj-1] = stepxf[*, jpj-2]
1179        stepxf[jpi-1, jpj-1] = stepxf[jpi-2, jpj-2]
1180      ENDIF
1181      glamf = glamt + 0.5 * stepxf
1182    ENDIF ELSE glamf = glamt + 0.5
1183    IF keyword_set(key_periodic) AND (max(glamf)-min(glamt)) GE 360 THEN BEGIN
1184      IF NOT keyword_set(glamboundary) THEN BEGIN
1185        bigger = where(glamf GE min(glamt)+360)
1186        glamf[bigger] = glamf[bigger]-360.
1187      ENDIF ELSE glamf = glamboundary[0] > temporary(glamf) < glamboundary[1]
1188    ENDIF
1189    IF jpj GT 1 THEN BEGIN
1190; we must compute stepyf: y distance between T(i,j) T(i+1,j+1)
1191      stepyf = shift(gphit, -1, -1) - gphit
1192      stepyf[*, jpj-1] = stepyf[*, jpj-2]
1193      IF jpi GT 1 THEN BEGIN
1194        if NOT keyword_set(key_periodic) THEN $
1195          stepyf[jpi-1, *] = stepyf[jpi-2, *]
1196        stepyf[jpi-1, jpj-1] = stepyf[jpi-2, jpj-2]
1197      ENDIF
1198      gphif = gphit + 0.5 * stepyf
1199    ENDIF ELSE gphif = gphit + 0.5
1200;
1201    IF jpj EQ 1 THEN BEGIN
1202      glamt = reform(glamt, jpi, jpj, /over)
1203      gphit = reform(gphit, jpi, jpj, /over)
1204      glamf = reform(glamf, jpi, jpj, /over)
1205      gphif = reform(gphif, jpi, jpj, /over)
1206      e1t = reform(e1t, jpi, jpj, /over)
1207      e2t = reform(e2t, jpi, jpj, /over)
1208    ENDIF
1209;
1210    IF keyword_set(fullcgrid) THEN BEGIN
1211      glamu = (temporary(glamu))[0:*:stride[0], 0:*:stride[1]]
1212      gphiu = (temporary(gphiu))[0:*:stride[0], 0:*:stride[1]]
1213      e1u = (temporary(e1u))[0:*:stride[0], 0:*:stride[1]]
1214      e2u = (temporary(e2u))[0:*:stride[0], 0:*:stride[1]]
1215      glamv = (temporary(glamv))[0:*:stride[0], 0:*:stride[1]]
1216      gphiv = (temporary(gphiv))[0:*:stride[0], 0:*:stride[1]]
1217      e1v = (temporary(e1v))[0:*:stride[0], 0:*:stride[1]]
1218      e2v = (temporary(e2v))[0:*:stride[0], 0:*:stride[1]]
1219      e1f = (temporary(e1f))[0:*:stride[0], 0:*:stride[1]]
1220      e2f = (temporary(e2f))[0:*:stride[0], 0:*:stride[1]]
1221      umaskred = (temporary(umaskred))[0, 0:*:stride[1], 0:*:stride[2]]
1222      vmaskred = (temporary(vmaskred))[0:*:stride[0], 0, 0:*:stride[2]]
1223      fmaskredy = (temporary(fmaskredy))[0, 0:*:stride[1], 0:*:stride[2]]
1224      fmaskredx = (temporary(fmaskredx))[0:*:stride[0], 0, 0:*:stride[2]]
1225      IF jpj EQ 1 THEN BEGIN
1226        glamu = reform(glamu, jpi, jpj, /over)
1227        gphiu = reform(gphiu, jpi, jpj, /over)
1228        e1u = reform(e1u, jpi, jpj, /over)
1229        e2u = reform(e2u, jpi, jpj, /over)
1230        glamv = reform(glamv, jpi, jpj, /over)
1231        gphiv = reform(gphiv, jpi, jpj, /over)
1232        e1v = reform(e1v, jpi, jpj, /over)
1233        e2v = reform(e2v, jpi, jpj, /over)
1234        e1f = reform(e1f, jpi, jpj, /over)
1235        e2f = reform(e2f, jpi, jpj, /over)
1236      ENDIF
1237    ENDIF
1238  ENDIF
1239;
1240;====================================================
1241; apply all the grid parameters
1242;====================================================
1243;
1244  @updateold
1245  domdef
1246;
1247;====================================================
1248; Triangulation
1249;====================================================
1250;
1251  IF total(tmask) EQ jpi*jpj*jpk $
1252    AND NOT keyword_set(key_irregular) THEN triangles_list = -1 $
1253  ELSE BEGIN
1254; are we using ORCA2 ?
1255    IF jpiglo EQ 182 AND jpi EQ 180 AND jpjglo EQ 149 AND jpj EQ 148 THEN $
1256       triangles_list = triangule() ELSE triangles_list = triangule(/keep_cont)
1257  ENDELSE
1258;
1259;====================================================
1260; time axis (default definition)
1261;====================================================
1262;
1263  IF n_elements(time) EQ 0 OR n_elements(jpt) EQ 0 THEN BEGIN
1264    jpt = 1
1265    time = 0
1266  ENDIF
1267;
1268  IF NOT keyword_set(key_forgetold) THEN BEGIN
1269@updateold
1270  ENDIF
1271;====================================================
1272; grid parameters used by xxx
1273;====================================================
1274;
1275  IF NOT keyword_set(strcalling) THEN BEGIN
1276    IF n_elements(ccmeshparameters) EQ 0 THEN strcalling = 'computegrid' $
1277    ELSE strcalling = ccmeshparameters.filename
1278  ENDIF
1279  IF n_elements(glamt) GE 2 THEN BEGIN
1280    glaminfo = moment(glamt)
1281    IF finite(glaminfo[2]) EQ 0 THEN glaminfo = glaminfo[0:1]
1282    gphiinfo = moment(gphit)
1283    IF finite(gphiinfo[2]) EQ 0 THEN gphiinfo = gphiinfo[0:1]
1284  ENDIF ELSE BEGIN
1285    glaminfo = glamt
1286    gphiinfo = gphit
1287  ENDELSE
1288  IF keyword_set(romsh) THEN $
1289     romszinfos = {h:romsh[xmin:xmax, ymin:ymax], zeta:replicate(0., jpi, jpj), theta_s:-1, theta_b:-1, hc:-1} $
1290  ELSE romszinfos = {h:-1, zeta:-1, theta_s:-1, theta_b:-1, hc:-1}
1291
1292  ccmeshparameters = {filename:strcalling  $
1293          , glaminfo:float(string(glaminfo, format = '(E11.4)')) $
1294          , gphiinfo:float(string(gphiinfo, format = '(E11.4)')) $
1295          , jpiglo:jpiglo, jpjglo:jpjglo, jpkglo:jpkglo $
1296          , jpi:jpi, jpj:jpj, jpk:jpk $
1297          , ixminmesh:ixminmesh, ixmaxmesh:ixmaxmesh $
1298          , iyminmesh:iyminmesh, iymaxmesh:iymaxmesh $
1299          , izminmesh:izminmesh, izmaxmesh:izmaxmesh $
1300          , key_shift:key_shift, key_periodic:key_periodic $
1301          , key_stride:key_stride, key_gridtype:key_gridtype $
1302          , key_yreverse:key_yreverse, key_zreverse:key_zreverse $
1303          , key_partialstep:key_partialstep, key_onearth:key_onearth}
1304
1305  ccreadparameters = {funclec_name:'read_ncdf' $
1306          , jpidta:jpidta, jpjdta:jpjdta, jpkdta:jpkdta $
1307          , ixmindta:ixmindta, ixmaxdta:ixmaxdta $
1308          , iymindta:iymindta, iymaxdta:iymaxdta $
1309          , izmindta:izmindta, izmaxdta:izmaxdta}
1310;------------------------------------------------------------
1311  IF keyword_set(key_performance) EQ 1 THEN $
1312    print, 'time computegrid', systime(1)-time1
1313;------------------------------------------------------------
1314  return
1315end
Note: See TracBrowser for help on using the repository browser.