Skip to content

Commit b7b2449

Browse files
committed
FEAT: allow above and below grid interpolation
1 parent 21c934d commit b7b2449

File tree

1 file changed

+155
-28
lines changed

1 file changed

+155
-28
lines changed

src/solver_grid_interpolation.cpp

Lines changed: 155 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,8 @@ void Grid::get_cubesphere_grid_range(struct cubesphere_range &cr) const {
184184
// Almost the copy of interp_sphere_linear_helper
185185
// --------------------------------------------------------------------------
186186

187-
void Grid::set_interp_coef_sphere(const sphere_range &sr,
187+
struct interp_coef_t Grid::get_interp_coef_sphere(
188+
const sphere_range &sr,
188189
const precision_t lon_in,
189190
const precision_t lat_in,
190191
const precision_t alt_in) {
@@ -200,13 +201,15 @@ void Grid::set_interp_coef_sphere(const sphere_range &sr,
200201

201202
// Determine whether the point is inside this grid
202203
// Treat north pole specially because latitude is inclusive for both -cPI/2 and cPI/2
204+
// Dpn't check for altitude here!
203205
if (lon_in < sr.lon_min || lon_in >= sr.lon_max || lat_in < sr.lat_min
204-
|| lat_in > sr.lat_max || (lat_in == sr.lat_max && sr.lat_max != cPI / 2)
205-
|| alt_in < sr.alt_min || alt_in > sr.alt_max) {
206-
interp_coefs.push_back(coef);
207-
return;
206+
|| lat_in > sr.lat_max || (lat_in == sr.lat_max && sr.lat_max != cPI / 2)) {
207+
return coef;
208208
}
209209

210+
// This point is in the grid!
211+
coef.in_grid = true;
212+
210213
// ASSUMPTION: LONGITUDE AND LATITUDE ARE LINEARLY SPACED, nGCs >= 1
211214
// For the cell containing it, directly calculate its x and y index
212215
// Find its z index using binary search
@@ -228,21 +231,35 @@ void Grid::set_interp_coef_sphere(const sphere_range &sr,
228231
// The altitude may not be linearly spaced, so use binary search to find
229232
// the first element smaller than or equal to the altitude of the give point
230233
// Implemented in search_altitude
231-
coef.iAlt = search_altitude(alt_in);
232-
coef.rAlt = (alt_in - geoAlt_scgc(0, 0, coef.iAlt))
233-
/ (geoAlt_scgc(0, 0, coef.iAlt + 1) - geoAlt_scgc(0, 0, coef.iAlt));
234234

235-
// Put the coefficient into the vector
236-
coef.in_grid = true;
237-
interp_coefs.push_back(coef);
235+
if (alt_in < sr.alt_min) {
236+
coef.iAlt = nGCs;
237+
coef.rAlt = alt_in - sr.alt_min;
238+
coef.below_grid = true;
239+
coef.above_grid = false;
240+
} else {
241+
if (alt_in > sr.alt_max) {
242+
coef.iAlt = nAlts - nGCs;
243+
coef.rAlt = alt_in - sr.alt_max;
244+
coef.below_grid = false;
245+
coef.above_grid = true;
246+
} else {
247+
coef.iAlt = search_altitude(alt_in);
248+
coef.rAlt = (alt_in - geoAlt_scgc(0, 0, coef.iAlt))
249+
/ (geoAlt_scgc(0, 0, coef.iAlt + 1) - geoAlt_scgc(0, 0, coef.iAlt));
250+
coef.below_grid = false;
251+
coef.above_grid = false;
252+
}
253+
}
254+
return coef;
238255
}
239256

240257
// --------------------------------------------------------------------------
241258
// Set interpolation coefficients helper function for cubesphere grid
242259
// Almost the copy of interp_cubesphere_linear_helper
243260
// --------------------------------------------------------------------------
244261

245-
void Grid::set_interp_coef_cubesphere(const cubesphere_range &cr,
262+
struct interp_coef_t Grid::get_interp_coef_cubesphere(const cubesphere_range &cr,
246263
const precision_t lon_in,
247264
const precision_t lat_in,
248265
const precision_t alt_in) {
@@ -259,8 +276,7 @@ void Grid::set_interp_coef_cubesphere(const cubesphere_range &cr,
259276

260277
// Determine whether the projection point is on the surface of the grid
261278
if (surface_in != cr.surface_number) {
262-
interp_coefs.push_back(coef);
263-
return;
279+
return coef;
264280
}
265281

266282
// Calculate the theoretical fractional row index and column index
@@ -280,12 +296,13 @@ void Grid::set_interp_coef_cubesphere(const cubesphere_range &cr,
280296
|| row_frac_index > row_index_max || (row_frac_index == row_index_max &&
281297
cr.row_max_exclusive)
282298
|| col_frac_index > col_index_max || (col_frac_index == col_index_max &&
283-
cr.col_max_exclusive)
284-
|| alt_in < cr.alt_min || alt_in > cr.alt_max) {
285-
interp_coefs.push_back(coef);
286-
return;
299+
cr.col_max_exclusive)) {
300+
return coef;
287301
}
288302

303+
// This point is in the grid!
304+
coef.in_grid = true;
305+
289306
// Get the real integer index and the interpolation coefficient
290307
uint64_t row_index, col_index, alt_index;
291308
precision_t rRow, rCol, rAlt;
@@ -303,13 +320,27 @@ void Grid::set_interp_coef_cubesphere(const cubesphere_range &cr,
303320
coef.rCol = col_frac_index - coef.iCol;
304321
coef.iCol += nGCs - 1;
305322
// Use binary search to find the index for altitude
306-
coef.iAlt = search_altitude(alt_in);
307-
coef.rAlt = (alt_in - geoAlt_scgc(0, 0, coef.iAlt))
308-
/ (geoAlt_scgc(0, 0, coef.iAlt + 1) - geoAlt_scgc(0, 0, coef.iAlt));
309323

310-
// Put the coefficient into the vector
311-
coef.in_grid = true;
312-
interp_coefs.push_back(coef);
324+
if (alt_in < cr.alt_min) {
325+
coef.iAlt = nGCs;
326+
coef.rAlt = 0.0;
327+
coef.below_grid = true;
328+
coef.above_grid = false;
329+
} else {
330+
if (alt_in > cr.alt_max) {
331+
coef.iAlt = nAlts - nGCs;
332+
coef.rAlt = 0.0;
333+
coef.below_grid = false;
334+
coef.above_grid = true;
335+
} else {
336+
coef.iAlt = search_altitude(alt_in);
337+
coef.rAlt = (alt_in - geoAlt_scgc(0, 0, coef.iAlt))
338+
/ (geoAlt_scgc(0, 0, coef.iAlt + 1) - geoAlt_scgc(0, 0, coef.iAlt));
339+
coef.below_grid = false;
340+
coef.above_grid = false;
341+
}
342+
}
343+
return coef;
313344
}
314345

315346
// --------------------------------------------------------------------------
@@ -319,6 +350,8 @@ void Grid::set_interp_coef_cubesphere(const cubesphere_range &cr,
319350
bool Grid::set_interpolation_coefs(const std::vector<precision_t> &Lons,
320351
const std::vector<precision_t> &Lats,
321352
const std::vector<precision_t> &Alts) {
353+
354+
struct interp_coef_t coef;
322355
// If this is not a geo grid, return false
323356
if (!IsGeoGrid)
324357
return false;
@@ -337,21 +370,84 @@ bool Grid::set_interpolation_coefs(const std::vector<precision_t> &Lons,
337370
get_cubesphere_grid_range(cr);
338371

339372
// Calculate the index and coefficients for each point
340-
for (size_t i = 0; i < Lons.size(); ++i)
341-
set_interp_coef_cubesphere(cr, Lons[i], Lats[i], Alts[i]);
373+
for (size_t i = 0; i < Lons.size(); ++i) {
374+
coef = get_interp_coef_cubesphere(cr, Lons[i], Lats[i], Alts[i]);
375+
interp_coefs.push_back(coef);
376+
}
377+
342378
} else {
343379
// Calculate the range of the grid
344380
struct sphere_range sr;
345381
get_sphere_grid_range(sr);
346382

347383
// Calculate the index and coefficients for each point
348-
for (size_t i = 0; i < Lons.size(); ++i)
349-
set_interp_coef_sphere(sr, Lons[i], Lats[i], Alts[i]);
384+
for (size_t i = 0; i < Lons.size(); ++i) {
385+
coef = get_interp_coef_sphere(sr, Lons[i], Lats[i], Alts[i]);
386+
interp_coefs.push_back(coef);
387+
}
350388
}
351389

352390
return true;
353391
}
354392

393+
// --------------------------------------------------------------------------
394+
// Set the interpolation coefficients
395+
// (v2 - return a list of interpolation coefficients)
396+
// --------------------------------------------------------------------------
397+
398+
std::vector<struct interp_coef_t> Grid::get_interpolation_coefs(
399+
const std::vector<precision_t> &Lons,
400+
const std::vector<precision_t> &Lats,
401+
const std::vector<precision_t> &Alts) {
402+
403+
int64_t nPts = Lons.size(), iPt;
404+
std::vector<struct interp_coef_t> listOfCoefs;
405+
struct interp_coef_t singleCoef;
406+
bool isBad = false;
407+
408+
// If this is not a geo grid, return false
409+
if (!IsGeoGrid)
410+
isBad = true;
411+
412+
// If the size of Lons, Lats and Alts are not the same, return false
413+
if (Lons.size() != Lats.size() || Lats.size() != Alts.size())
414+
isBad = true;
415+
416+
if (isBad) {
417+
for (iPt = 0; iPt < nPts; ++iPt) {
418+
// Put the coefficient into the vector
419+
singleCoef.in_grid = false;
420+
listOfCoefs.push_back(singleCoef);
421+
}
422+
return listOfCoefs;
423+
}
424+
425+
// Handle according to whether it is cubesphere or not
426+
if (IsCubeSphereGrid) {
427+
// Calculate the range of the grid
428+
struct cubesphere_range cr;
429+
get_cubesphere_grid_range(cr);
430+
431+
// Calculate the index and coefficients for each point
432+
for (iPt = 0; iPt < nPts; ++iPt) {
433+
singleCoef = get_interp_coef_cubesphere(cr, Lons[iPt], Lats[iPt], Alts[iPt]);
434+
listOfCoefs.push_back(singleCoef);
435+
}
436+
} else {
437+
// Calculate the range of the grid
438+
struct sphere_range sr;
439+
get_sphere_grid_range(sr);
440+
441+
// Calculate the index and coefficients for each point
442+
for (iPt = 0; iPt < nPts; ++iPt) {
443+
singleCoef = get_interp_coef_sphere(sr, Lons[iPt], Lats[iPt], Alts[iPt]);
444+
listOfCoefs.push_back(singleCoef);
445+
}
446+
}
447+
448+
return listOfCoefs;
449+
}
450+
355451
// --------------------------------------------------------------------------
356452
// Do the interpolation based on the coefficients stored in interp_coefs
357453
// --------------------------------------------------------------------------
@@ -381,3 +477,34 @@ std::vector<precision_t> Grid::get_interpolation_values(
381477

382478
return ans;
383479
}
480+
481+
// --------------------------------------------------------------------------
482+
// Do the interpolation based on the coefficients passed in
483+
// --------------------------------------------------------------------------
484+
485+
std::vector<precision_t> Grid::get_interpolation_values(arma_cube data,
486+
std::vector<struct interp_coef_t> coefArray ) {
487+
std::vector<precision_t> ans;
488+
489+
// If the size of data is not the same as the size of grid, return an empty vector
490+
if (data.n_rows != nLons || data.n_cols != nLats || data.n_slices != nAlts)
491+
return ans;
492+
493+
for (auto &it : coefArray) {
494+
// Do interpolation if in_grid = true. Push cNinf otherwise
495+
if (it.in_grid) {
496+
ans.push_back(interpolate_unit_cube(
497+
data.subcube(it.iRow, it.iCol, it.iAlt, unit_cube_size),
498+
it.rRow,
499+
it.rCol,
500+
it.rAlt
501+
));
502+
// Add std::cout if needed here
503+
// std::cout << "iProc = " << iProc << " interpolates the point successfully\n";
504+
} else
505+
ans.push_back(cNinf);
506+
}
507+
508+
return ans;
509+
}
510+

0 commit comments

Comments
 (0)