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

Last change on this file since 240 was 238, checked in by pinsard, 17 years ago

improvements/corrections of some *.pro headers

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