[59] | 1 | ;+ |
---|
| 2 | ; NAME: compute_fromreg_bilinear_weigaddr |
---|
| 3 | ; |
---|
| 4 | ; PURPOSE: compute the weight and address neede to interpolate data from a |
---|
| 5 | ; "regular grid" to any grid using the bilinear method |
---|
| 6 | ; |
---|
| 7 | ; CATEGORY:interpolation |
---|
| 8 | ; |
---|
| 9 | ; CALLING SEQUENCE: |
---|
| 10 | ; compute_fromreg_bilinear_weigaddr, alon, alat, olon, olat, weig, addr |
---|
| 11 | ; |
---|
| 12 | ; INPUTS: |
---|
| 13 | ; lonin and latin: longitude/latitude of the input data |
---|
| 14 | ; lonout and latout: longitude/latitude of the output data |
---|
| 15 | ; |
---|
| 16 | ; KEYWORD PARAMETERS: |
---|
| 17 | ; |
---|
| 18 | ; /NONORTHERNLINE and /NOSOUTHERNLINE: activate if you don't whant to take into |
---|
| 19 | ; account the northen/southern line of the input data when perfoming the |
---|
| 20 | ; interpolation. |
---|
| 21 | ; |
---|
| 22 | ; OUTPUTS: |
---|
| 23 | ; weig, addr: 2D arrays, weig and addr are the weight and addresses used to |
---|
| 24 | ; perform the interpolation: |
---|
| 25 | ; dataout = total(weig*datain[addr], 1) |
---|
| 26 | ; dataout = reform(dataout, jpio, jpjo, /over) |
---|
| 27 | ; |
---|
| 28 | ; COMMON BLOCKS: none |
---|
| 29 | ; |
---|
| 30 | ; SIDE EFFECTS: ? |
---|
| 31 | ; |
---|
| 32 | ; RESTRICTIONS: |
---|
| 33 | ; - the input grid must be a "regular grid", defined as a grid for which each |
---|
| 34 | ; lontitudes lines have the same latitude and each latitudes columns have the |
---|
| 35 | ; same longitude. |
---|
| 36 | ; - We supposed the data are located on a sphere, with a periodicity along |
---|
| 37 | ; the longitude. |
---|
| 38 | ; - points located out of the southern and northern boundaries are interpolated |
---|
| 39 | ; using a linear interpolation only along the longitudinal direction. |
---|
| 40 | ; |
---|
| 41 | ; EXAMPLE: |
---|
| 42 | ; |
---|
| 43 | ; MODIFICATION HISTORY: |
---|
| 44 | ; November 2005: Sebastien Masson (smasson@lodyc.jussieu.fr) |
---|
| 45 | ; |
---|
| 46 | ;- |
---|
| 47 | ; |
---|
| 48 | ;---------------------------------------------------------- |
---|
| 49 | ;---------------------------------------------------------- |
---|
| 50 | ; |
---|
| 51 | PRO compute_fromreg_bilinear_weigaddr, alonin, alatin, olonin, olat, weig, addr $ |
---|
| 52 | , NONORTHERNLINE = nonorthernline, NOSOUTHERNLINE = nosouthernline |
---|
| 53 | ; |
---|
| 54 | compile_opt strictarr, strictarrsubs |
---|
| 55 | ; |
---|
| 56 | alon = alonin |
---|
| 57 | alat = alatin |
---|
| 58 | olon = olonin |
---|
| 59 | ; |
---|
| 60 | jpia = n_elements(alon) |
---|
| 61 | jpja = n_elements(alat) |
---|
| 62 | ; |
---|
| 63 | jpio = (size(olon, /dimensions))[0] |
---|
| 64 | jpjo = (size(olon, /dimensions))[1] |
---|
| 65 | ; |
---|
| 66 | ; alon |
---|
| 67 | minalon = min(alon, max = maxalon) |
---|
| 68 | IF maxalon-minalon GE 360. THEN stop |
---|
| 69 | ; alon must be monotonically increasing |
---|
| 70 | IF array_equal(sort(alon), lindgen(jpia)) NE 1 THEN BEGIN |
---|
| 71 | shiftx = -(where(alon EQ min(alon)))[0] |
---|
| 72 | alon = shift(alon, shiftx) |
---|
| 73 | IF array_equal(sort(alon), lindgen(jpia)) NE 1 THEN stop |
---|
| 74 | ENDIF ELSE shiftx = 0 |
---|
| 75 | ; for longitude periodic bondary condition we add the fist |
---|
| 76 | ; column on the right side of the array and |
---|
| 77 | alon = [alon, alon[0]+360.] |
---|
| 78 | jpia = jpia+1L |
---|
| 79 | ; alat |
---|
| 80 | revy = alat[0] GT alat[1] |
---|
| 81 | IF revy THEN alat = reverse(alat) |
---|
| 82 | ; alat must be monotonically increasing |
---|
| 83 | IF array_equal(sort(alat), lindgen(jpja)) NE 1 THEN stop |
---|
| 84 | ; |
---|
| 85 | if keyword_set(nonorthernline) then BEGIN |
---|
| 86 | jpja = jpja - 1L |
---|
| 87 | alat = alat[0: jpja-1L] |
---|
| 88 | ENDIF |
---|
| 89 | if keyword_set(nosouthernline) then BEGIN |
---|
| 90 | alat = alat[1: jpja-1L] |
---|
| 91 | jpja = jpja - 1L |
---|
| 92 | ENDIF |
---|
| 93 | ; olon between minalon et minalon+360 |
---|
| 94 | out = where(olon LT minalon) |
---|
| 95 | WHILE out[0] NE -1 DO BEGIN |
---|
| 96 | olon[out] = olon[out]+360. |
---|
| 97 | out = where(olon LT minalon) |
---|
| 98 | ENDWHILE |
---|
| 99 | out = where(olon GE minalon+360.) |
---|
| 100 | WHILE out[0] NE -1 DO BEGIN |
---|
| 101 | olon[out] = olon[out]- 360. |
---|
| 102 | out = where(olon GE minalon+360.) |
---|
| 103 | ENDWHILE |
---|
| 104 | ; make sure that all values of olon are located within values of alon |
---|
| 105 | IF min(olon, max = ma) LT minalon THEN stop |
---|
| 106 | IF ma GE minalon+360. THEN stop |
---|
| 107 | ; |
---|
| 108 | ; we want to do biliear interpolation => for each ocean point, we must |
---|
| 109 | ; find in which atm cell it is located. |
---|
| 110 | ; if the ocean point is out of the atm grid, we use closest neighbor |
---|
| 111 | ; interpolation |
---|
| 112 | ; |
---|
| 113 | ; for each T point of oce grid, we find in which armospheric cell it is |
---|
| 114 | ; located. |
---|
| 115 | ; As the atmospheric grid is regular, we can use inrecgrid instead |
---|
| 116 | ; of inquad. |
---|
| 117 | pos = inrecgrid(olon, olat, alon[0:jpia-2L], alat[0:jpja-2L] $ |
---|
| 118 | , checkout = [alon[jpia-1L], alat[jpja-1L]], /output2d) |
---|
| 119 | ; checks... |
---|
| 120 | ; for longitude, each ocean points must be located in atm cell. |
---|
| 121 | IF (where(pos[0, *] EQ -1))[0] NE -1 THEN stop |
---|
| 122 | ; no ocean point should be located westward of the left bondary of the |
---|
| 123 | ; atm cell in which it is supposed to be located |
---|
| 124 | IF total(olon LT alon[pos[0, *]]) NE 0 THEN stop |
---|
| 125 | ; no ocean point should be located eastward of the right bondary of the |
---|
| 126 | ; atm cell in which it is supposed to be located |
---|
| 127 | IF total(olon GT alon[pos[0, *]+1]) NE 0 THEN stop |
---|
| 128 | ; |
---|
| 129 | ; we use bilinear interpolation |
---|
| 130 | ; |
---|
| 131 | ; we change the coordinates of each ocean points to fit into a |
---|
| 132 | ; rectangle defined by: |
---|
| 133 | ; |
---|
| 134 | ; y2 *------------* |
---|
| 135 | ; | | |
---|
| 136 | ; | | |
---|
| 137 | ; | | |
---|
| 138 | ; y1 *------------* |
---|
| 139 | ; x1 x2 |
---|
| 140 | ; |
---|
| 141 | ; X = (x-x1)/(x2-x1) |
---|
| 142 | ; Y = (y-y1)/(y2-y1) |
---|
| 143 | ; |
---|
| 144 | indx = pos[0, *] |
---|
| 145 | indy = (temporary(pos))[1, *] |
---|
| 146 | ; points located out of the atmospheric grid...(too much northward or southward) |
---|
| 147 | bad = where(indy EQ -1) |
---|
| 148 | indy = 0 > indy |
---|
| 149 | ; |
---|
| 150 | IF max(indx) GT jpia-2 THEN stop ; checks... |
---|
| 151 | IF max(indy) GT jpja-2 THEN stop ; checks... |
---|
| 152 | ; x coordinates of the atm cell |
---|
| 153 | x1 = alon[indx] |
---|
| 154 | x2 = alon[indx+1] |
---|
| 155 | ; new x coordinates of the ocean points in each cell |
---|
| 156 | divi = temporary(x2)-x1 |
---|
| 157 | glamnew = (olon-x1)/temporary(divi) |
---|
| 158 | x1 = -1 ; free memory |
---|
| 159 | olon = -1 ; free memory |
---|
| 160 | ; y coordinates of the atm cell |
---|
| 161 | y1 = alat[indy] |
---|
| 162 | y2 = alat[indy+1] ; |
---|
| 163 | ; new y coordinates of the ocean points in each cell |
---|
| 164 | divi = temporary(y2)-y1 |
---|
| 165 | zero = where(divi EQ 0) |
---|
| 166 | IF zero[0] NE -1 THEN divi[zero] = 1. |
---|
| 167 | gphinew = (olat-y1)/temporary(divi) |
---|
| 168 | y1 = -1 ; free memory |
---|
| 169 | ; checks... |
---|
| 170 | IF min(glamnew) LT 0 THEN stop |
---|
| 171 | IF max(glamnew) GT 1 THEN stop |
---|
| 172 | ; |
---|
| 173 | ; weight and address array used for bilinear interpolation. |
---|
| 174 | xaddr = lonarr(4, jpio*jpjo) |
---|
| 175 | xaddr[0, *] = indx |
---|
| 176 | xaddr[1, *] = indx + 1L |
---|
| 177 | xaddr[2, *] = indx + 1L |
---|
| 178 | xaddr[3, *] = indx |
---|
| 179 | ; |
---|
| 180 | yaddr = lonarr(4, jpio*jpjo) |
---|
| 181 | yaddr[0, *] = indy |
---|
| 182 | yaddr[1, *] = indy |
---|
| 183 | yaddr[2, *] = indy + 1L |
---|
| 184 | yaddr[3, *] = indy + 1L |
---|
| 185 | ; compute the weight for the bilinear interpolation. |
---|
| 186 | weig = fltarr(4, jpio*jpjo) |
---|
| 187 | weig[0, *] = (1.-glamnew) * (1.-gphinew) |
---|
| 188 | weig[1, *] = glamnew * (1.-gphinew) |
---|
| 189 | weig[2, *] = glamnew * gphinew |
---|
| 190 | weig[3, *] = (1.-glamnew) * gphinew |
---|
| 191 | ; free memory |
---|
| 192 | gphinew = -1 |
---|
| 193 | IF bad[0] EQ -1 THEN glamnew = -1 ELSE glamnew = (temporary(glamnew))[bad] |
---|
| 194 | ; we work now on the "bad" points |
---|
| 195 | ; linear interpolation only along the longitudinal direction |
---|
| 196 | IF bad[0] NE -1 THEN BEGIN |
---|
| 197 | ybad = olat[bad] |
---|
| 198 | ; the ocean points that are not located into an atm cell should be |
---|
| 199 | ; located northward of the northern boudary of the atm grid |
---|
| 200 | ; or southward of the southern boudary of the atm grid |
---|
| 201 | IF total(ybad GE min(alat) AND ybad LE max(alat)) GE 1 THEN stop |
---|
| 202 | ; |
---|
| 203 | weig[0, bad] = (1.-glamnew) |
---|
| 204 | weig[1, bad] = temporary(glamnew) |
---|
| 205 | weig[2, bad] = 0. |
---|
| 206 | weig[3, bad] = 0. |
---|
| 207 | south = where(ybad LT alat[0]) |
---|
| 208 | IF south[0] NE -1 THEN yaddr[*, bad[temporary(south)]] = 0L |
---|
| 209 | north = where(ybad GT alat[jpja-1]) |
---|
| 210 | IF north[0] NE -1 THEN yaddr[*, bad[temporary(north)]] = 0L |
---|
| 211 | ybad = -1 & bad = -1 ; free memory |
---|
| 212 | ENDIF |
---|
| 213 | ; check totalweight = 1 |
---|
| 214 | totalweig = abs(1-total(weig, 1)) |
---|
| 215 | IF (where(temporary(totalweig) GE 1.e-5))[0] NE -1 THEN stop |
---|
| 216 | ; |
---|
| 217 | ; come back to the original atm grid without longitudinal overlap. |
---|
| 218 | ; |
---|
| 219 | jpia = jpia-1L |
---|
| 220 | xaddr = temporary(xaddr) MOD jpia |
---|
| 221 | ; take into account shiftx if needed |
---|
| 222 | IF shiftx NE 0 THEN xaddr = (temporary(xaddr) - shiftx) MOD jpia |
---|
| 223 | ; take into account nosouthernline and nonorthernline |
---|
| 224 | if keyword_set(nosouthernline) then BEGIN |
---|
| 225 | yaddr = temporary(yaddr) + 1L |
---|
| 226 | jpja = jpja + 1L |
---|
| 227 | ENDIF |
---|
| 228 | if keyword_set(nonorthernline) then jpja = jpja + 1L |
---|
| 229 | ; take into account revy if needed |
---|
| 230 | IF revy EQ 1 THEN yaddr = jpja - 1L - temporary(yaddr) |
---|
| 231 | ; ; |
---|
| 232 | addr = temporary(yaddr)*jpia + temporary(xaddr) |
---|
| 233 | ; |
---|
| 234 | return |
---|
| 235 | end |
---|
| 236 | |
---|