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

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

some improvements and corrections in some .pro file according to
aspell and idldoc log file

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