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

Last change on this file since 327 was 327, checked in by pinsard, 16 years ago

modification of headers : mainly blanks around = sign for keywords in declaration of function and pro

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