source: trunk/SRC/Interpolation/compute_fromreg_imoms3_weigaddr.pro @ 327

Last change on this file since 327 was 327, checked in by pinsard, 16 years ago

modification of headers : mainly blanks around = sign for keywords in declaration of function and pro

  • Property svn:keywords set to Id
File size: 16.6 KB
Line 
1;+
2;
3; @file_comments
4; compute the weight and address need to interpolate data from a
5; "regular grid" to any grid using the imoms3 method
6;
7; @categories
8; Interpolation
9;
10; @param alonin {in}{required}{type=2d array}
11; longitude of the input data
12;
13; @param alatin {in}{required}{type=2d array}
14; latitude of the input data
15;
16; @param olonin {in}{required}{type=2d array}
17; longitude of the output data
18;
19; @param olat {in}{required}{type=2d array}
20; latitude of the output data
21;
22; @keyword NONORTHERNLINE {type=scalar 0 or 1}{default=0}
23; put 1 if you don't want to take into
24; account the northern line of the input data when performing the interpolation.
25;
26; @keyword NOSOUTHERNLINE {type=scalar 0 or 1}{default=0}
27; put 1 if you don't want to take into
28; account the southern line of the input data when performing the interpolation.
29;
30; @param weig {out}{type=2d array}
31; (see ADDR)
32;
33; @param addr {out}{type=2d array}
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)
38;
39; @restrictions
40;  - the input grid must be a "regular/rectangular grid", defined as a grid for
41;  which each longitude lines have the same latitude and each latitude columns
42;  have the same longitude.
43;  -  We supposed the data are located on a sphere, with a periodicity along
44;  the longitude.
45;  -  points located between the first/last 2 lines are interpolated
46;  using a imoms3 interpolation along the longitudinal direction and linear
47;  interpolation along the latitudinal direction
48;  - points located out of the southern and northern boundaries are interpolated
49;  using a imoms3 interpolation only along the longitudinal direction.
50;
51; @history
52;  November 2005: Sebastien Masson (smasson\@lodyc.jussieu.fr)
53;  March 2006: works for rectangular grids
54;
55; @version
56; $Id$
57;
58;-
59PRO compute_fromreg_imoms3_weigaddr, alonin, alatin, olonin, olat, weig, addr $
60                                   , NONORTHERNLINE=nonorthernline, $
61                                     NOSOUTHERNLINE=nosouthernline
62;
63  compile_opt idl2, strictarrsubs
64;
65  alon = alonin
66  alat = alatin
67  olon = olonin
68;
69  jpia = n_elements(alon)
70  jpja = n_elements(alat)
71;
72  jpio = (size(olon, /dimensions))[0]
73  jpjo = (size(olon, /dimensions))[1]
74;
75; alon
76  minalon = min(alon,  max = maxalon)
77  IF maxalon-minalon GE 360. THEN stop
78; alon must be monotonically increasing
79  IF array_equal(sort(alon), lindgen(jpia)) NE 1 THEN BEGIN
80    shiftx = -(where(alon EQ min(alon)))[0]
81    alon = shift(alon, shiftx)
82    IF array_equal(sort(alon), lindgen(jpia)) NE 1 THEN stop
83  ENDIF ELSE shiftx = 0
84; alon is it regularly spaced?
85  step = alon-shift(alon, 1)
86  step[0] = step[0] + 360.
87  IF total((step-step[0]) GE 1.e-6) NE 0 THEN noregx = 1
88; we extend the longitude range of alon (-> easy interpolation even
89; near minalon and maxalon)
90  toadd = 10*jpia/360+1
91  alon = [alon[jpia-toadd:jpia-1]-360., alon[*], alon[0:toadd-1]+360.]
92  jpia = jpia+2*toadd
93; alat
94  revy = alat[0] GT alat[1]
95  IF revy THEN alat = reverse(alat)
96; alat must be monotonically increasing
97  IF array_equal(sort(alat), lindgen(jpja)) NE 1 THEN stop
98; alat is it regularly spaced?
99  step = alat-shift(alat, 1)
100  step = step[1:jpja - 1L]
101  IF total((step-step[0]) GE 1.e-6) NE 0 THEN noregy = 1
102;
103  if keyword_set(nonorthernline) then BEGIN
104    jpja = jpja - 1L
105    alat = alat[0: jpja-1L]
106  ENDIF
107  if keyword_set(nosouthernline) then BEGIN
108    alat = alat[1: jpja-1L]
109    jpja = jpja - 1L
110  ENDIF
111; olon between minalon and minalon+360
112  out = where(olon LT minalon)
113  WHILE out[0] NE -1 DO BEGIN
114    olon[out] = olon[out]+360.
115    out = where(olon LT minalon)
116  ENDWHILE
117  out = where(olon GE minalon+360.)
118  WHILE out[0] NE -1 DO BEGIN
119    olon[out] = olon[out]- 360.
120    out = where(olon GE minalon+360.)
121  ENDWHILE
122; make sure that all values of olon are located within values of alon
123  IF min(olon, max = ma) LT minalon THEN stop
124  IF ma GE minalon+360. THEN stop
125;
126  xaddr = lonarr(16, jpio*jpjo)
127  yaddr = lonarr(16, jpio*jpjo)
128  weig = fltarr(16, jpio*jpjo)
129;
130  indexlon = value_locate(alon, olon)
131  IF total(alon[indexlon] GT olon) NE 0 THEN stop
132  IF total(alon[indexlon + 1L] LE olon) NE 0 THEN stop
133  IF (where(indexlon LE 1L     ))[0] NE -1 THEN stop
134  IF (where(indexlon GE jpia-3L))[0] NE -1 THEN stop
135  indexlat = value_locate(alat, olat)
136;
137; for the ocean points located below the atm line
138; jpja-2 and above the line 1
139; for those points we can always find 16 neighbors
140; imoms interpolation along longitude and latitude
141;
142  short = where(indexlat LT jpja-2L AND indexlat GE 1L)
143  ilon = indexlon[short]
144  ilat = indexlat[short]
145;
146  IF NOT keyword_set(noregy) THEN BEGIN
147    delta = alat[ilat+1L]-alat[ilat]
148    IF max(abs(delta-delta[0])) GE 1.e-6 THEN stop
149    delta = delta[0]
150;
151    d0 = (alat[ilat-1L]-olat[short])/delta
152    IF min(d0, max = ma) LE -2 THEN stop
153    IF ma GT -1 THEN stop
154    wy0 = imoms3(temporary(d0))
155    d1 = (alat[ilat   ]-olat[short])/delta
156    IF min(d1, max = ma) LE -1 THEN stop
157    IF ma GT 0 THEN stop
158    wy1 = imoms3(temporary(d1))
159    d2 = (alat[ilat+1L]-olat[short])/delta
160    IF min(d2, max = ma) LE 0 THEN stop
161    IF ma GT 1 THEN stop
162    wy2 = imoms3(temporary(d2))
163    d3 = (alat[ilat+2L]-olat[short])/delta
164    IF min(d3, max = ma) LE 1 THEN stop
165    IF ma GT 2 THEN stop
166    wy3 = imoms3(temporary(d3))
167  ENDIF ELSE BEGIN
168    nele = n_elements(short)
169    wy0 = fltarr(nele)
170    wy1 = fltarr(nele)
171    wy2 = fltarr(nele)
172    wy3 = fltarr(nele)
173    FOR i = 0L, nele-1 DO BEGIN
174      IF i MOD 10000 EQ 0 THEN print, i
175      newlat = spl_incr(alat[ilat[i]-1L:ilat[i]+2L], [-1., 0., 1., 2.], olat[short[i]])
176      IF newlat LE 0 THEN stop
177      IF newlat GT 1 THEN stop
178      wy0[i] = imoms3(newlat+1)
179      wy1[i] = imoms3(newlat)
180      wy2[i] = imoms3(1-newlat)
181      wy3[i] = imoms3(2-newlat)
182    ENDFOR
183  ENDELSE
184;
185  mi = min(wy0+wy1+wy2+wy3, max = ma)
186  IF abs(mi-1) GE 1.e-6 THEN stop
187  IF abs(ma-1) GE 1.e-6 THEN stop
188;
189  IF NOT keyword_set(noregx) THEN BEGIN
190    delta = alon[ilon]-alon[ilon-1L]
191    IF max(abs(delta-delta[0])) GE 1.e-6 THEN stop
192    delta = delta[0]
193;
194    d0 = (alon[ilon-1L]-olon[short])/delta
195    IF min(d0, max = ma) LE -2 THEN stop
196    IF ma GT -1 THEN stop
197    wx0 = imoms3(temporary(d0))
198    d1 = (alon[ilon   ]-olon[short])/delta
199    IF min(d1, max = ma) LE -1 THEN stop
200    IF ma GT 0 THEN stop
201    wx1 = imoms3(temporary(d1))
202    d2 = (alon[ilon+1L]-olon[short])/delta
203    IF min(d2, max = ma) LE 0 THEN stop
204    IF ma GT 1 THEN stop
205    wx2 = imoms3(temporary(d2))
206    d3 = (alon[ilon+2L]-olon[short])/delta
207    IF min(d3, max = ma) LE 1 THEN stop
208    IF ma GT 2 THEN stop
209    wx3 = imoms3(temporary(d3))
210  ENDIF ELSE BEGIN
211    nele = n_elements(short)
212    wx0 = fltarr(nele)
213    wx1 = fltarr(nele)
214    wx2 = fltarr(nele)
215    wx3 = fltarr(nele)
216    FOR i = 0L, nele-1 DO BEGIN
217      IF i MOD 10000 EQ 0 THEN print, i
218      newlon = spl_incr(alon[ilon[i]-1L:ilon[i]+2L], [-1., 0., 1., 2.], olon[short[i]])
219      IF newlon LE 0 THEN stop
220      IF newlon GT 1 THEN stop
221      wx0[i] = imoms3(newlon+1)
222      wx1[i] = imoms3(newlon)
223      wx2[i] = imoms3(1-newlon)
224      wx3[i] = imoms3(2-newlon)
225    ENDFOR
226  ENDELSE
227;
228  mi = min(wx0+wx1+wx2+wx3, max = ma)
229  IF abs(mi-1) GE 1.e-6 THEN stop
230  IF abs(ma-1) GE 1.e-6 THEN stop
231;
232; line 0
233  xaddr[0, short] = ilon - 1L
234  xaddr[1, short] = ilon
235  xaddr[2, short] = ilon + 1L
236  xaddr[3, short] = ilon + 2L
237  yaddr[0, short] = ilat - 1L
238  yaddr[1, short] = yaddr[0, short]
239  yaddr[2, short] = yaddr[0, short]
240  yaddr[3, short] = yaddr[0, short]
241  weig[0, short] = wx0 * wy0
242  weig[1, short] = wx1 * wy0
243  weig[2, short] = wx2 * wy0
244  weig[3, short] = wx3 * wy0
245; line 1
246  xaddr[4, short] = ilon - 1L
247  xaddr[5, short] = ilon
248  xaddr[6, short] = ilon + 1L
249  xaddr[7, short] = ilon + 2L
250  yaddr[4, short] = ilat
251  yaddr[5, short] = ilat
252  yaddr[6, short] = ilat
253  yaddr[7, short] = ilat
254  weig[4, short] = wx0 * wy1
255  weig[5, short] = wx1 * wy1
256  weig[6, short] = wx2 * wy1
257  weig[7, short] = wx3 * wy1
258; line 2
259  xaddr[8, short] = ilon - 1L
260  xaddr[9, short] = ilon
261  xaddr[10, short] = ilon + 1L
262  xaddr[11, short] = ilon + 2L
263  yaddr[8, short] = ilat + 1L
264  yaddr[9, short] = yaddr[8, short]
265  yaddr[10, short] = yaddr[8, short]
266  yaddr[11, short] = yaddr[8, short]
267  weig[8, short] = wx0 * wy2
268  weig[9, short] = wx1 * wy2
269  weig[10, short] = wx2 * wy2
270  weig[11, short] = wx3 * wy2
271; line 3
272  xaddr[12, short] = ilon - 1L
273  xaddr[13, short] = ilon
274  xaddr[14, short] = ilon + 1L
275  xaddr[15, short] = ilon + 2L
276  yaddr[12, short] = ilat + 2L
277  yaddr[13, short] = yaddr[12, short]
278  yaddr[14, short] = yaddr[12, short]
279  yaddr[15, short] = yaddr[12, short]
280  weig[12, short] = wx0 * wy3
281  weig[13, short] = wx1 * wy3
282  weig[14, short] = wx2 * wy3
283  weig[15, short] = wx3 * wy3
284;
285  mi = min(total(weig[*, short], 1, /double), max = ma)
286  IF abs(mi-1) GE 1.e-6 THEN stop
287  IF abs(ma-1) GE 1.e-6 THEN stop
288;
289; for the ocean points located between the atm lines
290; jpja-2 and jpja-1 or between the atm lines 0 and 1
291; linear interpolation between line 1 and line 2
292;
293  short = where(indexlat EQ jpja-2L OR indexlat EQ 0)
294  IF short[0] NE -1 THEN BEGIN
295    ilon = indexlon[short]
296    ilat = indexlat[short]
297;
298    delta = alat[ilat+1L]-alat[ilat]
299    IF NOT keyword_set(noregy) THEN BEGIN
300      IF max(abs(delta-delta[0])) GE 1.e-6 THEN stop
301      delta = delta[0]
302    ENDIF
303;
304    d1 = (alat[ilat   ]-olat[short])/delta
305    IF min(d1, max = ma) LE -1 THEN stop
306    IF ma GT 0 THEN stop
307    wy1 = 1.+ temporary(d1)
308    d2 = (alat[ilat+1L]-olat[short])/delta
309    IF min(d2, max = ma) LE 0 THEN stop
310    IF ma GT 1 THEN stop
311    wy2 = 1.- temporary(d2)
312;
313    mi = min(wy1+wy2, max = ma)
314    IF abs(mi-1) GE 1.e-6 THEN stop
315    IF abs(ma-1) GE 1.e-6 THEN stop
316; but imoms3 along the longitude
317    IF NOT keyword_set(noregx) THEN BEGIN
318      delta = alon[ilon]-alon[ilon-1L]
319      IF max(abs(delta-delta[0])) GE 1.e-6 THEN stop
320      delta = delta[0]
321;
322      d0 = (alon[ilon-1L]-olon[short])/delta
323      IF min(d0, max = ma) LE -2 THEN stop
324      IF ma GT -1 THEN stop
325      wx0 = imoms3(temporary(d0))
326      d1 = (alon[ilon   ]-olon[short])/delta
327      IF min(d1, max = ma) LE -1 THEN stop
328      IF ma GT 0 THEN stop
329      wx1 = imoms3(temporary(d1))
330      d2 = (alon[ilon+1L]-olon[short])/delta
331      IF min(d2, max = ma) LE 0 THEN stop
332      IF ma GT 1 THEN stop
333      wx2 = imoms3(temporary(d2))
334      d3 = (alon[ilon+2L]-olon[short])/delta
335      IF min(d3, max = ma) LE 1 THEN stop
336      IF ma GT 2 THEN stop
337      wx3 = imoms3(temporary(d3))
338    ENDIF ELSE BEGIN
339      nele = n_elements(short)
340      wx0 = fltarr(nele)
341      wx1 = fltarr(nele)
342      wx2 = fltarr(nele)
343      wx3 = fltarr(nele)
344      FOR i = 0L, nele-1 DO BEGIN
345        IF i MOD 10000 EQ 0 THEN print, i
346        newlon = spl_incr(alon[ilon[i]-1L:ilon[i]+2L], [-1., 0., 1., 2.], olon[short[i]])
347        IF newlon LE 0 THEN stop
348        IF newlon GT 1 THEN stop
349        wx0[i] = imoms3(newlon+1)
350        wx1[i] = imoms3(newlon)
351        wx2[i] = imoms3(1-newlon)
352        wx3[i] = imoms3(2-newlon)
353      ENDFOR
354    ENDELSE
355;
356    mi = min(wx0+wx1+wx2+wx3, max = ma)
357    IF abs(mi-1) GE 1.e-6 THEN stop
358    IF abs(ma-1) GE 1.e-6 THEN stop
359; line 1
360    xaddr[0, short] = ilon - 1L
361    xaddr[1, short] = ilon
362    xaddr[2, short] = ilon + 1L
363    xaddr[3, short] = ilon + 2L
364    yaddr[0, short] = ilat
365    yaddr[1, short] = ilat
366    yaddr[2, short] = ilat
367    yaddr[3, short] = ilat
368    weig[0, short] = wx0 * wy1
369    weig[1, short] = wx1 * wy1
370    weig[2, short] = wx2 * wy1
371    weig[3, short] = wx3 * wy1
372; line 2
373    xaddr[4, short] = ilon - 1L
374    xaddr[5, short] = ilon
375    xaddr[6, short] = ilon + 1L
376    xaddr[7, short] = ilon + 2L
377    yaddr[4, short] = ilat + 1L
378    yaddr[5, short] = yaddr[4, short]
379    yaddr[6, short] = yaddr[4, short]
380    yaddr[7, short] = yaddr[4, short]
381    weig[4, short] = wx0 * wy2
382    weig[5, short] = wx1 * wy2
383    weig[6, short] = wx2 * wy2
384    weig[7, short] = wx3 * wy2
385;
386    mi = min(total(weig[*, short], 1, /double), max = ma)
387    IF abs(mi-1) GE 1.e-6 THEN stop
388    IF abs(ma-1) GE 1.e-6 THEN stop
389;
390  ENDIF
391;
392; for the ocean points located below the line 0
393; Interpolation only along the longitude
394;
395  short = where(indexlat EQ -1)
396  IF short[0] NE -1 THEN BEGIN
397    ilon = indexlon[short]
398;
399    IF NOT keyword_set(noregx) THEN BEGIN
400      delta = alon[ilon]-alon[ilon-1L]
401      IF max(abs(delta-delta[0])) GE 1.e-6 THEN stop
402      delta = delta[0]
403;
404      d0 = (alon[ilon-1L]-olon[short])/delta
405      IF min(d0, max = ma) LE -2 THEN stop
406      IF ma GT -1 THEN stop
407      wx0 = imoms3(temporary(d0))
408      d1 = (alon[ilon   ]-olon[short])/delta
409      IF min(d1, max = ma) LE -1 THEN stop
410      IF ma GT 0 THEN stop
411      wx1 = imoms3(temporary(d1))
412      d2 = (alon[ilon+1L]-olon[short])/delta
413      IF min(d2, max = ma) LE 0 THEN stop
414      IF ma GT 1 THEN stop
415      wx2 = imoms3(temporary(d2))
416      d3 = (alon[ilon+2L]-olon[short])/delta
417      IF min(d3, max = ma) LE 1 THEN stop
418      IF ma GT 2 THEN stop
419      wx3 = imoms3(temporary(d3))
420    ENDIF ELSE BEGIN
421      nele = n_elements(short)
422      wx0 = fltarr(nele)
423      wx1 = fltarr(nele)
424      wx2 = fltarr(nele)
425      wx3 = fltarr(nele)
426      FOR i = 0L, nele-1 DO BEGIN
427        IF i MOD 10000 EQ 0 THEN print, i
428        newlon = spl_incr(alon[ilon[i]-1L:ilon[i]+2L], [-1., 0., 1., 2.], olon[short[i]])
429        IF newlon LE 0 THEN stop
430        IF newlon GT 1 THEN stop
431        wx0[i] = imoms3(newlon+1)
432        wx1[i] = imoms3(newlon)
433        wx2[i] = imoms3(1-newlon)
434        wx3[i] = imoms3(2-newlon)
435      ENDFOR
436    ENDELSE
437;
438    mi = min(wx0+wx1+wx2+wx3, max = ma)
439    IF abs(mi-1) GE 1.e-6 THEN stop
440    IF abs(ma-1) GE 1.e-6 THEN stop
441; line 1
442    xaddr[0, short] = ilon - 1L
443    xaddr[1, short] = ilon
444    xaddr[2, short] = ilon + 1L
445    xaddr[3, short] = ilon + 2L
446    yaddr[0:3, short] = 0
447    weig[0, short] = wx0
448    weig[1, short] = wx1
449    weig[2, short] = wx2
450    weig[3, short] = wx3
451;
452    mi = min(total(weig[*, short], 1, /double), max = ma)
453    IF abs(mi-1) GE 1.e-6 THEN stop
454    IF abs(ma-1) GE 1.e-6 THEN stop
455;
456  ENDIF
457;
458; for the ocean points located above jpia-1
459; Interpolation only along the longitude
460;
461  short = where(indexlat EQ jpja-1L)
462  IF short[0] NE -1 THEN BEGIN
463    ilon = indexlon[short]
464;
465    IF NOT keyword_set(noregx) THEN BEGIN
466      delta = alon[ilon]-alon[ilon-1L]
467      IF max(abs(delta-delta[0])) GE 1.e-6 THEN stop
468      delta = delta[0]
469;
470      d0 = (alon[ilon-1L]-olon[short])/delta
471      IF min(d0, max = ma) LE -2 THEN stop
472      IF ma GT -1 THEN stop
473      wx0 = imoms3(temporary(d0))
474      d1 = (alon[ilon   ]-olon[short])/delta
475      IF min(d1, max = ma) LE -1 THEN stop
476      IF ma GT 0 THEN stop
477      wx1 = imoms3(temporary(d1))
478      d2 = (alon[ilon+1L]-olon[short])/delta
479      IF min(d2, max = ma) LE 0 THEN stop
480      IF ma GT 1 THEN stop
481      wx2 = imoms3(temporary(d2))
482      d3 = (alon[ilon+2L]-olon[short])/delta
483      IF min(d3, max = ma) LE 1 THEN stop
484      IF ma GT 2 THEN stop
485      wx3 = imoms3(temporary(d3))
486    ENDIF ELSE BEGIN
487      nele = n_elements(short)
488      wx0 = fltarr(nele)
489      wx1 = fltarr(nele)
490      wx2 = fltarr(nele)
491      wx3 = fltarr(nele)
492      FOR i = 0L, nele-1 DO BEGIN
493        IF i MOD 10000 EQ 0 THEN print, i
494        newlon = spl_incr(alon[ilon[i]-1L:ilon[i]+2L], [-1., 0., 1., 2.], olon[short[i]])
495        IF newlon LE 0 THEN stop
496        IF newlon GT 1 THEN stop
497        wx0[i] = imoms3(newlon+1)
498        wx1[i] = imoms3(newlon)
499        wx2[i] = imoms3(1-newlon)
500        wx3[i] = imoms3(2-newlon)
501      ENDFOR
502    ENDELSE
503;
504    mi = min(wx0+wx1+wx2+wx3, max = ma)
505    IF abs(mi-1) GE 1.e-6 THEN stop
506    IF abs(ma-1) GE 1.e-6 THEN stop
507; line 1
508    xaddr[0, short] = ilon-1L
509    xaddr[1, short] = ilon
510    xaddr[2, short] = ilon+1L
511    xaddr[3, short] = ilon+2L
512    yaddr[0:3, short] = jpja-1L
513    weig[0, short] = wx0
514    weig[1, short] = wx1
515    weig[2, short] = wx2
516    weig[3, short] = wx3
517;
518    mi = min(total(weig[*, short], 1, /double), max = ma)
519    IF abs(mi-1) GE 1.e-6 THEN stop
520    IF abs(ma-1) GE 1.e-6 THEN stop
521;
522  ENDIF
523;
524; Come back to the original index of atm grid without longitudinal overlap.
525;
526;
527  xaddr = temporary(xaddr) - toadd
528  jpia = jpia - 2*toadd
529; make sure all values are ge 0
530  xaddr = temporary(xaddr) + jpia
531; range the values between 0 and jpia-1
532  xaddr = temporary(xaddr) mod jpia
533;
534; take into account shiftx if needed
535  IF shiftx NE 0 THEN xaddr = (temporary(xaddr) - shiftx) MOD jpia
536; take into account nosouthernline and nonorthernline
537  if keyword_set(nosouthernline) then BEGIN
538    yaddr = temporary(yaddr) + 1L
539    jpja = jpja + 1L
540  ENDIF
541  if keyword_set(nonorthernline) then jpja = jpja + 1L
542; take into account revy if needed
543  IF revy EQ 1 THEN yaddr = jpja - 1L - temporary(yaddr)
544;                        ;
545  addr = temporary(yaddr)*jpia+temporary(xaddr)
546;
547  RETURN
548END
Note: See TracBrowser for help on using the repository browser.