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

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

improvements of Interpolation/*.pro header

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