36 #include <boost/geometry.hpp>
41 namespace bg = boost::geometry;
42 namespace bgi = boost::geometry::index;
46 namespace LibUtilities
64 ASSERTL0(ptsInField->GetDim() <= m_dim,
"too many dimesions in inField");
65 ASSERTL0(ptsOutField->GetDim() <= m_dim,
"too many dimesions in outField");
67 m_ptsInField = ptsInField;
68 m_ptsOutField = ptsOutField;
70 size_t nOutPts = m_ptsOutField->GetNpoints();
76 if (m_ptsInField->GetDim() == 1 || m_coordId >= 0)
86 if ((!m_rtree || !reuseTree) && m_method !=
eQuadratic)
98 for (
size_t i = 0; i < nOutPts; ++i)
101 for (
size_t j = 0; j < m_ptsOutField->GetDim(); ++j)
103 tmp[j] = m_ptsOutField->GetPointVal(j, i);
107 CalcW_NNeighbour(searchPt);
109 int progress = int(100 * i / nOutPts);
110 if (m_progressCallback && progress > lastProg)
112 m_progressCallback(i, nOutPts);
122 ASSERTL0(m_ptsInField->GetDim() == 1 || m_coordId >= 0,
128 for (
size_t i = 0; i < nOutPts; ++i)
131 for (
size_t j = 0; j < m_ptsOutField->GetDim(); ++j)
133 tmp[j] = m_ptsOutField->GetPointVal(j, i);
137 if (m_ptsInField->GetNpoints() <= 2)
139 CalcW_Linear(searchPt, m_coordId);
143 CalcW_Quadratic(searchPt, m_coordId);
146 int progress = int(100 * i / nOutPts);
147 if (m_progressCallback && progress > lastProg)
149 m_progressCallback(i, nOutPts);
159 int numPts = m_ptsInField->GetDim();
160 numPts = 1 << numPts;
161 numPts = min(numPts,
int(m_ptsInField->GetNpoints() / 2));
166 for (
size_t i = 0; i < nOutPts; ++i)
169 for (
size_t j = 0; j < m_ptsOutField->GetDim(); ++j)
171 tmp[j] = m_ptsOutField->GetPointVal(j, i);
175 CalcW_Shepard(searchPt, numPts);
177 int progress = int(100 * i / nOutPts);
178 if (m_progressCallback && progress > lastProg)
180 m_progressCallback(i, nOutPts);
191 "No filter width set");
193 NekDouble sigma = m_filtWidth * 0.4246609001;
195 m_maxPts = min(m_maxPts,
int(m_ptsInField->GetNpoints() / 2));
200 for (
size_t i = 0; i < nOutPts; ++i)
203 for (
size_t j = 0; j < m_ptsOutField->GetDim(); ++j)
205 tmp[j] = m_ptsOutField->GetPointVal(j, i);
209 CalcW_Gauss(searchPt, sigma, m_maxPts);
211 int progress = int(100 * i / nOutPts);
212 if (m_progressCallback && progress > lastProg)
214 m_progressCallback(i, nOutPts);
223 NEKERROR(ErrorUtil::efatal,
"Invalid interpolation m_method");
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");
246 m_ptsInField = ptsInField;
247 m_ptsOutField = ptsOutField;
249 if (m_weights.GetRows() == 0)
251 CalcWeights(m_ptsInField, m_ptsOutField);
254 ASSERTL0(m_weights.GetRows() == m_ptsOutField->GetNpoints(),
255 "weights dimension mismatch");
257 size_t nFields = m_ptsOutField->GetNFields();
258 size_t nOutPts = m_ptsOutField->GetNpoints();
259 size_t inDim = m_ptsInField->GetDim();
262 for (
size_t i = 0; i < nFields; ++i)
264 for (
size_t j = 0; j < nOutPts; ++j)
266 size_t nPts = m_weights.GetColumns();
275 for (
size_t k = 0; k < nPts; ++k)
277 size_t nIdx = m_neighInds[j][k];
278 val += m_weights[j][k] *
279 m_ptsInField->GetPointVal(inDim + i, nIdx);
281 m_ptsOutField->SetPointVal(m_ptsOutField->GetDim() + i, j, val);
286 int Interpolator::GetDim()
const
291 int Interpolator::GetCoordId()
const
313 return m_ptsOutField;
316 void Interpolator::PrintStatistics()
319 for (
int i = 0; i < m_neighInds.GetRows(); ++i)
321 for (
int j = 0; j < m_neighInds.GetColumns(); ++j)
323 if (m_neighInds[i][j] > 0)
330 cout <<
"Number of points: " << m_neighInds.GetRows() << endl;
331 if (m_neighInds.GetRows() > 0)
333 cout <<
"mean Number of Neighbours per point: "
334 << meanN / m_neighInds.GetRows() << endl;
348 void Interpolator::CalcW_Gauss(
const PtsPoint &searchPt,
353 vector<PtsPoint> neighbourPts;
354 FindNeighbours(searchPt, neighbourPts, 4 * sigma, maxPts);
355 size_t numPts = neighbourPts.size();
364 m_neighInds[searchPt.
idx][0] = neighbourPts.front().idx;
365 m_weights[searchPt.
idx][0] = 1.0;
370 NekDouble sigmaNew = 0.25 * neighbourPts.back().dist;
372 for (
size_t i = 0; i < numPts; i++)
374 m_neighInds[searchPt.
idx][i] = neighbourPts.at(i).idx;
378 NekDouble ts2 = 2.0 * sigmaNew * sigmaNew;
379 for (
size_t i = 0; i < numPts; ++i)
381 m_weights[searchPt.
idx][i] =
382 exp(-1.0 * neighbourPts[i].dist * neighbourPts[i].dist / ts2);
383 wSum += m_weights[searchPt.
idx][i];
386 for (
size_t i = 0; i < numPts; ++i)
388 m_weights[searchPt.
idx][i] = m_weights[searchPt.
idx][i] / wSum;
401 void Interpolator::CalcW_Linear(
const PtsPoint &searchPt,
int m_coordId)
403 int npts = m_ptsInField->GetNpoints();
408 for (i = 0; i < npts - 1; ++i)
410 if ((m_ptsInField->GetPointVal(0, i) <=
415 NekDouble pdiff = m_ptsInField->GetPointVal(0, i + 1) -
416 m_ptsInField->GetPointVal(0, i);
418 m_neighInds[searchPt.
idx][0] = i;
419 m_neighInds[searchPt.
idx][1] = i + 1;
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;
429 ASSERTL0(i != npts - 1,
"Failed to find coordinate " +
430 boost::lexical_cast<string>(coord) +
431 " within provided input points");
442 void Interpolator::CalcW_NNeighbour(
const PtsPoint &searchPt)
445 vector<PtsPoint> neighbourPts;
448 FindNNeighbours(searchPt, neighbourPts, 1);
450 m_neighInds[searchPt.
idx][0] = neighbourPts[0].idx;
451 m_weights[searchPt.
idx][0] = 1.0;
469 void Interpolator::CalcW_Shepard(
const PtsPoint &searchPt,
int numPts)
472 vector<PtsPoint> neighbourPts;
473 FindNNeighbours(searchPt, neighbourPts, numPts);
475 for (
int i = 0; i < neighbourPts.size(); i++)
477 m_neighInds[searchPt.
idx][i] = neighbourPts[i].idx;
482 for (
int i = 0; i < neighbourPts.size(); ++i)
486 m_weights[searchPt.
idx][i] = 1.0;
492 for (
int i = 0; i < neighbourPts.size(); ++i)
494 m_weights[searchPt.
idx][i] = 1 / pow(
double(neighbourPts[i].dist),
495 double(m_ptsInField->GetDim()));
496 wSum += m_weights[searchPt.
idx][i];
499 for (
int i = 0; i < neighbourPts.size(); ++i)
501 m_weights[searchPt.
idx][i] = m_weights[searchPt.
idx][i] / wSum;
516 void Interpolator::CalcW_Quadratic(
const PtsPoint &searchPt,
int m_coordId)
518 int npts = m_ptsInField->GetNpoints();
523 for (i = 0; i < npts - 1; ++i)
525 if ((m_ptsInField->GetPointVal(0, i) <=
530 NekDouble pdiff = m_ptsInField->GetPointVal(0, i + 1) -
531 m_ptsInField->GetPointVal(0, i);
537 NekDouble pdiff2 = m_ptsInField->GetPointVal(0, i + 2) -
538 m_ptsInField->GetPointVal(0, i + 1);
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) /
546 h3 = (coord - m_ptsInField->GetPointVal(0, i)) *
547 (coord - m_ptsInField->GetPointVal(0, i + 1)) /
548 ((pdiff + pdiff2) * pdiff2);
550 m_neighInds[searchPt.
idx][0] = i;
551 m_neighInds[searchPt.
idx][1] = i + 1;
552 m_neighInds[searchPt.
idx][2] = i + 2;
557 NekDouble pdiff2 = m_ptsInField->GetPointVal(0, i) -
558 m_ptsInField->GetPointVal(0, i - 1);
560 h1 = (m_ptsInField->GetPointVal(0, i + 1) - coord) *
561 (coord - m_ptsInField->GetPointVal(0, i - 1)) /
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);
570 m_neighInds[searchPt.
idx][0] = i;
571 m_neighInds[searchPt.
idx][1] = i + 1;
572 m_neighInds[searchPt.
idx][2] = i - 1;
575 m_weights[searchPt.
idx][0] = h1;
576 m_weights[searchPt.
idx][1] = h2;
577 m_weights[searchPt.
idx][2] = h3;
582 ASSERTL0(i != npts - 1,
"Failed to find coordinate " +
583 boost::lexical_cast<string>(coord) +
584 " within provided input points");
587 void Interpolator::SetupTree()
589 std::vector<PtsPointPair> inPoints;
590 for (
int i = 0; i < m_ptsInField->GetNpoints(); ++i)
593 for (
int j = 0; j < m_ptsInField->GetDim(); ++j)
595 coords[j] = m_ptsInField->GetPointVal(j, i);
601 m_rtree->insert(inPoints.begin(), inPoints.end());
604 for (
auto &it : inPoints)
606 std::vector<PtsPointPair> result;
611 m_rtree->query(bgi::nearest(it.first, 2),
612 std::back_inserter(result));
617 for (
auto &it2 : result)
619 if (it.second != it2.second &&
638 void Interpolator::FindNNeighbours(
const PtsPoint &searchPt,
639 vector<PtsPoint> &neighbourPts,
640 const unsigned int numPts)
642 std::vector<PtsPointPair> result;
645 m_rtree->query(bgi::nearest(searchBPoint, numPts),
646 std::back_inserter(result));
649 for (
int i = 0; i < result.size(); ++i)
651 int idx = result[i].second;
653 for (
int j = 0; j < m_ptsInField->GetDim(); ++j)
655 coords[j] = m_ptsInField->GetPointVal(j, idx);
657 NekDouble d = bg::distance(searchBPoint, result[i].first);
658 neighbourPts.push_back(
PtsPoint(idx, coords, d));
661 sort(neighbourPts.begin(), neighbourPts.end());
672 void Interpolator::FindNeighbours(
const PtsPoint &searchPt,
673 vector<PtsPoint> &neighbourPts,
675 const unsigned int maxPts)
680 searchPt.
coords[2] - dist);
682 searchPt.
coords[2] + dist);
683 bg::model::box<BPoint> bbox(bbMin, bbMax);
686 std::vector<PtsPointPair> result;
689 m_rtree->query(bgi::within(bbox) && bgi::nearest(searchBPoint, maxPts),
690 std::back_inserter(result));
694 m_rtree->query(bgi::within(bbox), std::back_inserter(result));
698 for (
int i = 0; i < result.size(); ++i)
700 int idx = result[i].second;
702 for (
int j = 0; j < m_ptsInField->GetDim(); ++j)
704 coords[j] = m_ptsInField->GetPointVal(j, idx);
706 NekDouble d = bg::distance(searchBPoint, result[i].first);
711 neighbourPts.push_back(
PtsPoint(idx, coords, d));
715 sort(neighbourPts.begin(), neighbourPts.end());
#define ASSERTL0(condition, msg)
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Array< OneD, NekDouble > coords
std::pair< BPoint, unsigned int > PtsPointPair
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
static const NekDouble kNekZeroTol
The above copyright notice and this permission notice shall be included.