source: trunk/SRC/Interpolation/compute_fromreg_imoms3_weigaddr.pro

Last change on this file was 501, checked in by smasson, 8 years ago

set of bugfixes...

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