Nektar++
Public Member Functions | Protected Attributes | List of all members
Nektar::FieldUtils::Interpolator< T > Class Template Reference

A class that contains algorithms for interpolation between pts fields, expansions and different meshes. More...

#include <Interpolator.h>

Inheritance diagram for Nektar::FieldUtils::Interpolator< T >:
[legend]

Public Member Functions

 Interpolator (LibUtilities::InterpMethod method=LibUtilities::eNoMethod, short int coordId=-1, NekDouble filtWidth=0.0, int maxPts=1000)
 Constructor of the Interpolator class. More...
 
FIELD_UTILS_EXPORT void Interpolate (const T expInField, T &expOutField, NekDouble def_value=0.0)
 Interpolate from an expansion to an expansion. More...
 
FIELD_UTILS_EXPORT void Interpolate (const T expInField, LibUtilities::PtsFieldSharedPtr &ptsOutField, NekDouble def_value=0.0)
 Interpolate from an expansion to a pts field. More...
 
FIELD_UTILS_EXPORT void Interpolate (const LibUtilities::PtsFieldSharedPtr ptsInField, T &expOutField)
 Interpolate from a pts field to an expansion. More...
 
FIELD_UTILS_EXPORT void Interpolate (const LibUtilities::PtsFieldSharedPtr ptsInField, LibUtilities::PtsFieldSharedPtr &ptsOutField)
 Interpolate from a pts field to a pts field. More...
 
FIELD_UTILS_EXPORT void InterpExp1ToExp2 (const T exp1, T &exp2)
 Interpolate from an expansion to an expansion. More...
 
- Public Member Functions inherited from Nektar::LibUtilities::Interpolator
 Interpolator (InterpMethod method=eNoMethod, short int coordId=-1, NekDouble filtWidth=0.0, int maxPts=1000)
 Constructor of the Interpolator class. More...
 
void CalcWeights (const LibUtilities::PtsFieldSharedPtr ptsInField, LibUtilities::PtsFieldSharedPtr &ptsOutField, bool reuseTree=false)
 Compute interpolation weights without doing any interpolation. More...
 
void Interpolate (const LibUtilities::PtsFieldSharedPtr ptsInField, LibUtilities::PtsFieldSharedPtr &ptsOutField)
 Interpolate from a pts field to a pts field. More...
 
int GetDim () const
 returns the dimension of the Interpolator. Should be higher than the dimensions of the interpolated fields More...
 
NekDouble GetFiltWidth () const
 Returns the filter width. More...
 
int GetCoordId () const
 Returns the coordinate id along which the interpolation should be performed. More...
 
InterpMethod GetInterpMethod () const
 Returns the interpolation method used by this interpolator. More...
 
LibUtilities::PtsFieldSharedPtr GetInField () const
 Returns the input field. More...
 
LibUtilities::PtsFieldSharedPtr GetOutField () const
 Returns the output field. More...
 
void PrintStatistics ()
 Returns if the weights have already been computed. More...
 
template<typename FuncPointerT , typename ObjectPointerT >
void SetProgressCallback (FuncPointerT func, ObjectPointerT obj)
 sets a callback funtion which gets called every time the interpolation progresses More...
 

Protected Attributes

m_expInField
 input field More...
 
m_expOutField
 output field More...
 
- Protected Attributes inherited from Nektar::LibUtilities::Interpolator
LibUtilities::PtsFieldSharedPtr m_ptsInField
 input field More...
 
LibUtilities::PtsFieldSharedPtr m_ptsOutField
 output field More...
 
std::function< void(const int position, const int goal)> m_progressCallback
 

Detailed Description

template<typename T>
class Nektar::FieldUtils::Interpolator< T >

A class that contains algorithms for interpolation between pts fields, expansions and different meshes.

Definition at line 50 of file FieldUtils/Interpolator.h.

Constructor & Destructor Documentation

◆ Interpolator()

template<typename T >
Nektar::FieldUtils::Interpolator< T >::Interpolator ( LibUtilities::InterpMethod  method = LibUtilities::eNoMethod,
short int  coordId = -1,
NekDouble  filtWidth = 0.0,
int  maxPts = 1000 
)
inline

Constructor of the Interpolator class.

Parameters
methodinterpolation method, defaults to a sensible value if not set
coordIdcoordinate id along which the interpolation should be performed
filtWidthfilter width, required by some algorithms such as eGauss
maxPtslimit number of considered points

if method is not specified, the best algorithm is chosen autpomatically.

If coordId is not specified, a full 1D/2D/3D interpolation is performed without collapsing any coordinate.

filtWidth must be specified for the eGauss algorithm only.

Definition at line 71 of file FieldUtils/Interpolator.h.

74  : LibUtilities::Interpolator(method, coordId, filtWidth, maxPts)
75  {
76  }

Member Function Documentation

◆ InterpExp1ToExp2()

template<typename T >
void Nektar::FieldUtils::Interpolator< T >::InterpExp1ToExp2 ( const T  exp1,
T &  exp2 
)

Interpolate from an expansion to an expansion.

Definition at line 347 of file FieldUtils/Interpolator.cpp.

348 {
349 
350  // Interpolation from exp1 -> exp2 assuming that exp1 and exp2 are the
351  // same explists, but at potentially different polynomial orders.
352  if (exp1.size() != exp2.size())
353  {
354  NEKERROR(ErrorUtil::efatal, "not the same mesh")
355  }
356 
357  for (int n = 0; n < exp1.size(); ++n)
358  {
359  // Interpolation from exp1 -> exp2 assuming that exp1 and exp2 are the
360  // same explists, but at potentially different polynomial orders.
361  if (exp1[n]->GetExpSize() != exp2[n]->GetExpSize())
362  {
363  NEKERROR(ErrorUtil::efatal, "not the same mesh")
364  }
365 
366  // If same polynomial orders, simply copy solution
367  if (exp1[n]->GetTotPoints() == exp2[n]->GetTotPoints())
368  {
369  Vmath::Vcopy(exp1[n]->GetTotPoints(), exp1[n]->GetPhys(), 1,
370  exp2[n]->UpdatePhys(), 1);
371  }
372  // If different polynomial orders, interpolate solution
373  else
374  {
375  // Transform solution from physical to coefficient space
376  exp1[n]->FwdTransLocalElmt(exp1[n]->GetPhys(),
377  exp1[n]->UpdateCoeffs());
378 
379  for (int i = 0; i < exp1[n]->GetExpSize(); ++i)
380  {
381  // Get the elements
382  LocalRegions::ExpansionSharedPtr elmt1 = exp1[n]->GetExp(i),
383  elmt2 = exp2[n]->GetExp(i);
384 
385  // Get the offset of elements in the storage arrays.
386  int offset1 = exp1[n]->GetCoeff_Offset(i);
387  int offset2 = exp2[n]->GetCoeff_Offset(i);
388 
389  // Get number of modes
390  Array<OneD, LibUtilities::BasisSharedPtr> base1 =
391  elmt1->GetBase();
392  std::vector<unsigned int> nummodes1(base1.size());
393  std::vector<LibUtilities::BasisType> btype1(base1.size());
394  for (int j = 0; j < nummodes1.size(); ++j)
395  {
396  nummodes1[j] = base1[j]->GetNumModes();
397  btype1[j] = base1[j]->GetBasisType();
398  }
399 
400  // Extract data from exp1 -> exp2.
401  elmt2->ExtractDataToCoeffs(
402  &exp1[n]->GetCoeffs()[offset1], nummodes1, 0,
403  &exp2[n]->UpdateCoeffs()[offset2], btype1);
404  }
405 
406  // Transform solution back to physical space
407  exp2[n]->BwdTrans(exp2[n]->GetCoeffs(), exp2[n]->UpdatePhys());
408  }
409  }
410 }
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:209
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:68
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1255

References NEKERROR, and Vmath::Vcopy().

◆ Interpolate() [1/4]

template<typename T >
void Nektar::FieldUtils::Interpolator< T >::Interpolate ( const LibUtilities::PtsFieldSharedPtr  ptsInField,
LibUtilities::PtsFieldSharedPtr ptsOutField 
)

Interpolate from a pts field to a pts field.

Definition at line 413 of file FieldUtils/Interpolator.cpp.

416 {
417  LibUtilities::Interpolator::Interpolate(ptsInField, ptsOutField);
418 }
void Interpolate(const LibUtilities::PtsFieldSharedPtr ptsInField, LibUtilities::PtsFieldSharedPtr &ptsOutField)
Interpolate from a pts field to a pts field.

◆ Interpolate() [2/4]

template<typename T >
void Nektar::FieldUtils::Interpolator< T >::Interpolate ( const LibUtilities::PtsFieldSharedPtr  ptsInField,
T &  expOutField 
)

Interpolate from a pts field to an expansion.

Parameters
ptsInFieldinput field
expOutFieldoutput field

In and output fields must have the same dimension and number of fields.

Definition at line 281 of file FieldUtils/Interpolator.cpp.

283 {
284  ASSERTL0(expOutField.size() == ptsInField->GetNFields(),
285  "number of fields does not match");
286  ASSERTL0(ptsInField->GetDim() <= GetDim(), "too many dimesions in inField");
287  ASSERTL0(expOutField[0]->GetCoordim(0) <= GetDim(),
288  "too many dimesions in outField");
289 
290  m_ptsInField = ptsInField;
291 
292  int nFields = max((int)ptsInField->GetNFields(), (int)expOutField.size());
293  int nOutPts = expOutField[0]->GetTotPoints();
294  int outNumHomDir = 0;
295  if (expOutField[0]->GetExpType() == MultiRegions::e3DH1D ||
296  expOutField[0]->GetExpType() == MultiRegions::e2DH1D)
297  {
298  outNumHomDir = 1;
299  }
300  else if (expOutField[0]->GetExpType() == MultiRegions::e3DH2D)
301  {
302  outNumHomDir = 2;
303  }
304  int outDim = expOutField[0]->GetCoordim(0) + outNumHomDir;
305 
306  // create intermediate Ptsfield that wraps the expOutField
307  Array<OneD, Array<OneD, NekDouble>> pts(outDim);
308  for (int i = 0; i < outDim; ++i)
309  {
310  pts[i] = Array<OneD, NekDouble>(nOutPts);
311  }
312  if (outDim == 1)
313  {
314  expOutField[0]->GetCoords(pts[0]);
315  }
316  else if (outDim == 2)
317  {
318  expOutField[0]->GetCoords(pts[0], pts[1]);
319  }
320  else if (outDim == 3)
321  {
322  expOutField[0]->GetCoords(pts[0], pts[1], pts[2]);
323  }
324 
327 
328  for (int f = 0; f < expOutField.size(); ++f)
329  {
330  tmpPts->AddField(expOutField[f]->GetPhys(),
331  m_ptsInField->GetFieldName(f));
332  }
333  // interpolate m_ptsInField to this intermediate field
335  // write the intermediate fields data into our expOutField
336  for (int i = 0; i < nFields; i++)
337  {
338  int ptsi = outDim + i;
339  for (int j = 0; j < nOutPts; ++j)
340  {
341  expOutField[i]->UpdatePhys()[j] = tmpPts->GetPointVal(ptsi, j);
342  }
343  }
344 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
int GetDim() const
returns the dimension of the Interpolator. Should be higher than the dimensions of the interpolated f...
LibUtilities::PtsFieldSharedPtr m_ptsInField
input field
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
std::shared_ptr< PtsField > PtsFieldSharedPtr
Definition: PtsField.h:190

References ASSERTL0, Nektar::MultiRegions::e2DH1D, Nektar::MultiRegions::e3DH1D, and Nektar::MultiRegions::e3DH2D.

◆ Interpolate() [3/4]

template<typename T >
void Nektar::FieldUtils::Interpolator< T >::Interpolate ( const T  expInField,
LibUtilities::PtsFieldSharedPtr ptsOutField,
NekDouble  def_value = 0.0 
)

Interpolate from an expansion to a pts field.

Parameters
expInFieldinput field
ptsOutFieldoutput field

In and output fields must have the same dimension and number of fields. Weights are currently not stored for later use. The interpolation is performed by evaluating the expInField at the points of ptsOutField, so only eNoMethod is supported.

Definition at line 140 of file FieldUtils/Interpolator.cpp.

143 {
144  ASSERTL0(expInField.size() == ptsOutField->GetNFields(),
145  "number of fields does not match");
146  ASSERTL0(expInField[0]->GetCoordim(0) <= GetDim(),
147  "too many dimesions in inField");
148  ASSERTL0(ptsOutField->GetDim() <= GetDim(),
149  "too many dimesions in outField");
150  ASSERTL0(ptsOutField->GetDim() >= expInField[0]->GetCoordim(0),
151  "too few dimesions in outField");
153  "only direct evaluation supported for this interpolation");
154  ASSERTL0(expInField[0]->GetExpType() != MultiRegions::e3DH2D,
155  "interpolation from 3DH2D expansion unsupported");
156 
157  m_ptsOutField = ptsOutField;
158 
159  int nInDim = expInField[0]->GetCoordim(0);
160  int nOutPts = m_ptsOutField->GetNpoints();
161  int lastProg = 0;
162 
163  int elmtid = -1;
164  for (int i = 0; i < nOutPts; ++i)
165  {
166  Array<OneD, NekDouble> Lcoords(nInDim, 0.0);
167  Array<OneD, NekDouble> coords(3, 0.0);
168  for (int j = 0; j < m_ptsOutField->GetDim(); ++j)
169  {
170  coords[j] = m_ptsOutField->GetPointVal(j, i);
171  }
172 
173  // Obtain Element and LocalCoordinate to interpolate.
174  elmtid = expInField[0]->GetExpIndex(
175  coords, Lcoords, NekConstants::kGeomFactorsTol, true, elmtid,
177 
178  // we use kGeomFactorsTol as tolerance, while StdPhysEvaluate has
179  // kNekZeroTol hardcoded, so we need to limit Lcoords to not produce
180  // a ton of warnings
181  for (int j = 0; j < nInDim; ++j)
182  {
183  Lcoords[j] = std::max(Lcoords[j], -1.0);
184  Lcoords[j] = std::min(Lcoords[j], 1.0);
185  }
186 
187  if (elmtid >= 0)
188  {
189  int offset = expInField[0]->GetPhys_Offset(elmtid);
190 
191  for (int f = 0; f < expInField.size(); ++f)
192  {
193  NekDouble value;
194 
195  if (expInField[f]->GetExpType() == MultiRegions::e3DH1D ||
196  expInField[f]->GetExpType() == MultiRegions::e2DH1D)
197  {
198  ASSERTL0(expInField[f]->GetWaveSpace(),
199  "interpolation from 3DH1D/2DH1D requires field in "
200  "wavespace");
201  NekDouble lHom = expInField[f]->GetHomoLen();
202  NekDouble BetaT =
203  2. * M_PI * fmod(coords[nInDim], lHom) / lHom;
204  int nPlanes =
205  expInField[f]->GetHomogeneousBasis()->GetZ().size();
206  NekDouble coeff = 0.;
207  Array<OneD, const unsigned int> planes =
208  expInField[f]->GetZIDs();
209  value = 0.;
210 
211  for (size_t n = 0; n < planes.size(); ++n)
212  {
213  auto planeExp = expInField[f]->GetPlane(planes[n]);
214  coeff = planeExp->GetExp(elmtid)->StdPhysEvaluate(
215  Lcoords, planeExp->GetPhys() + offset);
216 
217  if (planes[n] == 0)
218  {
219  value += coeff;
220  }
221  else if (planes[n] == 1)
222  {
223  value += cos(0.5 * nPlanes * BetaT) * coeff;
224  }
225  else if (planes[n] % 2 == 0)
226  {
227  NekDouble phase = (planes[n] >> 1) * BetaT;
228  value += cos(phase) * coeff;
229  }
230  else
231  {
232  NekDouble phase = (planes[n] >> 1) * BetaT;
233  value += -sin(phase) * coeff;
234  }
235  }
236  }
237  else
238  {
239  value = expInField[f]->GetExp(elmtid)->StdPhysEvaluate(
240  Lcoords, expInField[f]->GetPhys() + offset);
241  }
242 
243  if ((boost::math::isnan)(value))
244  {
245  ASSERTL0(false, "new value is not a number");
246  }
247  else
248  {
249  m_ptsOutField->SetPointVal(m_ptsOutField->GetDim() + f, i,
250  value);
251  }
252  }
253  }
254  else
255  {
256  for (int f = 0; f < expInField.size(); ++f)
257  {
258  m_ptsOutField->SetPointVal(m_ptsOutField->GetDim() + f, i,
259  def_value);
260  }
261  }
262 
263  int progress = int(100 * i / nOutPts);
264  if (m_progressCallback && progress > lastProg)
265  {
266  m_progressCallback(i, nOutPts);
267  lastProg = progress;
268  }
269  }
270 }
InterpMethod GetInterpMethod() const
Returns the interpolation method used by this interpolator.
std::function< void(const int position, const int goal)> m_progressCallback
LibUtilities::PtsFieldSharedPtr m_ptsOutField
output field
static const NekDouble kGeomFactorsTol
double NekDouble

References ASSERTL0, Nektar::MultiRegions::e2DH1D, Nektar::MultiRegions::e3DH1D, Nektar::MultiRegions::e3DH2D, Nektar::LibUtilities::eNoMethod, and Nektar::NekConstants::kGeomFactorsTol.

◆ Interpolate() [4/4]

template<typename T >
void Nektar::FieldUtils::Interpolator< T >::Interpolate ( const T  expInField,
T &  expOutField,
NekDouble  def_value = 0.0 
)

Interpolate from an expansion to an expansion.

Interpolate from one expansion to an other.

Parameters
expInFieldinput field
expOutFieldoutput field

In and output fields must have the same dimension and number of fields. Weights are currently not stored for later use. The interpolation is performed by evaluating the expInField at the quadrature points of expOutField, so only eNoMethod is supported. If both expansions use the same mesh, use LibUtilities/Foundations/Interp.h instead.

Definition at line 64 of file FieldUtils/Interpolator.cpp.

66 {
67  ASSERTL0(expInField.size() == expOutField.size(),
68  "number of fields does not match");
69  ASSERTL0(expInField[0]->GetCoordim(0) <= GetDim(),
70  "too many dimensions in inField");
71  ASSERTL0(expOutField[0]->GetCoordim(0) <= GetDim(),
72  "too many dimensions in outField");
74  "only direct evaluation supported for this interpolation");
75 
76  int nFields = max((int)expInField.size(), (int)expOutField.size());
77  int nOutPts = expOutField[0]->GetTotPoints();
78  int outNumHomDir = 0;
79  if (expOutField[0]->GetExpType() == MultiRegions::e3DH1D ||
80  expOutField[0]->GetExpType() == MultiRegions::e2DH1D)
81  {
82  outNumHomDir = 1;
83  }
84  else if (expOutField[0]->GetExpType() == MultiRegions::e3DH2D)
85  {
86  outNumHomDir = 2;
87  }
88  int outDim = expOutField[0]->GetCoordim(0) + outNumHomDir;
89 
90  // create intermediate Ptsfield that wraps the expOutField
91  Array<OneD, Array<OneD, NekDouble>> pts(outDim);
92  for (int i = 0; i < outDim; ++i)
93  {
94  pts[i] = Array<OneD, NekDouble>(nOutPts);
95  }
96  if (outDim == 1)
97  {
98  expOutField[0]->GetCoords(pts[0]);
99  }
100  else if (outDim == 2)
101  {
102  expOutField[0]->GetCoords(pts[0], pts[1]);
103  }
104  else if (outDim == 3)
105  {
106  expOutField[0]->GetCoords(pts[0], pts[1], pts[2]);
107  }
108 
111  for (int f = 0; f < expOutField.size(); ++f)
112  {
113  tmpPts->AddField(expOutField[f]->GetPhys(), "DefaultVar");
114  }
115  // interpolate m_ptsInField to this intermediate field
116  Interpolate(expInField, tmpPts, def_value);
117  // write the intermediate fields data into our expOutField
118  for (int i = 0; i < nFields; i++)
119  {
120  int ptsi = outDim + i;
121  for (int j = 0; j < nOutPts; ++j)
122  {
123  expOutField[i]->UpdatePhys()[j] = tmpPts->GetPointVal(ptsi, j);
124  }
125  }
126 }
FIELD_UTILS_EXPORT void Interpolate(const T expInField, T &expOutField, NekDouble def_value=0.0)
Interpolate from an expansion to an expansion.

References ASSERTL0, and Nektar::LibUtilities::eNoMethod.

Referenced by Nektar::SolverUtils::SessionFunction::EvaluatePts(), Nektar::FieldUtils::ProcessInterpPoints::InterpolateFieldToPts(), Nektar::FieldUtils::ProcessInterpPtsToPts::InterpolatePtsToPts(), Nektar::FieldUtils::ProcessInterpField::v_Process(), Nektar::FieldUtils::ProcessInterpPointDataToFld::v_Process(), and Nektar::FieldUtils::ProcessWallNormalData::v_Process().

Member Data Documentation

◆ m_expInField

template<typename T >
T Nektar::FieldUtils::Interpolator< T >::m_expInField
protected

input field

Definition at line 101 of file FieldUtils/Interpolator.h.

◆ m_expOutField

template<typename T >
T Nektar::FieldUtils::Interpolator< T >::m_expOutField
protected

output field

Definition at line 103 of file FieldUtils/Interpolator.h.