source: trunk/SRC/Interpolation/compute_fromreg_bilinear_weigaddr.pro @ 118

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

add $ in Calendar, Grid, Interpolation, Obsolete and Postscript *.pro files, add svn:keywords Id to all these files, some improvements in header

  • Property svn:executable set to *
  • Property svn:keywords set to Id
File size: 7.5 KB
Line 
1;+
2; @file_comments compute the weight and address needed to interpolate data from a
3;          "regular grid" to any grid using the bilinear method
4;   
5; @categories interpolation
6;
7; @param alonin {in}{required} longitudeof the input data
8; @param alatin  {in}{required} latitude of the input data
9; @param olonin {in}{required} longitude of the output data
10; @param olat  {in}{required} latitude of the output data
11;
12; @keyword     /NONORTHERNLINE activate if you don't whant to take into
13;          account the northen line of the input data when perfoming the
14; @keyword     /NOSOUTHERNLINE activate if you don't whant to take into
15;          account the southern line of the input data when perfoming the
16;          interpolation.
17;
18; @param weig {out}
19; @param addr {out}
20; 2D arrays, weig and addr are the weight and addresses used to
21; perform the interpolation:
22;  dataout = total(weig*datain[addr], 1)
23;  dataout = reform(dataout, jpio, jpjo, /over)
24;
25; @restrictions
26;  -  the input grid must be a "regular grid", defined as a grid for which each
27;     lontitudes lines have the same latitude and each latitudes columns have the
28;     same longitude.
29;  -  We supposed the data are located on a sphere, with a periodicity along
30;     the longitude.
31;  -  points located out of the southern and northern boundaries are interpolated
32;     using a linear interpolation only along the longitudinal direction.
33;
34; @history
35;  November 2005: Sebastien Masson (smasson\@lodyc.jussieu.fr)
36;
37; @version $Id$
38;
39;-
40;
41;----------------------------------------------------------
42;----------------------------------------------------------
43;
44PRO compute_fromreg_bilinear_weigaddr, alonin, alatin, olonin, olat, weig, addr $
45  , NONORTHERNLINE = nonorthernline, NOSOUTHERNLINE = nosouthernline
46;
47  compile_opt idl2, strictarrsubs
48;
49  alon = alonin
50  alat = alatin
51  olon = olonin
52;
53  jpia = n_elements(alon)
54  jpja = n_elements(alat)
55;
56  jpio = (size(olon, /dimensions))[0]
57  jpjo = (size(olon, /dimensions))[1]
58;
59; alon
60  minalon = min(alon,  max = maxalon)
61  IF maxalon-minalon GE 360. THEN stop
62; alon must be monotonically increasing
63  IF array_equal(sort(alon), lindgen(jpia)) NE 1 THEN BEGIN
64    shiftx = -(where(alon EQ min(alon)))[0]
65    alon = shift(alon, shiftx)
66    IF array_equal(sort(alon), lindgen(jpia)) NE 1 THEN stop
67  ENDIF ELSE shiftx = 0
68; for longitude periodic bondary condition we add the fist
69; column on the right side of the array and
70  alon = [alon, alon[0]+360.]
71  jpia = jpia+1L
72; alat
73  revy = alat[0] GT alat[1]
74  IF revy THEN alat = reverse(alat)
75; alat must be monotonically increasing
76  IF array_equal(sort(alat), lindgen(jpja)) NE 1 THEN stop
77;
78  if keyword_set(nonorthernline) then BEGIN
79    jpja = jpja - 1L
80    alat = alat[0: jpja-1L]
81  ENDIF
82  if keyword_set(nosouthernline) then BEGIN
83    alat = alat[1: jpja-1L]
84    jpja = jpja - 1L
85  ENDIF
86; olon between minalon et minalon+360
87  out = where(olon LT minalon)
88  WHILE out[0] NE -1 DO BEGIN
89    olon[out] = olon[out]+360.
90    out = where(olon LT minalon)
91  ENDWHILE
92  out = where(olon GE minalon+360.)
93  WHILE out[0] NE -1 DO BEGIN
94    olon[out] = olon[out]- 360.
95    out = where(olon GE minalon+360.)
96  ENDWHILE
97; make sure that all values of olon are located within values of alon
98  IF min(olon, max = ma) LT minalon THEN stop
99  IF ma GE minalon+360. THEN stop
100;
101; we want to do biliear interpolation => for each ocean point, we must
102; find in which atm cell it is located.
103; if the ocean point is out of the atm grid, we use closest neighbor
104; interpolation
105;
106; for each T point of oce grid, we find in which armospheric cell it is
107; located.
108; As the atmospheric grid is regular, we can use inrecgrid instead
109; of inquad.
110  pos = inrecgrid(olon, olat, alon[0:jpia-2L], alat[0:jpja-2L] $
111                  , checkout = [alon[jpia-1L], alat[jpja-1L]], /output2d)
112; checks...
113; for longitude, each ocean points must be located in atm cell.
114  IF (where(pos[0, *] EQ -1))[0] NE -1 THEN stop
115; no ocean point should be located westward of the left bondary of the
116; atm cell in which it is supposed to be located
117  IF total(olon LT alon[pos[0, *]]) NE 0 THEN stop
118; no ocean point should be located eastward of the right bondary of the
119; atm cell in which it is supposed to be located
120  IF total(olon GT alon[pos[0, *]+1]) NE 0 THEN stop
121;
122; we use bilinear interpolation
123;
124; we change the coordinates of each ocean points to fit into a
125; rectangle defined by:
126;
127;  y2 *------------*
128;     |            |
129;     |            |
130;     |            |
131;  y1 *------------*
132;     x1          x2
133;
134;    X = (x-x1)/(x2-x1)
135;    Y = (y-y1)/(y2-y1)
136;
137  indx = pos[0, *]
138  indy = (temporary(pos))[1, *]
139; points located out of the atmospheric grid...(too much northward or southward)
140  bad = where(indy EQ -1)
141  indy = 0 > indy
142;
143  IF max(indx) GT jpia-2 THEN stop ; checks...
144  IF max(indy) GT jpja-2 THEN stop ; checks...
145; x coordinates of the atm cell
146  x1 = alon[indx]
147  x2 = alon[indx+1]
148; new x coordinates of the ocean points in each cell
149  divi = temporary(x2)-x1
150  glamnew = (olon-x1)/temporary(divi)
151  x1 = -1 ; free memory
152  olon = -1 ; free memory
153; y coordinates of the atm cell
154  y1 = alat[indy]
155  y2 = alat[indy+1]             ;
156; new y coordinates of the ocean points in each cell
157  divi = temporary(y2)-y1
158  zero = where(divi EQ 0)
159  IF zero[0] NE -1 THEN divi[zero] = 1.
160  gphinew = (olat-y1)/temporary(divi)
161  y1 = -1 ; free memory
162; checks...
163  IF min(glamnew) LT 0 THEN stop
164  IF max(glamnew) GT 1 THEN stop
165;
166; weight and address array used for bilinear interpolation.
167  xaddr = lonarr(4, jpio*jpjo)
168  xaddr[0, *] = indx 
169  xaddr[1, *] = indx + 1L
170  xaddr[2, *] = indx + 1L
171  xaddr[3, *] = indx 
172;
173  yaddr = lonarr(4, jpio*jpjo)
174  yaddr[0, *] = indy
175  yaddr[1, *] = indy
176  yaddr[2, *] = indy + 1L
177  yaddr[3, *] = indy + 1L
178; compute the weight for the bilinear interpolation.
179  weig = fltarr(4, jpio*jpjo)
180  weig[0, *] = (1.-glamnew) * (1.-gphinew)
181  weig[1, *] =     glamnew  * (1.-gphinew)
182  weig[2, *] =     glamnew  *     gphinew
183  weig[3, *] = (1.-glamnew) *     gphinew
184; free memory
185  gphinew = -1
186  IF bad[0] EQ -1 THEN glamnew = -1 ELSE glamnew = (temporary(glamnew))[bad]
187; we work now on the "bad" points
188; linear interpolation only along the longitudinal direction
189  IF bad[0] NE -1 THEN BEGIN
190    ybad = olat[bad]
191; the ocean points that are not located into an atm cell should be
192; located northward of the northern boudary of the atm grid
193;      or southward of the southern boudary of the atm grid
194    IF total(ybad GE min(alat) AND ybad LE max(alat)) GE 1 THEN stop
195;
196    weig[0, bad] = (1.-glamnew)
197    weig[1, bad] = temporary(glamnew)
198    weig[2, bad] = 0.
199    weig[3, bad] = 0.
200    south = where(ybad LT alat[0])
201    IF south[0] NE -1 THEN yaddr[*, bad[temporary(south)]] = 0L
202    north = where(ybad GT alat[jpja-1])
203    IF north[0] NE -1 THEN yaddr[*, bad[temporary(north)]] = 0L
204    ybad = -1 & bad = -1 ; free memory
205  ENDIF
206; check totalweight = 1
207  totalweig = abs(1-total(weig, 1))
208  IF (where(temporary(totalweig) GE 1.e-5))[0] NE -1 THEN stop
209;
210; come back to the original atm grid without longitudinal overlap.
211;
212  jpia = jpia-1L
213  xaddr = temporary(xaddr) MOD jpia
214; take into account shiftx if needed
215  IF shiftx NE 0 THEN xaddr = (temporary(xaddr) - shiftx) MOD jpia
216; take into account nosouthernline and nonorthernline
217  if keyword_set(nosouthernline) then BEGIN
218    yaddr = temporary(yaddr) + 1L
219    jpja = jpja + 1L
220  ENDIF
221  if keyword_set(nonorthernline) then jpja = jpja + 1L
222; take into account revy if needed
223  IF revy EQ 1 THEN yaddr = jpja - 1L - temporary(yaddr)
224;                         ;
225  addr = temporary(yaddr)*jpia + temporary(xaddr)
226;
227  return
228end
229
Note: See TracBrowser for help on using the repository browser.