37 #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() == 3)
80 else if (m_ptsInField->GetDim() == 1 || m_coordId >= 0)
90 if ((!m_rtree || !reuseTree) && m_method !=
eQuadratic)
103 for (
size_t i = 0; i < nOutPts; ++i)
106 for (
size_t j = 0; j < m_ptsOutField->GetDim(); ++j)
108 tmp[j] = m_ptsOutField->GetPointVal(j, i);
112 CalcW_NNeighbour(searchPt);
114 int progress = int(100 * i / nOutPts);
115 if (m_progressCallback && progress > lastProg)
117 m_progressCallback(i, nOutPts);
127 ASSERTL0(m_ptsInField->GetDim() == 1 || m_coordId >= 0,
134 for (
size_t i = 0; i < nOutPts; ++i)
137 for (
size_t j = 0; j < m_ptsOutField->GetDim(); ++j)
139 tmp[j] = m_ptsOutField->GetPointVal(j, i);
143 if (m_ptsInField->GetNpoints() <= 2)
145 CalcW_Linear(searchPt, m_coordId);
149 CalcW_Quadratic(searchPt, m_coordId);
152 int progress = int(100 * i / nOutPts);
153 if (m_progressCallback && progress > lastProg)
155 m_progressCallback(i, nOutPts);
165 int numPts = m_ptsInField->GetDim();
166 numPts = 1 << numPts;
167 numPts = min(numPts,
int(m_ptsInField->GetNpoints() / 2));
173 for (
size_t i = 0; i < nOutPts; ++i)
176 for (
size_t j = 0; j < m_ptsOutField->GetDim(); ++j)
178 tmp[j] = m_ptsOutField->GetPointVal(j, i);
182 CalcW_Shepard(searchPt, numPts);
184 int progress = int(100 * i / nOutPts);
185 if (m_progressCallback && progress > lastProg)
187 m_progressCallback(i, nOutPts);
198 "No filter width set");
200 NekDouble sigma = m_filtWidth * 0.4246609001;
202 m_maxPts = min(m_maxPts,
int(m_ptsInField->GetNpoints() / 2));
208 for (
size_t i = 0; i < nOutPts; ++i)
211 for (
size_t j = 0; j < m_ptsOutField->GetDim(); ++j)
213 tmp[j] = m_ptsOutField->GetPointVal(j, i);
217 CalcW_Gauss(searchPt, sigma, m_maxPts);
219 int progress = int(100 * i / nOutPts);
220 if (m_progressCallback && progress > lastProg)
222 m_progressCallback(i, nOutPts);
231 NEKERROR(ErrorUtil::efatal,
"Invalid interpolation m_method");
249 ASSERTL0(ptsInField->GetNFields() == ptsOutField->GetNFields(),
250 "number of fields does not match");
251 ASSERTL0(ptsInField->GetDim() <= m_dim,
"too many dimesions in inField");
252 ASSERTL0(ptsOutField->GetDim() <= m_dim,
"too many dimesions in outField");
254 m_ptsInField = ptsInField;
255 m_ptsOutField = ptsOutField;
257 if (m_weights.GetRows() == 0)
259 CalcWeights(m_ptsInField, m_ptsOutField);
262 ASSERTL0(m_weights.GetRows() == m_ptsOutField->GetNpoints(),
263 "weights dimension mismatch");
265 size_t nFields = m_ptsOutField->GetNFields();
266 size_t nOutPts = m_ptsOutField->GetNpoints();
267 size_t inDim = m_ptsInField->GetDim();
270 for (
size_t i = 0; i < nFields; ++i)
272 for (
size_t j = 0; j < nOutPts; ++j)
274 size_t nPts = m_weights.GetColumns();
283 for (
size_t k = 0; k < nPts; ++k)
285 size_t nIdx = m_neighInds[j][k];
286 val += m_weights[j][k] *
287 m_ptsInField->GetPointVal(inDim + i, nIdx);
289 m_ptsOutField->SetPointVal(m_ptsOutField->GetDim() + i, j, val);
294 int Interpolator::GetDim()
const
299 int Interpolator::GetCoordId()
const
321 return m_ptsOutField;
324 void Interpolator::PrintStatistics()
327 for (
int i = 0; i < m_neighInds.GetRows(); ++i)
329 for (
int j = 0; j < m_neighInds.GetColumns(); ++j)
331 if (m_neighInds[i][j] > 0)
338 cout <<
"Number of points: " << m_neighInds.GetRows() << endl;
339 if (m_neighInds.GetRows() > 0)
341 cout <<
"mean Number of Neighbours per point: "
342 << meanN / m_neighInds.GetRows() << endl;
360 vector<PtsPoint> neighbourPts;
361 FindNeighbours(searchPt, neighbourPts, 4 * sigma, maxPts);
362 size_t numPts = neighbourPts.size();
371 m_neighInds[searchPt.
idx][0] = neighbourPts.front().idx;
372 m_weights[searchPt.
idx][0] = 1.0;
377 NekDouble sigmaNew = 0.25 * neighbourPts.back().dist;
379 for (
size_t i = 0; i < numPts; i++)
381 m_neighInds[searchPt.
idx][i] = neighbourPts.at(i).idx;
385 NekDouble ts2 = 2.0 * sigmaNew * sigmaNew;
386 for (
size_t i = 0; i < numPts; ++i)
388 m_weights[searchPt.
idx][i] =
389 exp(-1.0 * neighbourPts[i].dist * neighbourPts[i].dist / ts2);
390 wSum += m_weights[searchPt.
idx][i];
393 for (
size_t i = 0; i < numPts; ++i)
395 m_weights[searchPt.
idx][i] = m_weights[searchPt.
idx][i] / wSum;
408 void Interpolator::CalcW_Linear(
const PtsPoint &searchPt,
int m_coordId)
410 int npts = m_ptsInField->GetNpoints();
415 for (i = 0; i < npts - 1; ++i)
417 if ((m_ptsInField->GetPointVal(0, i) <=
422 NekDouble pdiff = m_ptsInField->GetPointVal(0, i + 1) -
423 m_ptsInField->GetPointVal(0, i);
425 m_neighInds[searchPt.
idx][0] = i;
426 m_neighInds[searchPt.
idx][1] = i + 1;
428 m_weights[searchPt.
idx][0] =
429 (m_ptsInField->GetPointVal(0, i + 1) - coord) / pdiff;
430 m_weights[searchPt.
idx][1] =
431 (coord - m_ptsInField->GetPointVal(0, i)) / pdiff;
436 ASSERTL0(i != npts - 1,
"Failed to find coordinate " +
437 boost::lexical_cast<string>(coord) +
438 " within provided input points");
449 void Interpolator::CalcW_NNeighbour(
const PtsPoint &searchPt)
452 vector<PtsPoint> neighbourPts;
455 FindNNeighbours(searchPt, neighbourPts, 1);
457 m_neighInds[searchPt.
idx][0] = neighbourPts[0].idx;
458 m_weights[searchPt.
idx][0] = 1.0;
476 void Interpolator::CalcW_Shepard(
const PtsPoint &searchPt,
int numPts)
479 vector<PtsPoint> neighbourPts;
480 FindNNeighbours(searchPt, neighbourPts, numPts);
482 for (
int i = 0; i < neighbourPts.size(); i++)
484 m_neighInds[searchPt.
idx][i] = neighbourPts[i].idx;
489 for (
int i = 0; i < neighbourPts.size(); ++i)
493 m_weights[searchPt.
idx][i] = 1.0;
499 for (
int i = 0; i < neighbourPts.size(); ++i)
501 m_weights[searchPt.
idx][i] = 1 / pow(
double(neighbourPts[i].dist),
502 double(m_ptsInField->GetDim()));
503 wSum += m_weights[searchPt.
idx][i];
506 for (
int i = 0; i < neighbourPts.size(); ++i)
508 m_weights[searchPt.
idx][i] = m_weights[searchPt.
idx][i] / wSum;
523 void Interpolator::CalcW_Quadratic(
const PtsPoint &searchPt,
int m_coordId)
525 int npts = m_ptsInField->GetNpoints();
530 for (i = 0; i < npts - 1; ++i)
532 if ((m_ptsInField->GetPointVal(0, i) <=
537 NekDouble pdiff = m_ptsInField->GetPointVal(0, i + 1) -
538 m_ptsInField->GetPointVal(0, i);
544 NekDouble pdiff2 = m_ptsInField->GetPointVal(0, i + 2) -
545 m_ptsInField->GetPointVal(0, i + 1);
547 h1 = (m_ptsInField->GetPointVal(0, i + 1) - coord) *
548 (m_ptsInField->GetPointVal(0, i + 2) - coord) /
549 (pdiff * (pdiff + pdiff2));
550 h2 = (coord - m_ptsInField->GetPointVal(0, i)) *
551 (m_ptsInField->GetPointVal(0, i + 2) - coord) /
553 h3 = (coord - m_ptsInField->GetPointVal(0, i)) *
554 (coord - m_ptsInField->GetPointVal(0, i + 1)) /
555 ((pdiff + pdiff2) * pdiff2);
557 m_neighInds[searchPt.
idx][0] = i;
558 m_neighInds[searchPt.
idx][1] = i + 1;
559 m_neighInds[searchPt.
idx][2] = i + 2;
564 NekDouble pdiff2 = m_ptsInField->GetPointVal(0, i) -
565 m_ptsInField->GetPointVal(0, i - 1);
567 h1 = (m_ptsInField->GetPointVal(0, i + 1) - coord) *
568 (coord - m_ptsInField->GetPointVal(0, i - 1)) /
570 h2 = (coord - m_ptsInField->GetPointVal(0, i)) *
571 (coord - m_ptsInField->GetPointVal(0, i - 1)) /
572 (pdiff * (pdiff + pdiff2));
573 h3 = (m_ptsInField->GetPointVal(0, i) - coord) *
574 (m_ptsInField->GetPointVal(0, i + 1) - coord) /
575 ((pdiff + pdiff2) * pdiff);
577 m_neighInds[searchPt.
idx][0] = i;
578 m_neighInds[searchPt.
idx][1] = i + 1;
579 m_neighInds[searchPt.
idx][2] = i - 1;
582 m_weights[searchPt.
idx][0] = h1;
583 m_weights[searchPt.
idx][1] = h2;
584 m_weights[searchPt.
idx][2] = h3;
589 ASSERTL0(i != npts - 1,
"Failed to find coordinate " +
590 boost::lexical_cast<string>(coord) +
591 " within provided input points");
594 void Interpolator::SetupTree()
596 std::vector<PtsPointPair> inPoints;
597 for (
int i = 0; i < m_ptsInField->GetNpoints(); ++i)
600 for (
int j = 0; j < m_ptsInField->GetDim(); ++j)
602 coords[j] = m_ptsInField->GetPointVal(j, i);
608 m_rtree->insert(inPoints.begin(), inPoints.end());
611 for (
auto &it : inPoints)
613 std::vector<PtsPointPair> result;
618 m_rtree->query(bgi::nearest(it.first, 2), std::back_inserter(result));
623 for (
auto &it2 : result)
625 if (it.second != it2.second &&
644 void Interpolator::FindNNeighbours(
const PtsPoint &searchPt,
645 vector<PtsPoint> &neighbourPts,
646 const unsigned int numPts)
648 std::vector<PtsPointPair> result;
651 m_rtree->query(bgi::nearest(searchBPoint, numPts),
652 std::back_inserter(result));
655 for (
int i = 0; i < result.size(); ++i)
657 int idx = result[i].second;
659 for (
int j = 0; j < m_ptsInField->GetDim(); ++j)
661 coords[j] = m_ptsInField->GetPointVal(j, idx);
663 NekDouble d = bg::distance(searchBPoint, result[i].first);
664 neighbourPts.push_back(
PtsPoint(idx, coords, d));
667 sort(neighbourPts.begin(), neighbourPts.end());
678 void Interpolator::FindNeighbours(
const PtsPoint &searchPt,
679 vector<PtsPoint> &neighbourPts,
681 const unsigned int maxPts)
686 searchPt.
coords[2] - dist);
688 searchPt.
coords[2] + dist);
689 bg::model::box<BPoint> bbox(bbMin, bbMax);
692 std::vector<PtsPointPair> result;
695 m_rtree->query(bgi::within(bbox) && bgi::nearest(searchBPoint, maxPts),
696 std::back_inserter(result));
700 m_rtree->query(bgi::within(bbox), std::back_inserter(result));
704 for (
int i = 0; i < result.size(); ++i)
706 int idx = result[i].second;
708 for (
int j = 0; j < m_ptsInField->GetDim(); ++j)
710 coords[j] = m_ptsInField->GetPointVal(j, idx);
712 NekDouble d = bg::distance(searchBPoint, result[i].first);
717 neighbourPts.push_back(
PtsPoint(idx, coords, d));
721 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.