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

Last change on this file since 202 was 202, checked in by smasson, 17 years ago

add extrapsmooth + light bugfix in compute_fromirr_bilinear_weigaddr + improve some headers

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