Nektar++
LibUtilities/BasicUtils/Interpolator.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: Interpolator.cpp
4 //
5 // For more information, please see: http://www.nektar.info/
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2016 Kilian Lackhove
10 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
11 // Department of Aeronautics, Imperial College London (UK), and Scientific
12 // Computing and Imaging Institute, University of Utah (USA).
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description: Interpolator
33 //
34 ////////////////////////////////////////////////////////////////////////////////
35 
36 #include <boost/geometry.hpp>
38 
39 using namespace std;
40 
41 namespace bg = boost::geometry;
42 namespace bgi = boost::geometry::index;
43 
44 namespace Nektar
45 {
46 namespace LibUtilities
47 {
48 
49 /**
50  * @brief Compute interpolation weights without doing any interpolation
51  *
52  * @param ptsInField input field
53  * @param ptsOutField output field
54  * @param reuseTree if an r-tree has been constructed already, reuse it
55  * (e.g. for repeated calls over the same input points).
56  *
57  * In and output fields must have the same dimension. The most suitable
58  * algorithm is chosen automatically if it wasnt set explicitly.
59  */
60 void Interpolator::CalcWeights(const LibUtilities::PtsFieldSharedPtr ptsInField,
62  bool reuseTree)
63 {
64  ASSERTL0(ptsInField->GetDim() <= m_dim, "too many dimesions in inField");
65  ASSERTL0(ptsOutField->GetDim() <= m_dim, "too many dimesions in outField");
66 
67  m_ptsInField = ptsInField;
68  m_ptsOutField = ptsOutField;
69 
70  size_t nOutPts = m_ptsOutField->GetNpoints();
71  int lastProg = 0;
72 
73  // set a default method
74  if (m_method == eNoMethod)
75  {
76  if (m_ptsInField->GetDim() == 1 || m_coordId >= 0)
77  {
78  m_method = eQuadratic;
79  }
80  else
81  {
82  m_method = eShepard;
83  }
84  }
85 
86  if ((!m_rtree || !reuseTree) && m_method != eQuadratic)
87  {
88  SetupTree();
89  }
90 
91  switch (m_method)
92  {
93  case eNearestNeighbour:
94  {
95  m_weights = Array<TwoD, NekDouble>(nOutPts, 1, 0.0);
96  m_neighInds = Array<TwoD, unsigned int>(nOutPts, 1, (unsigned int) 0);
97 
98  for (size_t i = 0; i < nOutPts; ++i)
99  {
100  Array<OneD, NekDouble> tmp(m_dim, 0.0);
101  for (size_t j = 0; j < m_ptsOutField->GetDim(); ++j)
102  {
103  tmp[j] = m_ptsOutField->GetPointVal(j, i);
104  }
105  PtsPoint searchPt(i, tmp, 1E30);
106 
107  CalcW_NNeighbour(searchPt);
108 
109  int progress = int(100 * i / nOutPts);
110  if (m_progressCallback && progress > lastProg)
111  {
112  m_progressCallback(i, nOutPts);
113  lastProg = progress;
114  }
115  }
116 
117  break;
118  }
119 
120  case eQuadratic:
121  {
122  ASSERTL0(m_ptsInField->GetDim() == 1 || m_coordId >= 0,
123  "not implemented");
124 
125  m_weights = Array<TwoD, NekDouble>(nOutPts, 3, 0.0);
126  m_neighInds = Array<TwoD, unsigned int>(nOutPts, 3, (unsigned int) 0);
127 
128  for (size_t i = 0; i < nOutPts; ++i)
129  {
130  Array<OneD, NekDouble> tmp(m_dim, 0.0);
131  for (size_t j = 0; j < m_ptsOutField->GetDim(); ++j)
132  {
133  tmp[j] = m_ptsOutField->GetPointVal(j, i);
134  }
135  PtsPoint searchPt(i, tmp, 1E30);
136 
137  if (m_ptsInField->GetNpoints() <= 2)
138  {
139  CalcW_Linear(searchPt, m_coordId);
140  }
141  else
142  {
143  CalcW_Quadratic(searchPt, m_coordId);
144  }
145 
146  int progress = int(100 * i / nOutPts);
147  if (m_progressCallback && progress > lastProg)
148  {
149  m_progressCallback(i, nOutPts);
150  lastProg = progress;
151  }
152  }
153 
154  break;
155  }
156 
157  case eShepard:
158  {
159  int numPts = m_ptsInField->GetDim();
160  numPts = 1 << numPts; // 2 ^ numPts
161  numPts = min(numPts, int(m_ptsInField->GetNpoints() / 2));
162 
163  m_weights = Array<TwoD, NekDouble>(nOutPts, numPts, 0.0);
164  m_neighInds = Array<TwoD, unsigned int>(nOutPts, numPts, (unsigned int) 0);
165 
166  for (size_t i = 0; i < nOutPts; ++i)
167  {
168  Array<OneD, NekDouble> tmp(m_dim, 0.0);
169  for (size_t j = 0; j < m_ptsOutField->GetDim(); ++j)
170  {
171  tmp[j] = m_ptsOutField->GetPointVal(j, i);
172  }
173  PtsPoint searchPt(i, tmp, 1E30);
174 
175  CalcW_Shepard(searchPt, numPts);
176 
177  int progress = int(100 * i / nOutPts);
178  if (m_progressCallback && progress > lastProg)
179  {
180  m_progressCallback(i, nOutPts);
181  lastProg = progress;
182  }
183  }
184 
185  break;
186  }
187 
188  case eGauss:
189  {
190  ASSERTL0(m_filtWidth > NekConstants::kNekZeroTol,
191  "No filter width set");
192  // use m_filtWidth as FWHM
193  NekDouble sigma = m_filtWidth * 0.4246609001;
194 
195  m_maxPts = min(m_maxPts, int(m_ptsInField->GetNpoints() / 2));
196 
197  m_weights = Array<TwoD, NekDouble>(nOutPts, m_maxPts, 0.0);
198  m_neighInds = Array<TwoD, unsigned int>(nOutPts, m_maxPts, (unsigned int) 0);
199 
200  for (size_t i = 0; i < nOutPts; ++i)
201  {
202  Array<OneD, NekDouble> tmp(m_dim, 0.0);
203  for (size_t j = 0; j < m_ptsOutField->GetDim(); ++j)
204  {
205  tmp[j] = m_ptsOutField->GetPointVal(j, i);
206  }
207  PtsPoint searchPt(i, tmp, 1E30);
208 
209  CalcW_Gauss(searchPt, sigma, m_maxPts);
210 
211  int progress = int(100 * i / nOutPts);
212  if (m_progressCallback && progress > lastProg)
213  {
214  m_progressCallback(i, nOutPts);
215  lastProg = progress;
216  }
217  }
218 
219  break;
220  }
221 
222  default:
223  NEKERROR(ErrorUtil::efatal, "Invalid interpolation m_method");
224  break;
225  }
226 }
227 
228 /**
229  * @brief Interpolate from a pts field to a pts field
230  *
231  * @param ptsInField input field
232  * @param ptsOutField output field
233  *
234  * In and output fields must have the same dimension and number of fields.
235  * The most suitable algorithm is chosen automatically if it wasnt set
236  * explicitly.
237  */
238 void Interpolator::Interpolate(const LibUtilities::PtsFieldSharedPtr ptsInField,
239  LibUtilities::PtsFieldSharedPtr &ptsOutField)
240 {
241  ASSERTL0(ptsInField->GetNFields() == ptsOutField->GetNFields(),
242  "number of fields does not match");
243  ASSERTL0(ptsInField->GetDim() <= m_dim, "too many dimesions in inField");
244  ASSERTL0(ptsOutField->GetDim() <= m_dim, "too many dimesions in outField");
245 
246  m_ptsInField = ptsInField;
247  m_ptsOutField = ptsOutField;
248 
249  if (m_weights.GetRows() == 0)
250  {
251  CalcWeights(m_ptsInField, m_ptsOutField);
252  }
253 
254  ASSERTL0(m_weights.GetRows() == m_ptsOutField->GetNpoints(),
255  "weights dimension mismatch");
256 
257  size_t nFields = m_ptsOutField->GetNFields();
258  size_t nOutPts = m_ptsOutField->GetNpoints();
259  size_t inDim = m_ptsInField->GetDim();
260 
261  // interpolate points and transform
262  for (size_t i = 0; i < nFields; ++i)
263  {
264  for (size_t j = 0; j < nOutPts; ++j)
265  {
266  size_t nPts = m_weights.GetColumns();
267 
268  // skip if there were no neighbours found for this point
269  if (nPts == 0)
270  {
271  continue;
272  }
273 
274  NekDouble val = 0.0;
275  for (size_t k = 0; k < nPts; ++k)
276  {
277  size_t nIdx = m_neighInds[j][k];
278  val += m_weights[j][k] *
279  m_ptsInField->GetPointVal(inDim + i, nIdx);
280  }
281  m_ptsOutField->SetPointVal(m_ptsOutField->GetDim() + i, j, val);
282  }
283  }
284 }
285 
286 int Interpolator::GetDim() const
287 {
288  return m_dim;
289 }
290 
291 int Interpolator::GetCoordId() const
292 {
293  return m_coordId;
294 }
295 
296 NekDouble Interpolator::GetFiltWidth() const
297 {
298  return m_filtWidth;
299 }
300 
301 InterpMethod Interpolator::GetInterpMethod() const
302 {
303  return m_method;
304 }
305 
306 LibUtilities::PtsFieldSharedPtr Interpolator::GetInField() const
307 {
308  return m_ptsInField;
309 }
310 
311 LibUtilities::PtsFieldSharedPtr Interpolator::GetOutField() const
312 {
313  return m_ptsOutField;
314 }
315 
316 void Interpolator::PrintStatistics()
317 {
318  int meanN = 0;
319  for (int i = 0; i < m_neighInds.GetRows(); ++i)
320  {
321  for (int j = 0; j < m_neighInds.GetColumns(); ++j)
322  {
323  if (m_neighInds[i][j] > 0)
324  {
325  meanN +=1;
326  }
327  }
328  }
329 
330  cout << "Number of points: " << m_neighInds.GetRows() << endl;
331  if (m_neighInds.GetRows() > 0)
332  {
333  cout << "mean Number of Neighbours per point: "
334  << meanN / m_neighInds.GetRows() << endl;
335  }
336 }
337 
338 /**
339  * @brief Computes interpolation weights using gaussian interpolation
340  *
341  * @param searchPt point for which the weights are computed
342  * @param sigma standard deviation of the gauss function
343  *
344  * Performs an interpolation using gauss weighting. Ideal for filtering fields.
345  * The filter width should be half the FWHM (= 1.1774 sigma) and must be set in
346  * the constructor of the Interpolator class.
347  */
348 void Interpolator::CalcW_Gauss(const PtsPoint &searchPt,
349  const NekDouble sigma,
350  const int maxPts)
351 {
352  // find nearest neighbours
353  vector<PtsPoint> neighbourPts;
354  FindNeighbours(searchPt, neighbourPts, 4 * sigma, maxPts);
355  size_t numPts = neighbourPts.size();
356 
357  // handle the cases that there was no or just one point within 4 * sigma
358  if (numPts == 0)
359  {
360  return;
361  }
362  if (numPts == 1)
363  {
364  m_neighInds[searchPt.idx][0] = neighbourPts.front().idx;
365  m_weights[searchPt.idx][0] = 1.0;
366 
367  return;
368  }
369 
370  NekDouble sigmaNew = 0.25 * neighbourPts.back().dist;
371 
372  for (size_t i = 0; i < numPts; i++)
373  {
374  m_neighInds[searchPt.idx][i] = neighbourPts.at(i).idx;
375  }
376 
377  NekDouble wSum = 0.0;
378  NekDouble ts2 = 2.0 * sigmaNew * sigmaNew;
379  for (size_t i = 0; i < numPts; ++i)
380  {
381  m_weights[searchPt.idx][i] =
382  exp(-1.0 * neighbourPts[i].dist * neighbourPts[i].dist / ts2);
383  wSum += m_weights[searchPt.idx][i];
384  }
385 
386  for (size_t i = 0; i < numPts; ++i)
387  {
388  m_weights[searchPt.idx][i] = m_weights[searchPt.idx][i] / wSum;
389  }
390 }
391 
392 /**
393  * @brief Computes interpolation weights using linear interpolation
394  *
395  * @param searchPt point for which the weights are computed
396  * @param m_coordId coordinate id along which the interpolation should be
397  * performed
398  *
399  * Currently, only implemented for 1D
400  */
401 void Interpolator::CalcW_Linear(const PtsPoint &searchPt, int m_coordId)
402 {
403  int npts = m_ptsInField->GetNpoints();
404  int i;
405 
406  NekDouble coord = searchPt.coords[m_coordId];
407 
408  for (i = 0; i < npts - 1; ++i)
409  {
410  if ((m_ptsInField->GetPointVal(0, i) <=
411  (coord + NekConstants::kNekZeroTol)) &&
412  (coord <=
413  (m_ptsInField->GetPointVal(0, i + 1) + NekConstants::kNekZeroTol)))
414  {
415  NekDouble pdiff = m_ptsInField->GetPointVal(0, i + 1) -
416  m_ptsInField->GetPointVal(0, i);
417 
418  m_neighInds[searchPt.idx][0] = i;
419  m_neighInds[searchPt.idx][1] = i + 1;
420 
421  m_weights[searchPt.idx][0] =
422  (m_ptsInField->GetPointVal(0, i + 1) - coord) / pdiff;
423  m_weights[searchPt.idx][1] =
424  (coord - m_ptsInField->GetPointVal(0, i)) / pdiff;
425 
426  break;
427  }
428  }
429  ASSERTL0(i != npts - 1, "Failed to find coordinate " +
430  boost::lexical_cast<string>(coord) +
431  " within provided input points");
432 }
433 
434 /**
435  * @brief Computes interpolation weights using nearest neighbour interpolation
436  *
437  * @param searchPt point for which the weights are computed
438  * @param m_coordId coordinate id along which the interpolation should be
439  * performed
440  *
441  */
442 void Interpolator::CalcW_NNeighbour(const PtsPoint &searchPt)
443 {
444  // find nearest neighbours
445  vector<PtsPoint> neighbourPts;
446  // TODO: we currently dont handle the case when there are more than one
447  // most distant points (of same distance)
448  FindNNeighbours(searchPt, neighbourPts, 1);
449 
450  m_neighInds[searchPt.idx][0] = neighbourPts[0].idx;
451  m_weights[searchPt.idx][0] = 1.0;
452 }
453 
454 /**
455 * @brief Computes interpolation weights using linear interpolation
456 *
457 * @param searchPt point for which the weights are computed
458 * @param m_coordId coordinate id along which the interpolation should be
459 * performed
460 *
461 * The algorithm is based on Shepard, D. (1968). A two-dimensional interpolation
462 * function for irregularly-spaced data. Proceedings of the 1968 23rd ACM
463 * National Conference. pp. 517–524.
464 *
465 * In order to save memory, for n dimesnions, only 2^n points are considered.
466 * Contrary to Shepard, we use a fixed number of points with fixed weighting
467 * factors 1/d^n.
468 */
469 void Interpolator::CalcW_Shepard(const PtsPoint &searchPt, int numPts)
470 {
471  // find nearest neighbours
472  vector<PtsPoint> neighbourPts;
473  FindNNeighbours(searchPt, neighbourPts, numPts);
474 
475  for (int i = 0; i < neighbourPts.size(); i++)
476  {
477  m_neighInds[searchPt.idx][i] = neighbourPts[i].idx;
478  }
479 
480  // In case d < kVertexTheSameDouble ( d^2 < kNekSqrtTol), use the exact
481  // point and return
482  for (int i = 0; i < neighbourPts.size(); ++i)
483  {
484  if (neighbourPts[i].dist <= NekConstants::kNekZeroTol)
485  {
486  m_weights[searchPt.idx][i] = 1.0;
487  return;
488  }
489  }
490 
491  NekDouble wSum = 0.0;
492  for (int i = 0; i < neighbourPts.size(); ++i)
493  {
494  m_weights[searchPt.idx][i] = 1 / pow(double(neighbourPts[i].dist),
495  double(m_ptsInField->GetDim()));
496  wSum += m_weights[searchPt.idx][i];
497  }
498 
499  for (int i = 0; i < neighbourPts.size(); ++i)
500  {
501  m_weights[searchPt.idx][i] = m_weights[searchPt.idx][i] / wSum;
502  }
503 }
504 
505 /**
506  * @brief Computes interpolation weights using quadratic interpolation
507  *
508  * @param searchPt point for which the weights are computed
509  * @param m_coordId coordinate id along which the interpolation should be
510  * performed
511  *
512  * Currently, only implemented for 1D. Falls back to linear interpolation if
513  * only 2
514  * values are available.
515  */
516 void Interpolator::CalcW_Quadratic(const PtsPoint &searchPt, int m_coordId)
517 {
518  int npts = m_ptsInField->GetNpoints();
519  int i;
520 
521  NekDouble coord = searchPt.coords[m_coordId];
522 
523  for (i = 0; i < npts - 1; ++i)
524  {
525  if ((m_ptsInField->GetPointVal(0, i) <=
526  (coord + NekConstants::kNekZeroTol)) &&
527  (coord <=
528  (m_ptsInField->GetPointVal(0, i + 1) + NekConstants::kNekZeroTol)))
529  {
530  NekDouble pdiff = m_ptsInField->GetPointVal(0, i + 1) -
531  m_ptsInField->GetPointVal(0, i);
532  NekDouble h1, h2, h3;
533 
534  if (i < npts - 2)
535  {
536  // forwards stencil
537  NekDouble pdiff2 = m_ptsInField->GetPointVal(0, i + 2) -
538  m_ptsInField->GetPointVal(0, i + 1);
539 
540  h1 = (m_ptsInField->GetPointVal(0, i + 1) - coord) *
541  (m_ptsInField->GetPointVal(0, i + 2) - coord) /
542  (pdiff * (pdiff + pdiff2));
543  h2 = (coord - m_ptsInField->GetPointVal(0, i)) *
544  (m_ptsInField->GetPointVal(0, i + 2) - coord) /
545  (pdiff * pdiff2);
546  h3 = (coord - m_ptsInField->GetPointVal(0, i)) *
547  (coord - m_ptsInField->GetPointVal(0, i + 1)) /
548  ((pdiff + pdiff2) * pdiff2);
549 
550  m_neighInds[searchPt.idx][0] = i;
551  m_neighInds[searchPt.idx][1] = i + 1;
552  m_neighInds[searchPt.idx][2] = i + 2;
553  }
554  else
555  {
556  // backwards stencil
557  NekDouble pdiff2 = m_ptsInField->GetPointVal(0, i) -
558  m_ptsInField->GetPointVal(0, i - 1);
559 
560  h1 = (m_ptsInField->GetPointVal(0, i + 1) - coord) *
561  (coord - m_ptsInField->GetPointVal(0, i - 1)) /
562  (pdiff * pdiff2);
563  h2 = (coord - m_ptsInField->GetPointVal(0, i)) *
564  (coord - m_ptsInField->GetPointVal(0, i - 1)) /
565  (pdiff * (pdiff + pdiff2));
566  h3 = (m_ptsInField->GetPointVal(0, i) - coord) *
567  (m_ptsInField->GetPointVal(0, i + 1) - coord) /
568  ((pdiff + pdiff2) * pdiff);
569 
570  m_neighInds[searchPt.idx][0] = i;
571  m_neighInds[searchPt.idx][1] = i + 1;
572  m_neighInds[searchPt.idx][2] = i - 1;
573  }
574 
575  m_weights[searchPt.idx][0] = h1;
576  m_weights[searchPt.idx][1] = h2;
577  m_weights[searchPt.idx][2] = h3;
578 
579  break;
580  }
581  }
582  ASSERTL0(i != npts - 1, "Failed to find coordinate " +
583  boost::lexical_cast<string>(coord) +
584  " within provided input points");
585 }
586 
587 void Interpolator::SetupTree()
588 {
589  std::vector<PtsPointPair> inPoints;
590  for (int i = 0; i < m_ptsInField->GetNpoints(); ++i)
591  {
592  Array<OneD, NekDouble> coords(3, 0.0);
593  for (int j = 0; j < m_ptsInField->GetDim(); ++j)
594  {
595  coords[j] = m_ptsInField->GetPointVal(j, i);
596  }
597  inPoints.push_back(
598  PtsPointPair(BPoint(coords[0], coords[1], coords[2]), i));
599  }
601  m_rtree->insert(inPoints.begin(), inPoints.end());
602 
603  // remove duplicates from tree
604  for (auto &it : inPoints)
605  {
606  std::vector<PtsPointPair> result;
607 
608  // find nearest 2 points (2 because one of these might be the one we
609  // are
610  // checking)
611  m_rtree->query(bgi::nearest(it.first, 2),
612  std::back_inserter(result));
613 
614  // in case any of these 2 points is too close, remove the current
615  // point
616  // from the tree
617  for (auto &it2 : result)
618  {
619  if (it.second != it2.second &&
620  bg::distance(it.first, it2.first) <= NekConstants::kNekZeroTol)
621  {
622  m_rtree->remove(it);
623  break;
624  }
625  }
626  }
627 }
628 
629 /**
630  * @brief Finds the neares neighbours of a point
631  *
632  * @param searchPt point for which the neighbours are searched
633  * @param neighbourPts possible neighbour points
634  * @param numPts limits the number of neighbours found to the numPts
635  * nearest ones
636  *
637  */
638 void Interpolator::FindNNeighbours(const PtsPoint &searchPt,
639  vector<PtsPoint> &neighbourPts,
640  const unsigned int numPts)
641 {
642  std::vector<PtsPointPair> result;
643  BPoint searchBPoint(searchPt.coords[0], searchPt.coords[1],
644  searchPt.coords[2]);
645  m_rtree->query(bgi::nearest(searchBPoint, numPts),
646  std::back_inserter(result));
647 
648  // massage into or own format
649  for (int i = 0; i < result.size(); ++i)
650  {
651  int idx = result[i].second;
652  Array<OneD, NekDouble> coords(m_dim, 0.0);
653  for (int j = 0; j < m_ptsInField->GetDim(); ++j)
654  {
655  coords[j] = m_ptsInField->GetPointVal(j, idx);
656  }
657  NekDouble d = bg::distance(searchBPoint, result[i].first);
658  neighbourPts.push_back(PtsPoint(idx, coords, d));
659  }
660 
661  sort(neighbourPts.begin(), neighbourPts.end());
662 }
663 
664 /**
665  * @brief Finds the neares neighbours of a point
666  *
667  * @param searchPt point for which the neighbours are searched
668  * @param neighbourPts possible neighbour points
669  * @param dist limits the distance of the neighbours
670  *
671  */
672 void Interpolator::FindNeighbours(const PtsPoint &searchPt,
673  vector<PtsPoint> &neighbourPts,
674  const NekDouble dist,
675  const unsigned int maxPts)
676 {
677  BPoint searchBPoint(searchPt.coords[0], searchPt.coords[1],
678  searchPt.coords[2]);
679  BPoint bbMin(searchPt.coords[0] - dist, searchPt.coords[1] - dist,
680  searchPt.coords[2] - dist);
681  BPoint bbMax(searchPt.coords[0] + dist, searchPt.coords[1] + dist,
682  searchPt.coords[2] + dist);
683  bg::model::box<BPoint> bbox(bbMin, bbMax);
684 
685  // find points within the distance box
686  std::vector<PtsPointPair> result;
687  if (maxPts >= 1)
688  {
689  m_rtree->query(bgi::within(bbox) && bgi::nearest(searchBPoint, maxPts),
690  std::back_inserter(result));
691  }
692  else
693  {
694  m_rtree->query(bgi::within(bbox), std::back_inserter(result));
695  }
696 
697  // massage into or own format
698  for (int i = 0; i < result.size(); ++i)
699  {
700  int idx = result[i].second;
701  Array<OneD, NekDouble> coords(m_dim, 0.0);
702  for (int j = 0; j < m_ptsInField->GetDim(); ++j)
703  {
704  coords[j] = m_ptsInField->GetPointVal(j, idx);
705  }
706  NekDouble d = bg::distance(searchBPoint, result[i].first);
707 
708  // discard points beyonf dist
709  if (d <= dist)
710  {
711  neighbourPts.push_back(PtsPoint(idx, coords, d));
712  }
713  }
714 
715  sort(neighbourPts.begin(), neighbourPts.end());
716 }
717 }
718 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:209
boost::geometry::model::point< NekDouble, m_dim, boost::geometry::cs::cartesian > BPoint
General purpose memory allocation routines with the ability to allocate from thread specific memory p...
std::shared_ptr< PtsField > PtsFieldSharedPtr
Definition: PtsField.h:182
static const NekDouble kNekZeroTol
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:1
double NekDouble