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

Last change on this file since 114 was 114, checked in by smasson, 18 years ago

new compilation options (compile_opt idl2, strictarrsubs) in each routine

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