source: trunk/SRC/Interpolation/compute_fromirr_bilinear_weigaddr.pro @ 163

Last change on this file since 163 was 157, checked in by navarro, 18 years ago

header improvements + xxx doc

  • Property svn:keywords set to Id
File size: 9.0 KB
Line 
1;+
2; @file_comments
3; compute the weight and address needed to interpolate data from
4; an "irregular 2D grid" (defined as a grid made of quadrilateral cells)
5; to any grid using the bilinear method
6;
7; @categories
8; Interpolation
9;
10; @param olonin {in}{required}
11; longitude of the input data
12;
13; @param olat {in}{required}
14; latitude of the input data
15;
16; @param omsk {in}{required}
17; land/sea mask of the input data
18;
19; @param alonin {in}{required}
20; longitude of the output data
21;
22; @param alat {in}{required}
23; latitude of the output data
24;
25; @param amsk {in}{required}
26; land/sea mask of the output data
27;
28; @param weig {out}
29; @param addr {out}
30; 2D arrays, weig and addr are the weight and addresses used to
31; perform the interpolation:
32;  dataout = total(weig*datain[addr], 1)
33;  dataout = reform(dataout, jpia, jpja, /over)
34;
35; @restrictions
36;  -  the input grid must be an "irregular 2D grid", defined as a grid made
37;  of quadrilateral cells which corners positions are defined with olonin and olat
38;  -  We supposed the data are located on a sphere, with a periodicity along
39;  the longitude
40;  -  to perform the bilinear interpolation within quadrilateral cells, we
41;  first morph the cell into a square cell and then compute the bilinear
42;  interpolation.
43;  -  if some corners of the cell are land points, their weight is set to 0
44;  and the weight is redistributed on the remaining "water" corners
45;  -  points located out of the southern and northern boundaries or in cells
46;  containing only land points are set the the same value as their closest neighbor l
47;
48; @history
49;  June 2006: Sebastien Masson (smasson\@lodyc.jussieu.fr)
50;
51; @version $Id$
52;
53;-
54;
55PRO compute_fromirr_bilinear_weigaddr, olonin, olat, omsk, alonin, alat, amsk, weig, addr
56;
57  compile_opt idl2, strictarrsubs
58;
59  jpia = (size(alonin, /dimensions))[0]
60  jpja = (size(alonin, /dimensions))[1]
61;
62  jpio = (size(olonin, /dimensions))[0]
63  jpjo = (size(olonin, /dimensions))[1]
64;
65; longitude, between 0 and 360
66  alon = alonin MOD 360
67  out = where(alon LT 0)
68  IF out[0] NE -1 THEN alon[out] = alon[out]+360
69  olon = olonin MOD 360
70  out = where(olon LT 0)
71  IF out[0] NE -1 THEN olon[out] = olon[out]+360
72;
73; we work only on the water points
74  owater = where(omsk EQ 1)
75  nowater = n_elements(owater)
76  awater = where(amsk EQ 1)
77  nawater = n_elements(awater)
78;
79; define all cells that have corners located at olon, olat
80; we define the cell with the address of all corners
81;
82;            3        2
83;             +------+
84;             |      |
85;             |      |
86;             |      |
87;             +------+
88;            0        1
89;
90  alladdr = lindgen(jpio, jpjo-1)
91  celladdr = lonarr(4, jpio*(jpjo-1))
92  celladdr[0, *] = alladdr
93  celladdr[1, *] = shift(alladdr, -1)
94  celladdr[2, *] = shift(alladdr + jpio, -1)
95  celladdr[3, *] = alladdr + jpio
96;
97; list the cells that have at least 1 ocean point as corner
98  good = where(total(omsk[celladdr], 1) GT 0)
99; keep only those cells
100  celladdr = celladdr[*, temporary(good)]
101;
102  xcell = olon[celladdr]
103  minxcell = min(xcell, dimension = 1, max = maxxcell)
104  ycell = olat[celladdr]
105  minycell = min(ycell, dimension = 1, max = maxycell)
106; foraddr: address of the ocean water cell associated to each atmosphere water point
107  foraddr = lonarr(nawater)
108; forweight: x/y position of the atmosphere water point in the ocean water cell
109  forweight = dblarr(nawater, 2)
110;
111; Loop on all the water point of the atmosphere
112; We look for which ocean water cell contains the atmosphere water point
113;
114  delta = max([(360./jpio), (180./jpjo)])* 4.
115  FOR n = 0L, nawater-1 DO BEGIN
116; control print
117    IF (n MOD 5000) EQ 0 THEN print, n
118; longitude and latitude of the atmosphere water point
119    xx = alon[awater[n]]
120    yy = alat[awater[n]]
121; 1) we reduce the number of ocean cells for which we will try to know if
122; xx,yy is inside.
123    CASE 1 OF
124; if we are near the norh pole
125      yy GE (90-delta):BEGIN
126        lat1 = 90-2*delta
127        good = where(maxycell GE lat1)
128        onsphere = 1
129      END
130; if we are near the longitude periodicity area
131      xx LE delta OR xx GE (360-delta):BEGIN
132        lat1 = yy-delta
133        lat2 = yy+delta
134        good = where((minxcell LE 2*delta OR maxxcell GE (360-2*delta)) AND maxycell GE lat1 AND minycell LE lat2)
135        onsphere = 1
136      END
137; other cases
138      ELSE:BEGIN
139        lon1 = xx-delta
140        lon2 = xx+delta
141        lat1 = yy-delta
142        lat2 = yy+delta
143        good = where(maxxcell GE lon1 AND minxcell LE lon2 AND maxycell GE lat1 AND minycell le lat2)
144; ORCA cases : orca grid is irregular only northward of 40N
145        CASE 1 OF
146          jpio EQ 92   AND (jpjo EQ 76   OR jpjo EQ 75   OR jpjo EQ 74  ):onsphere = yy GT 40
147          jpio EQ 180  AND (jpjo EQ 149  OR jpjo EQ 148  OR jpjo EQ 147 ):onsphere = yy GT 40
148          jpio EQ 720  AND (jpjo EQ 522  OR jpjo EQ 521  OR jpjo EQ 520 ):onsphere = yy GT 40
149          jpio EQ 1440 AND (jpjo EQ 1021 OR jpjo EQ 1020 OR jpjo EQ 1019):onsphere = yy GT 40
150          ELSE:onsphere = 1
151        ENDCASE
152      END
153    ENDCASE
154; we found a short list of possible ocean water cells containing the atmosphere water point
155    IF good[0] NE -1 THEN BEGIN
156; in which cell is located the atmosphere water point?
157; Warning! inquad use clockwise quadrilateral definition
158      ind = inquad(xx, yy $
159                   , xcell[0, good], ycell[0, good] $
160                   , xcell[3, good], ycell[3, good] $
161                   , xcell[2, good], ycell[2, good] $
162                   , xcell[1, good], ycell[1, good] $
163                   , onsphere = onsphere, newcoord = newcoord, /noprint)
164; keep only the first cell (if the atmospheric point was located in several ocean cells)
165      ind = ind[0]
166; we found one ocean water cell containing the atmosphere water point
167      IF ind NE -1 THEN BEGIN
168        ind = good[ind]
169; we keep its address
170        foraddr[n] = ind
171; now, we morph the quadrilateral ocean cell into the reference square (0 -> 1)
172; in addition we get the corrdinates of the atmospheric point in this new morphed square
173        IF onsphere THEN BEGIN
174; Warning! quadrilateral2square use anticlockwise quadrilateral definition
175          xy = quadrilateral2square(newcoord[0, 0], newcoord[1, 0] $
176                                    , newcoord[0, 3], newcoord[1, 3] $
177                                    , newcoord[0, 2], newcoord[1, 2] $
178                                    , newcoord[0, 1], newcoord[1, 1] $
179                                    , newcoord[0, 4], newcoord[1, 4])
180        ENDIF ELSE BEGIN
181          xy = quadrilateral2square(xcell[0, ind], ycell[0, ind] $
182                                    , xcell[1, ind], ycell[1, ind] $
183                                    , xcell[2, ind], ycell[2, ind] $
184                                    , xcell[3, ind], ycell[3, ind], xx, yy)
185        ENDELSE
186; take care of rounding errors...
187        zero = where(abs(xy) LT 1e-4)
188        IF zero[0] NE -1 THEN xy[zero] = 0
189        one = where(abs(1-xy) LT 1e-4)
190        IF one[0] NE -1 THEN xy[one] = 1
191; some (useless) checks...
192        IF  xy[0] LT 0 OR xy[0] GT 1 THEN stop
193        IF  xy[0] LT 0 OR xy[0] GT 1 THEN stop
194; keep the new coordinates
195        forweight[n, 0] = xy[0]
196        forweight[n, 1] = xy[1]
197      ENDIF ELSE foraddr[n] = -1
198    ENDIF ELSE foraddr[n] = -1
199  ENDFOR
200; do we have some water atmospheric points that are not located in an water oceanic cell?
201  bad = where(foraddr EQ -1)
202  IF bad[0] NE -1 THEN BEGIN
203; yes?
204; we look for neighbor water atmospheric point located in water oceanic cell
205    badaddr = awater[bad]
206    good = where(foraddr NE -1)
207; list the atmospheric points located in water oceanic cell
208    goodaddr = awater[good]
209; there longitude and latitude
210    goodlon = alon[goodaddr]
211    goodlat = alat[goodaddr]
212; for all the bad points, look for a neighbor
213    neig = lonarr(n_elements(bad))
214    FOR i = 0, n_elements(bad)-1 DO BEGIN
215      neig[i] = (neighbor(alon[badaddr[i]], alat[badaddr[i]], goodlon, goodlat, /sphere))[0]
216    ENDFOR
217; get the address regarding foraddr
218    neig = good[neig]
219; associate each bad point with its neighbor (get its address and weight)
220    foraddr[bad] = foraddr[neig]
221    forweight[bad, *] = forweight[neig, *]
222  endif
223; transform the address of the ocean cell into the address of its 4 corners
224  newaaddr = celladdr[*, temporary(foraddr)]
225; now we compute the weight to give at each corner
226  newaweig = dblarr(4, nawater)
227  a = reform(forweight[*, 0], 1, nawater)
228  b = reform(forweight[*, 1], 1, nawater)
229  forweight =  -1 ; free memory
230  newaweig = [(1-a)*(1-b), (1-b)*a, a*b, (1-a)*b]
231  a = -1 &  b = -1 ; free memory
232; mask the weight to suppress the corner located on land
233  newaweig = newaweig*((omsk)[newaaddr])
234  totalweig = total(newaweig, 1)
235; for cell with some land corner,
236; we have to redistribute the weight on the reaining water corners
237; weights normalization
238  totalweig = total(newaweig, 1)
239  newaweig = newaweig/(replicate(1., 4)#totalweig)
240  totalweig = total(newaweig, 1)
241
242; weights
243  weig = dblarr(4, jpia*jpja)
244  weig[*, awater] = temporary(newaweig)
245; address
246  addr = dblarr(4, jpia*jpja)
247  addr[*, awater] = temporary(newaaddr)
248;
249  RETURN
250END
Note: See TracBrowser for help on using the repository browser.