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

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

some improvements and corrections in some .pro file according to
aspell and idldoc log file

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