36 #include <boost/geometry.hpp> 41 namespace bg = boost::geometry;
42 namespace bgi = boost::geometry::index;
46 namespace LibUtilities
61 ASSERTL0(ptsInField->GetDim() <= m_dim,
"too many dimesions in inField");
62 ASSERTL0(ptsOutField->GetDim() <= m_dim,
"too many dimesions in outField");
64 m_ptsInField = ptsInField;
65 m_ptsOutField = ptsOutField;
67 size_t nOutPts = m_ptsOutField->GetNpoints();
73 if (m_ptsInField->GetDim() == 1 || m_coordId >= 0)
95 for (
size_t i = 0; i < nOutPts; ++i)
98 for (
size_t j = 0; j < m_ptsOutField->GetDim(); ++j)
100 tmp[j] = m_ptsOutField->GetPointVal(j, i);
104 CalcW_NNeighbour(searchPt);
106 int progress = int(100 * i / nOutPts);
107 if (m_progressCallback && progress > lastProg)
109 m_progressCallback(i, nOutPts);
119 ASSERTL0(m_ptsInField->GetDim() == 1 || m_coordId >= 0,
125 for (
size_t i = 0; i < nOutPts; ++i)
128 for (
size_t j = 0; j < m_ptsOutField->GetDim(); ++j)
130 tmp[j] = m_ptsOutField->GetPointVal(j, i);
134 if (m_ptsInField->GetNpoints() <= 2)
136 CalcW_Linear(searchPt, m_coordId);
140 CalcW_Quadratic(searchPt, m_coordId);
143 int progress = int(100 * i / nOutPts);
144 if (m_progressCallback && progress > lastProg)
146 m_progressCallback(i, nOutPts);
156 int numPts = m_ptsInField->GetDim();
157 numPts = 2 << numPts;
158 numPts = min(numPts,
int(m_ptsInField->GetNpoints() / 2));
163 for (
size_t i = 0; i < nOutPts; ++i)
166 for (
size_t j = 0; j < m_ptsOutField->GetDim(); ++j)
168 tmp[j] = m_ptsOutField->GetPointVal(j, i);
172 CalcW_Shepard(searchPt, numPts);
174 int progress = int(100 * i / nOutPts);
175 if (m_progressCallback && progress > lastProg)
177 m_progressCallback(i, nOutPts);
188 "No filter width set");
190 NekDouble sigma = m_filtWidth * 0.4246609001;
192 m_maxPts = min(m_maxPts,
int(m_ptsInField->GetNpoints() / 2));
197 for (
size_t i = 0; i < nOutPts; ++i)
200 for (
size_t j = 0; j < m_ptsOutField->GetDim(); ++j)
202 tmp[j] = m_ptsOutField->GetPointVal(j, i);
206 CalcW_Gauss(searchPt, sigma, m_maxPts);
208 int progress = int(100 * i / nOutPts);
209 if (m_progressCallback && progress > lastProg)
211 m_progressCallback(i, nOutPts);
220 NEKERROR(ErrorUtil::efatal,
"Invalid interpolation m_method");
238 ASSERTL0(ptsInField->GetNFields() == ptsOutField->GetNFields(),
239 "number of fields does not match");
240 ASSERTL0(ptsInField->GetDim() <= m_dim,
"too many dimesions in inField");
241 ASSERTL0(ptsOutField->GetDim() <= m_dim,
"too many dimesions in outField");
243 m_ptsInField = ptsInField;
244 m_ptsOutField = ptsOutField;
246 if (m_weights.GetRows() == 0)
248 CalcWeights(m_ptsInField, m_ptsOutField);
251 ASSERTL0(m_weights.GetRows() == m_ptsOutField->GetNpoints(),
252 "weights dimension mismatch");
254 size_t nFields = m_ptsOutField->GetNFields();
255 size_t nOutPts = m_ptsOutField->GetNpoints();
256 size_t inDim = m_ptsInField->GetDim();
259 for (
size_t i = 0; i < nFields; ++i)
261 for (
size_t j = 0; j < nOutPts; ++j)
263 size_t nPts = m_weights.GetColumns();
272 for (
size_t k = 0; k < nPts; ++k)
274 size_t nIdx = m_neighInds[j][k];
275 val += m_weights[j][k] *
276 m_ptsInField->GetPointVal(inDim + i, nIdx);
278 m_ptsOutField->SetPointVal(m_ptsOutField->GetDim() + i, j, val);
283 int Interpolator::GetDim()
const 288 int Interpolator::GetCoordId()
const 310 return m_ptsOutField;
313 void Interpolator::PrintStatistics()
316 for (
int i = 0; i < m_neighInds.GetRows(); ++i)
318 for (
int j = 0; j < m_neighInds.GetColumns(); ++j)
320 if (m_neighInds[i][j] > 0)
327 cout <<
"Number of points: " << m_neighInds.GetRows() << endl;
328 if (m_neighInds.GetRows() > 0)
330 cout <<
"mean Number of Neighbours per point: " 331 << meanN / m_neighInds.GetRows() << endl;
345 void Interpolator::CalcW_Gauss(
const PtsPoint &searchPt,
350 vector<PtsPoint> neighbourPts;
351 FindNeighbours(searchPt, neighbourPts, 4 * sigma, maxPts);
352 size_t numPts = neighbourPts.size();
361 m_neighInds[searchPt.
idx][0] = neighbourPts.front().idx;
362 m_weights[searchPt.
idx][0] = 1.0;
367 NekDouble sigmaNew = 0.25 * neighbourPts.back().dist;
369 for (
size_t i = 0; i < numPts; i++)
371 m_neighInds[searchPt.
idx][i] = neighbourPts.at(i).idx;
375 NekDouble ts2 = 2.0 * sigmaNew * sigmaNew;
376 for (
size_t i = 0; i < numPts; ++i)
378 m_weights[searchPt.
idx][i] =
379 exp(-1.0 * neighbourPts[i].dist * neighbourPts[i].dist / ts2);
380 wSum += m_weights[searchPt.
idx][i];
383 for (
size_t i = 0; i < numPts; ++i)
385 m_weights[searchPt.
idx][i] = m_weights[searchPt.
idx][i] / wSum;
398 void Interpolator::CalcW_Linear(
const PtsPoint &searchPt,
int m_coordId)
400 int npts = m_ptsInField->GetNpoints();
405 for (i = 0; i < npts - 1; ++i)
407 if ((m_ptsInField->GetPointVal(0, i) <=
412 NekDouble pdiff = m_ptsInField->GetPointVal(0, i + 1) -
413 m_ptsInField->GetPointVal(0, i);
415 m_neighInds[searchPt.
idx][0] = i;
416 m_neighInds[searchPt.
idx][1] = i + 1;
418 m_weights[searchPt.
idx][0] =
419 (m_ptsInField->GetPointVal(0, i + 1) - coord) / pdiff;
420 m_weights[searchPt.
idx][1] =
421 (coord - m_ptsInField->GetPointVal(0, i)) / pdiff;
426 ASSERTL0(i != npts - 1,
"Failed to find coordinate " +
427 boost::lexical_cast<string>(coord) +
428 " within provided input points");
439 void Interpolator::CalcW_NNeighbour(
const PtsPoint &searchPt)
442 vector<PtsPoint> neighbourPts;
445 FindNNeighbours(searchPt, neighbourPts, 1);
447 m_neighInds[searchPt.
idx][0] = neighbourPts[0].idx;
448 m_weights[searchPt.
idx][0] = 1.0;
466 void Interpolator::CalcW_Shepard(
const PtsPoint &searchPt,
int numPts)
469 vector<PtsPoint> neighbourPts;
470 FindNNeighbours(searchPt, neighbourPts, numPts);
472 for (
int i = 0; i < neighbourPts.size(); i++)
474 m_neighInds[searchPt.
idx][i] = neighbourPts[i].idx;
479 for (
int i = 0; i < neighbourPts.size(); ++i)
483 m_weights[searchPt.
idx][i] = 1.0;
489 for (
int i = 0; i < neighbourPts.size(); ++i)
491 m_weights[searchPt.
idx][i] = 1 / pow(
double(neighbourPts[i].dist),
492 double(m_ptsInField->GetDim()));
493 wSum += m_weights[searchPt.
idx][i];
496 for (
int i = 0; i < neighbourPts.size(); ++i)
498 m_weights[searchPt.
idx][i] = m_weights[searchPt.
idx][i] / wSum;
513 void Interpolator::CalcW_Quadratic(
const PtsPoint &searchPt,
int m_coordId)
515 int npts = m_ptsInField->GetNpoints();
520 for (i = 0; i < npts - 1; ++i)
522 if ((m_ptsInField->GetPointVal(0, i) <=
527 NekDouble pdiff = m_ptsInField->GetPointVal(0, i + 1) -
528 m_ptsInField->GetPointVal(0, i);
534 NekDouble pdiff2 = m_ptsInField->GetPointVal(0, i + 2) -
535 m_ptsInField->GetPointVal(0, i + 1);
537 h1 = (m_ptsInField->GetPointVal(0, i + 1) - coord) *
538 (m_ptsInField->GetPointVal(0, i + 2) - coord) /
539 (pdiff * (pdiff + pdiff2));
540 h2 = (coord - m_ptsInField->GetPointVal(0, i)) *
541 (m_ptsInField->GetPointVal(0, i + 2) - coord) /
543 h3 = (coord - m_ptsInField->GetPointVal(0, i)) *
544 (coord - m_ptsInField->GetPointVal(0, i + 1)) /
545 ((pdiff + pdiff2) * pdiff2);
547 m_neighInds[searchPt.
idx][0] = i;
548 m_neighInds[searchPt.
idx][1] = i + 1;
549 m_neighInds[searchPt.
idx][2] = i + 2;
554 NekDouble pdiff2 = m_ptsInField->GetPointVal(0, i) -
555 m_ptsInField->GetPointVal(0, i - 1);
557 h1 = (m_ptsInField->GetPointVal(0, i + 1) - coord) *
558 (coord - m_ptsInField->GetPointVal(0, i - 1)) /
560 h2 = (coord - m_ptsInField->GetPointVal(0, i)) *
561 (coord - m_ptsInField->GetPointVal(0, i - 1)) /
562 (pdiff * (pdiff + pdiff2));
563 h3 = (m_ptsInField->GetPointVal(0, i) - coord) *
564 (m_ptsInField->GetPointVal(0, i + 1) - coord) /
565 ((pdiff + pdiff2) * pdiff);
567 m_neighInds[searchPt.
idx][0] = i;
568 m_neighInds[searchPt.
idx][1] = i + 1;
569 m_neighInds[searchPt.
idx][2] = i - 1;
572 m_weights[searchPt.
idx][0] = h1;
573 m_weights[searchPt.
idx][1] = h2;
574 m_weights[searchPt.
idx][2] = h3;
579 ASSERTL0(i != npts - 1,
"Failed to find coordinate " +
580 boost::lexical_cast<string>(coord) +
581 " within provided input points");
584 void Interpolator::SetupTree()
586 std::vector<PtsPointPair> inPoints;
587 for (
int i = 0; i < m_ptsInField->GetNpoints(); ++i)
590 for (
int j = 0; j < m_ptsInField->GetDim(); ++j)
592 coords[j] = m_ptsInField->GetPointVal(j, i);
598 m_rtree->insert(inPoints.begin(), inPoints.end());
601 for (
auto &it : inPoints)
603 std::vector<PtsPointPair> result;
608 m_rtree->query(bgi::nearest(it.first, 2),
609 std::back_inserter(result));
614 for (
auto &it2 : result)
616 if (it.second != it2.second &&
635 void Interpolator::FindNNeighbours(
const PtsPoint &searchPt,
636 vector<PtsPoint> &neighbourPts,
637 const unsigned int numPts)
639 std::vector<PtsPointPair> result;
642 m_rtree->query(bgi::nearest(searchBPoint, numPts),
643 std::back_inserter(result));
646 for (
int i = 0; i < result.size(); ++i)
648 int idx = result[i].second;
650 for (
int j = 0; j < m_ptsInField->GetDim(); ++j)
652 coords[j] = m_ptsInField->GetPointVal(j, idx);
654 NekDouble d = bg::distance(searchBPoint, result[i].first);
655 neighbourPts.push_back(
PtsPoint(idx, coords, d));
658 sort(neighbourPts.begin(), neighbourPts.end());
669 void Interpolator::FindNeighbours(
const PtsPoint &searchPt,
670 vector<PtsPoint> &neighbourPts,
672 const unsigned int maxPts)
677 searchPt.
coords[2] - dist);
679 searchPt.
coords[2] + dist);
680 bg::model::box<BPoint> bbox(bbMin, bbMax);
683 std::vector<PtsPointPair> result;
686 m_rtree->query(bgi::within(bbox) && bgi::nearest(searchBPoint, maxPts),
687 std::back_inserter(result));
691 m_rtree->query(bgi::within(bbox), std::back_inserter(result));
695 for (
int i = 0; i < result.size(); ++i)
697 int idx = result[i].second;
699 for (
int j = 0; j < m_ptsInField->GetDim(); ++j)
701 coords[j] = m_ptsInField->GetPointVal(j, idx);
703 NekDouble d = bg::distance(searchBPoint, result[i].first);
708 neighbourPts.push_back(
PtsPoint(idx, coords, d));
712 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 mod...
General purpose memory allocation routines with the ability to allocate from thread specific memory p...
Array< OneD, NekDouble > coords
std::pair< BPoint, unsigned int > PtsPointPair
boost::geometry::model::point< NekDouble, m_dim, boost::geometry::cs::cartesian > BPoint
std::shared_ptr< PtsField > PtsFieldSharedPtr
static const NekDouble kNekZeroTol