source: trunk/Interpolation/compute_fromreg_bilinear_weigaddr.pro @ 59

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

upgrade of Interpolation according to cerbere.lodyc.jussieu.fr: /usr/home/smasson/SAXO_RD/

  • Property svn:executable set to *
File size: 7.5 KB
Line 
1;+
2; NAME: compute_fromreg_bilinear_weigaddr
3;
4; PURPOSE: compute the weight and address neede to interpolate data from a
5;          "regular grid" to any grid using the bilinear method
6;   
7; CATEGORY:interpolation
8;
9; CALLING SEQUENCE:
10;     compute_fromreg_bilinear_weigaddr, alon, alat, olon, olat, weig, addr
11;
12; INPUTS:
13;     lonin and latin: longitude/latitude of the input data
14;     lonout and latout: longitude/latitude of the output data
15;
16; KEYWORD PARAMETERS:
17;
18;     /NONORTHERNLINE and /NOSOUTHERNLINE: activate if you don't whant to take into
19;          account the northen/southern line of the input data when perfoming the
20;          interpolation.
21;
22; OUTPUTS:
23;     weig, addr: 2D arrays, weig and addr are the weight and addresses used to
24;     perform the interpolation:
25;          dataout = total(weig*datain[addr], 1)
26;          dataout = reform(dataout, jpio, jpjo, /over)
27;
28; COMMON BLOCKS: none
29;
30; SIDE EFFECTS: ?
31;
32; RESTRICTIONS:
33;  -  the input grid must be a "regular grid", defined as a grid for which each
34;     lontitudes lines have the same latitude and each latitudes columns have the
35;     same longitude.
36;  -  We supposed the data are located on a sphere, with a periodicity along
37;     the longitude.
38;  -  points located out of the southern and northern boundaries are interpolated
39;     using a linear interpolation only along the longitudinal direction.
40;
41; EXAMPLE:
42;
43; MODIFICATION HISTORY:
44;  November 2005: Sebastien Masson (smasson@lodyc.jussieu.fr)
45;
46;-
47;
48;----------------------------------------------------------
49;----------------------------------------------------------
50;
51PRO compute_fromreg_bilinear_weigaddr, alonin, alatin, olonin, olat, weig, addr $
52  , NONORTHERNLINE = nonorthernline, NOSOUTHERNLINE = nosouthernline
53;
54  compile_opt strictarr, 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 bondary 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 bondary 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 bondary 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 boudary of the atm grid
200;      or southward of the southern boudary 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.