37 #include <boost/geometry.hpp>
42 namespace bg = boost::geometry;
43 namespace bgi = boost::geometry::index;
62 ASSERTL0(ptsInField->GetDim() <= m_dim,
"too many dimesions in inField");
63 ASSERTL0(ptsOutField->GetDim() <= m_dim,
"too many dimesions in outField");
65 m_ptsInField = ptsInField;
66 m_ptsOutField = ptsOutField;
68 int nOutPts = m_ptsOutField->GetNpoints();
74 if (m_ptsInField->GetDim() == 1 || m_coordId >= 0)
96 for (
int i = 0; i < nOutPts; ++i)
99 for (
int j = 0; j < m_ptsOutField->GetDim(); ++j)
101 tmp[j] = m_ptsOutField->GetPointVal(j, i);
105 CalcW_NNeighbour(searchPt);
107 int progress = int(100 * i / nOutPts);
108 if (m_progressCallback && progress > lastProg)
110 m_progressCallback(i, nOutPts);
120 ASSERTL0(m_ptsInField->GetDim() == 1 || m_coordId >= 0,
126 if (m_ptsInField->GetDim() == 1)
131 for (
int i = 0; i < nOutPts; ++i)
134 for (
int j = 0; j < m_ptsOutField->GetDim(); ++j)
136 tmp[j] = m_ptsOutField->GetPointVal(j, i);
140 if (m_ptsInField->GetNpoints() <= 2)
142 CalcW_Linear(searchPt, m_coordId);
146 CalcW_Quadratic(searchPt, m_coordId);
149 int progress = int(100 * i / nOutPts);
150 if (m_progressCallback && progress > lastProg)
152 m_progressCallback(i, nOutPts);
162 int numPts = pow(
double(2), m_ptsInField->GetDim());
163 numPts = min(numPts,
int(m_ptsInField->GetNpoints() / 2));
168 for (
int i = 0; i < nOutPts; ++i)
171 for (
int j = 0; j < m_ptsOutField->GetDim(); ++j)
173 tmp[j] = m_ptsOutField->GetPointVal(j, i);
177 CalcW_Shepard(searchPt, numPts);
179 int progress = int(100 * i / nOutPts);
180 if (m_progressCallback && progress > lastProg)
182 m_progressCallback(i, nOutPts);
193 "No filter width set");
195 NekDouble sigma = m_filtWidth * 0.4246609001;
197 m_maxPts = min(m_maxPts,
int(m_ptsInField->GetNpoints() / 2));
202 for (
int i = 0; i < nOutPts; ++i)
205 for (
int j = 0; j < m_ptsOutField->GetDim(); ++j)
207 tmp[j] = m_ptsOutField->GetPointVal(j, i);
211 CalcW_Gauss(searchPt, sigma, m_maxPts);
213 int progress = int(100 * i / nOutPts);
214 if (m_progressCallback && progress > lastProg)
216 m_progressCallback(i, nOutPts);
225 ASSERTL0(
false,
"Invalid interpolation m_method");
243 ASSERTL0(ptsInField->GetNFields() == ptsOutField->GetNFields(),
244 "number of fields does not match");
245 ASSERTL0(ptsInField->GetDim() <= m_dim,
"too many dimesions in inField");
246 ASSERTL0(ptsOutField->GetDim() <= m_dim,
"too many dimesions in outField");
248 m_ptsInField = ptsInField;
249 m_ptsOutField = ptsOutField;
251 if (m_weights.GetRows() == 0)
253 CalcWeights(m_ptsInField, m_ptsOutField);
256 ASSERTL0(m_weights.GetRows() == m_ptsOutField->GetNpoints(),
257 "weights dimension mismatch");
259 int nFields = m_ptsOutField->GetNFields();
260 int nOutPts = m_ptsOutField->GetNpoints();
261 int inDim = m_ptsInField->GetDim();
264 for (
int i = 0; i < nFields; ++i)
266 for (
int j = 0; j < nOutPts; ++j)
268 int nPts = m_weights.GetColumns();
277 for (
int k = 0; k < nPts; ++k)
279 unsigned int nIdx = m_neighInds[j][k];
280 val += m_weights[j][k] *
281 m_ptsInField->GetPointVal(inDim + i, nIdx);
283 m_ptsOutField->SetPointVal(m_ptsOutField->GetDim() + i, j, val);
302 void Interpolator::Interpolate(
303 const vector<MultiRegions::ExpListSharedPtr> expInField,
304 vector<MultiRegions::ExpListSharedPtr> &expOutField,
307 ASSERTL0(expInField.size() == expOutField.size(),
308 "number of fields does not match");
309 ASSERTL0(expInField[0]->GetCoordim(0) <= m_dim,
310 "too many dimesions in inField");
311 ASSERTL0(expOutField[0]->GetCoordim(0) <= m_dim,
312 "too many dimesions in outField")
314 "only direct evaluation supported for this interpolation");
316 m_expInField = expInField;
317 m_expOutField = expOutField;
319 int nInDim = expInField[0]->GetCoordim(0);
320 int nOutPts = m_expOutField[0]->GetTotPoints();
321 int nOutDim = m_expOutField[0]->GetCoordim(0);
327 for (
int i = 0; i < nOutDim; ++i)
333 m_expOutField[0]->GetCoords(coords[0]);
335 else if (nOutDim == 2)
337 m_expOutField[0]->GetCoords(coords[0], coords[1]);
339 else if (nOutDim == 3)
341 m_expOutField[0]->GetCoords(coords[0], coords[1], coords[2]);
344 for (
int i = 0; i < nOutPts; ++i)
346 for (
int j = 0; j < nOutDim; ++j)
348 Scoords[j] = coords[j][i];
352 int elmtid = m_expInField[0]->GetExpIndex(Scoords, Lcoords,
357 int offset = m_expInField[0]->GetPhys_Offset(elmtid);
359 for (
int f = 0; f < m_expInField.size(); ++f)
362 m_expInField[f]->GetExp(elmtid)->StdPhysEvaluate(
363 Lcoords, m_expInField[f]->GetPhys() + offset);
365 if ((boost::math::isnan)(value))
367 ASSERTL0(
false,
"new value is not a number");
371 m_expOutField[f]->UpdatePhys()[i] = value;
377 for (
int f = 0; f < m_expInField.size(); ++f)
379 m_expOutField[f]->UpdatePhys()[i] = def_value;
383 int progress = int(100 * i / nOutPts);
384 if (m_progressCallback && progress > lastProg)
386 m_progressCallback(i, nOutPts);
403 void Interpolator::Interpolate(
404 const vector<MultiRegions::ExpListSharedPtr> expInField,
408 ASSERTL0(expInField.size() == ptsOutField->GetNFields(),
409 "number of fields does not match");
410 ASSERTL0(expInField[0]->GetCoordim(0) <= m_dim,
411 "too many dimesions in inField");
412 ASSERTL0(ptsOutField->GetDim() <= m_dim,
"too many dimesions in outField");
414 "only direct evaluation supported for this interpolation");
416 m_expInField = expInField;
417 m_ptsOutField = ptsOutField;
419 int nInDim = expInField[0]->GetCoordim(0);
420 int nOutPts = m_ptsOutField->GetNpoints();
423 for (
int i = 0; i < nOutPts; ++i)
427 for (
int j = 0; j < m_ptsOutField->GetDim(); ++j)
429 coords[j] = m_ptsOutField->GetPointVal(j, i);
433 int elmtid = m_expInField[0]->GetExpIndex(coords, Lcoords,
438 int offset = m_expInField[0]->GetPhys_Offset(elmtid);
440 for (
int f = 0; f < m_expInField.size(); ++f)
443 m_expInField[f]->GetExp(elmtid)->StdPhysEvaluate(
444 Lcoords, m_expInField[f]->GetPhys() + offset);
446 if ((boost::math::isnan)(value))
448 ASSERTL0(
false,
"new value is not a number");
452 m_ptsOutField->SetPointVal(m_ptsOutField->GetDim() + f, i,
459 for (
int f = 0; f < m_expInField.size(); ++f)
461 m_ptsOutField->SetPointVal(m_ptsOutField->GetDim() + f, i,
466 int progress = int(100 * i / nOutPts);
467 if (m_progressCallback && progress > lastProg)
469 m_progressCallback(i, nOutPts);
483 void Interpolator::Interpolate(
485 vector<MultiRegions::ExpListSharedPtr> &expOutField)
487 ASSERTL0(expOutField.size() == ptsInField->GetNFields(),
488 "number of fields does not match");
489 ASSERTL0(ptsInField->GetDim() <= m_dim,
"too many dimesions in inField");
490 ASSERTL0(expOutField[0]->GetCoordim(0) <= m_dim,
491 "too many dimesions in outField");
493 m_ptsInField = ptsInField;
494 m_expOutField = expOutField;
496 int nFields = max((
int)ptsInField->GetNFields(), (int)m_expOutField.size());
497 int nOutPts = m_expOutField[0]->GetTotPoints();
498 int outDim = m_expOutField[0]->GetCoordim(0);
502 for (
int i = 0; i < outDim; ++i)
508 m_expOutField[0]->GetCoords(pts[0]);
510 else if (outDim == 2)
512 m_expOutField[0]->GetCoords(pts[0], pts[1]);
514 else if (outDim == 3)
516 m_expOutField[0]->GetCoords(pts[0], pts[1], pts[2]);
521 for (
int f = 0; f < expOutField.size(); ++f)
523 tmpPts->AddField(m_expOutField[f]->GetCoeffs(),
524 m_ptsInField->GetFieldName(f));
528 Interpolate(m_ptsInField, tmpPts);
531 for (
int i = 0; i < nFields; i++)
533 for (
int j = 0; j < nOutPts; ++j)
535 m_expOutField[i]->UpdatePhys()[j] = tmpPts->GetPointVal(i, j);
540 int Interpolator::GetDim()
const
545 int Interpolator::GetCoordId()
const
567 return m_ptsOutField;
570 void Interpolator::PrintStatistics()
573 for (
int i = 0; i < m_neighInds.GetRows(); ++i)
575 for (
int j = 0; j < m_neighInds.GetColumns(); ++j)
577 if (m_neighInds[i][j] > 0)
584 cout <<
"Number of points: " << m_neighInds.GetRows() << endl;
585 cout <<
"mean Number of Neighbours per point: "
586 << meanN / m_neighInds.GetRows() << endl;
599 void Interpolator::CalcW_Gauss(
const PtsPoint &searchPt,
604 vector<PtsPoint> neighbourPts;
605 FindNeighbours(searchPt, neighbourPts, 4 * sigma, maxPts);
606 int numPts = neighbourPts.size();
615 m_neighInds[searchPt.
idx][0] = neighbourPts.front().idx;
616 m_weights[searchPt.
idx][0] = 1.0;
621 NekDouble sigmaNew = 0.25 * neighbourPts.back().dist;
623 for (
int i = 0; i < numPts; i++)
625 m_neighInds[searchPt.
idx][i] = neighbourPts.at(i).idx;
630 for (
int i = 0; i < numPts; ++i)
632 m_weights[searchPt.
idx][i] =
633 exp(-1 * pow(neighbourPts[i].dist,
double(2.0)) / ts2);
634 wSum += m_weights[searchPt.
idx][i];
637 for (
int i = 0; i < numPts; ++i)
639 m_weights[searchPt.
idx][i] = m_weights[searchPt.
idx][i] / wSum;
652 void Interpolator::CalcW_Linear(
const PtsPoint &searchPt,
int m_coordId)
654 int npts = m_ptsInField->GetNpoints();
659 for (i = 0; i < npts - 1; ++i)
661 if ((m_ptsInField->GetPointVal(0, i) <=
666 NekDouble pdiff = m_ptsInField->GetPointVal(0, i + 1) -
667 m_ptsInField->GetPointVal(0, i);
669 m_neighInds[searchPt.
idx][0] = i;
670 m_neighInds[searchPt.
idx][1] = i + 1;
672 m_weights[searchPt.
idx][0] =
673 (m_ptsInField->GetPointVal(0, i + 1) - coord) / pdiff;
674 m_weights[searchPt.
idx][1] =
675 (coord - m_ptsInField->GetPointVal(0, i)) / pdiff;
680 ASSERTL0(i != npts - 1,
"Failed to find coordinate " +
681 boost::lexical_cast<string>(coord) +
682 " within provided input points");
693 void Interpolator::CalcW_NNeighbour(
const PtsPoint &searchPt)
696 vector<PtsPoint> neighbourPts;
699 FindNNeighbours(searchPt, neighbourPts, 1);
701 m_neighInds[searchPt.
idx][0] = neighbourPts[0].idx;
702 m_weights[searchPt.
idx][0] = 1.0;
720 void Interpolator::CalcW_Shepard(
const PtsPoint &searchPt,
int numPts)
723 vector<PtsPoint> neighbourPts;
724 FindNNeighbours(searchPt, neighbourPts, numPts);
726 for (
int i = 0; i < neighbourPts.size(); i++)
728 m_neighInds[searchPt.
idx][i] = neighbourPts[i].idx;
733 for (
int i = 0; i < neighbourPts.size(); ++i)
737 m_weights[searchPt.
idx][i] = 1.0;
743 for (
int i = 0; i < neighbourPts.size(); ++i)
745 m_weights[searchPt.
idx][i] = 1 / pow(
double(neighbourPts[i].dist),
746 double(m_ptsInField->GetDim()));
747 wSum += m_weights[searchPt.
idx][i];
750 for (
int i = 0; i < neighbourPts.size(); ++i)
752 m_weights[searchPt.
idx][i] = m_weights[searchPt.
idx][i] / wSum;
767 void Interpolator::CalcW_Quadratic(
const PtsPoint &searchPt,
int m_coordId)
769 int npts = m_ptsInField->GetNpoints();
774 for (i = 0; i < npts - 1; ++i)
776 if ((m_ptsInField->GetPointVal(0, i) <=
781 NekDouble pdiff = m_ptsInField->GetPointVal(0, i + 1) -
782 m_ptsInField->GetPointVal(0, i);
788 NekDouble pdiff2 = m_ptsInField->GetPointVal(0, i + 2) -
789 m_ptsInField->GetPointVal(0, i + 1);
791 h1 = (m_ptsInField->GetPointVal(0, i + 1) - coord) *
792 (m_ptsInField->GetPointVal(0, i + 2) - coord) /
793 (pdiff * (pdiff + pdiff2));
794 h2 = (coord - m_ptsInField->GetPointVal(0, i)) *
795 (m_ptsInField->GetPointVal(0, i + 2) - coord) /
797 h3 = (coord - m_ptsInField->GetPointVal(0, i)) *
798 (coord - m_ptsInField->GetPointVal(0, i + 1)) /
799 ((pdiff + pdiff2) * pdiff2);
801 m_neighInds[searchPt.
idx][0] = i;
802 m_neighInds[searchPt.
idx][1] = i + 1;
803 m_neighInds[searchPt.
idx][2] = i + 2;
808 NekDouble pdiff2 = m_ptsInField->GetPointVal(0, i) -
809 m_ptsInField->GetPointVal(0, i - 1);
811 h1 = (m_ptsInField->GetPointVal(0, i + 1) - coord) *
812 (coord - m_ptsInField->GetPointVal(0, i - 1)) /
814 h2 = (coord - m_ptsInField->GetPointVal(0, i)) *
815 (coord - m_ptsInField->GetPointVal(0, i - 1)) /
816 (pdiff * (pdiff + pdiff2));
817 h3 = (m_ptsInField->GetPointVal(0, i) - coord) *
818 (m_ptsInField->GetPointVal(0, i + 1) - coord) /
819 ((pdiff + pdiff2) * pdiff);
821 m_neighInds[searchPt.
idx][0] = i;
822 m_neighInds[searchPt.
idx][1] = i + 1;
823 m_neighInds[searchPt.
idx][2] = i - 1;
826 m_weights[searchPt.
idx][0] = h1;
827 m_weights[searchPt.
idx][1] = h2;
828 m_weights[searchPt.
idx][2] = h3;
833 ASSERTL0(i != npts - 1,
"Failed to find coordinate " +
834 boost::lexical_cast<string>(coord) +
835 " within provided input points");
838 void Interpolator::SetupTree()
840 std::vector<PtsPointPair> inPoints;
841 for (
int i = 0; i < m_ptsInField->GetNpoints(); ++i)
844 for (
int j = 0; j < m_ptsInField->GetDim(); ++j)
846 coords[j] = m_ptsInField->GetPointVal(j, i);
852 m_rtree->insert(inPoints.begin(), inPoints.end());
856 it != inPoints.end(); ++it)
858 std::vector<PtsPointPair> result;
863 m_rtree->query(bgi::nearest((*it).first, 2),
864 std::back_inserter(result));
870 it2 != result.end(); ++it2)
872 if ((*it).second != (*it2).second &&
873 bg::distance((*it).first, (*it2).first) <=
876 m_rtree->remove(*it);
892 void Interpolator::FindNNeighbours(
const PtsPoint &searchPt,
893 vector<PtsPoint> &neighbourPts,
894 const unsigned int numPts)
896 std::vector<PtsPointPair> result;
899 m_rtree->query(bgi::nearest(searchBPoint, numPts),
900 std::back_inserter(result));
903 for (
int i = 0; i < result.size(); ++i)
905 int idx = result[i].second;
907 for (
int j = 0; j < m_ptsInField->GetDim(); ++j)
909 coords[j] = m_ptsInField->GetPointVal(j, idx);
911 NekDouble d = bg::distance(searchBPoint, result[i].first);
912 neighbourPts.push_back(
PtsPoint(idx, coords, d));
915 sort(neighbourPts.begin(), neighbourPts.end());
926 void Interpolator::FindNeighbours(
const PtsPoint &searchPt,
927 vector<PtsPoint> &neighbourPts,
929 const unsigned int maxPts)
934 searchPt.
coords[2] - dist);
936 searchPt.
coords[2] + dist);
937 bg::model::box<BPoint> bbox(bbMin, bbMax);
940 std::vector<PtsPointPair> result;
943 m_rtree->query(bgi::within(bbox) && bgi::nearest(searchBPoint, maxPts),
944 std::back_inserter(result));
948 m_rtree->query(bgi::within(bbox), std::back_inserter(result));
952 for (
int i = 0; i < result.size(); ++i)
954 int idx = result[i].second;
956 for (
int j = 0; j < m_ptsInField->GetDim(); ++j)
958 coords[j] = m_ptsInField->GetPointVal(j, idx);
960 NekDouble d = bg::distance(searchBPoint, result[i].first);
965 neighbourPts.push_back(
PtsPoint(idx, coords, d));
969 sort(neighbourPts.begin(), neighbourPts.end());
std::pair< BPoint, unsigned int > PtsPointPair
#define ASSERTL0(condition, msg)
General purpose memory allocation routines with the ability to allocate from thread specific memory p...
Array< OneD, NekDouble > coords
boost::geometry::model::point< NekDouble, m_dim, boost::geometry::cs::cartesian > BPoint
boost::shared_ptr< PtsField > PtsFieldSharedPtr
static const NekDouble kNekZeroTol
StandardMatrixTag boost::call_traits< LhsDataType >::const_reference rhs typedef NekMatrix< LhsDataType, StandardMatrixTag >::iterator iterator