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

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

correction of some *.pro using aspell list; introduction of default idldoc syntax

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