Nektar++
Public Member Functions | Static Public Member Functions | Static Public Attributes | Protected Member Functions | List of all members
Nektar::FieldUtils::ProcessEquiSpacedOutput Class Reference

This processing module interpolates one field to another. More...

#include <ProcessEquiSpacedOutput.h>

Inheritance diagram for Nektar::FieldUtils::ProcessEquiSpacedOutput:
[legend]

Public Member Functions

 ProcessEquiSpacedOutput (FieldSharedPtr f)
 
virtual ~ProcessEquiSpacedOutput ()
 
virtual void Process (po::variables_map &vm)
 Write mesh to output file. More...
 
virtual std::string GetModuleName ()
 
virtual std::string GetModuleDescription ()
 
virtual ModulePriority GetModulePriority ()
 
- Public Member Functions inherited from Nektar::FieldUtils::ProcessModule
 ProcessModule ()
 
 ProcessModule (FieldSharedPtr p_f)
 
- Public Member Functions inherited from Nektar::FieldUtils::Module
FIELD_UTILS_EXPORT Module (FieldSharedPtr p_f)
 
FIELD_UTILS_EXPORT void RegisterConfig (std::string key, std::string value="")
 Register a configuration option with a module. More...
 
FIELD_UTILS_EXPORT void PrintConfig ()
 Print out all configuration options for a module. More...
 
FIELD_UTILS_EXPORT void SetDefaults ()
 Sets default configuration options for those which have not been set. More...
 
FIELD_UTILS_EXPORT void EvaluateTriFieldAtEquiSpacedPts (LocalRegions::ExpansionSharedPtr &exp, const Array< OneD, const NekDouble > &infield, Array< OneD, NekDouble > &outfield)
 

Static Public Member Functions

static std::shared_ptr< Modulecreate (FieldSharedPtr f)
 Creates an instance of this class. More...
 

Static Public Attributes

static ModuleKey className
 

Protected Member Functions

void SetHomogeneousConnectivity (void)
 
void GenOrthoModes (int n, const Array< OneD, const NekDouble > &phys, Array< OneD, NekDouble > &coeffs)
 
- Protected Member Functions inherited from Nektar::FieldUtils::Module
 Module ()
 

Additional Inherited Members

- Protected Attributes inherited from Nektar::FieldUtils::Module
FieldSharedPtr m_f
 Field object. More...
 
std::map< std::string, ConfigOptionm_config
 List of configuration values. More...
 

Detailed Description

This processing module interpolates one field to another.

Definition at line 48 of file ProcessEquiSpacedOutput.h.

Constructor & Destructor Documentation

◆ ProcessEquiSpacedOutput()

Nektar::FieldUtils::ProcessEquiSpacedOutput::ProcessEquiSpacedOutput ( FieldSharedPtr  f)

Definition at line 60 of file ProcessEquiSpacedOutput.cpp.

References Nektar::FieldUtils::Module::m_config.

61  : ProcessModule(f)
62 {
63  m_config["tetonly"] =
64  ConfigOption(true, "0", "Only process tetrahedral elements");
65 
66  m_config["modalenergy"] =
67  ConfigOption(true, "0", "Write output as modal energy");
68 }
std::map< std::string, ConfigOption > m_config
List of configuration values.

◆ ~ProcessEquiSpacedOutput()

Nektar::FieldUtils::ProcessEquiSpacedOutput::~ProcessEquiSpacedOutput ( )
virtual

Definition at line 70 of file ProcessEquiSpacedOutput.cpp.

71 {
72 }

Member Function Documentation

◆ create()

static std::shared_ptr<Module> Nektar::FieldUtils::ProcessEquiSpacedOutput::create ( FieldSharedPtr  f)
inlinestatic

Creates an instance of this class.

Definition at line 52 of file ProcessEquiSpacedOutput.h.

References Nektar::MemoryManager< DataType >::AllocateSharedPtr().

53  {
55  }
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.

◆ GenOrthoModes()

void Nektar::FieldUtils::ProcessEquiSpacedOutput::GenOrthoModes ( int  n,
const Array< OneD, const NekDouble > &  phys,
Array< OneD, NekDouble > &  coeffs 
)
protected

Definition at line 806 of file ProcessEquiSpacedOutput.cpp.

References ASSERTL0, Nektar::LibUtilities::eOrtho_A, Nektar::LibUtilities::eOrtho_B, Nektar::LibUtilities::eQuadrilateral, Nektar::LibUtilities::eTriangle, Nektar::StdRegions::StdExpansion::FwdTrans(), Nektar::LibUtilities::Interp2D(), and Nektar::FieldUtils::Module::m_f.

Referenced by GetModulePriority(), and Process().

810 {
812  e = m_f->m_exp[0]->GetExp(n);
813 
814  switch (e->DetShapeType())
815  {
817  {
818  int np0 = e->GetBasis(0)->GetNumPoints();
819  int np1 = e->GetBasis(1)->GetNumPoints();
820  int np = max(np0, np1);
821 
822  // to ensure points are correctly projected to np need
823  // to increase the order slightly of coordinates
824  LibUtilities::PointsKey pa(np + 1, e->GetPointsType(0));
825  LibUtilities::PointsKey pb(np, e->GetPointsType(1));
826  Array<OneD, NekDouble> tophys(np * (np + 1));
827 
828  LibUtilities::BasisKey Ba(LibUtilities::eOrtho_A, np, pa);
829  LibUtilities::BasisKey Bb(LibUtilities::eOrtho_B, np, pb);
830  StdRegions::StdTriExp OrthoExp(Ba, Bb);
831 
832  // interpolate points to new phys points!
833  LibUtilities::Interp2D(e->GetBasis(0)->GetBasisKey(),
834  e->GetBasis(1)->GetBasisKey(), phys, Ba, Bb,
835  tophys);
836 
837  OrthoExp.FwdTrans(tophys, coeffs);
838  break;
839  }
841  {
842  int np0 = e->GetBasis(0)->GetNumPoints();
843  int np1 = e->GetBasis(1)->GetNumPoints();
844  int np = max(np0, np1);
845 
846  LibUtilities::PointsKey pa(np + 1, e->GetPointsType(0));
847  LibUtilities::PointsKey pb(np + 1, e->GetPointsType(1));
848  Array<OneD, NekDouble> tophys((np + 1) * (np + 1));
849 
850  LibUtilities::BasisKey Ba(LibUtilities::eOrtho_A, np, pa);
851  LibUtilities::BasisKey Bb(LibUtilities::eOrtho_A, np, pb);
852  StdRegions::StdQuadExp OrthoExp(Ba, Bb);
853 
854  // interpolate points to new phys points!
855  LibUtilities::Interp2D(e->GetBasis(0)->GetBasisKey(),
856  e->GetBasis(1)->GetBasisKey(), phys, Ba, Bb,
857  tophys);
858 
859  OrthoExp.FwdTrans(phys, coeffs);
860  break;
861  }
862  default:
863  ASSERTL0(false, "Shape needs setting up");
864  break;
865  }
866 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
Principle Orthogonal Functions .
Definition: BasisType.h:46
void Interp2D(const BasisKey &fbasis0, const BasisKey &fbasis1, const Array< OneD, const NekDouble > &from, const BasisKey &tbasis0, const BasisKey &tbasis1, Array< OneD, NekDouble > &to)
this function interpolates a 2D function evaluated at the quadrature points of the 2D basis...
Definition: Interp.cpp:115
Principle Orthogonal Functions .
Definition: BasisType.h:45
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:65
FieldSharedPtr m_f
Field object.

◆ GetModuleDescription()

virtual std::string Nektar::FieldUtils::ProcessEquiSpacedOutput::GetModuleDescription ( )
inlinevirtual

Reimplemented from Nektar::FieldUtils::Module.

Definition at line 69 of file ProcessEquiSpacedOutput.h.

70  {
71  return "Interpolating fields to equispaced";
72  }

◆ GetModuleName()

virtual std::string Nektar::FieldUtils::ProcessEquiSpacedOutput::GetModuleName ( )
inlinevirtual

Implements Nektar::FieldUtils::Module.

Definition at line 64 of file ProcessEquiSpacedOutput.h.

65  {
66  return "ProcessEquiSpacedOutput";
67  }

◆ GetModulePriority()

virtual ModulePriority Nektar::FieldUtils::ProcessEquiSpacedOutput::GetModulePriority ( )
inlinevirtual

◆ Process()

void Nektar::FieldUtils::ProcessEquiSpacedOutput::Process ( po::variables_map &  vm)
virtual

Write mesh to output file.

Implements Nektar::FieldUtils::Module.

Definition at line 74 of file ProcessEquiSpacedOutput.cpp.

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), ASSERTL0, Nektar::StdRegions::eBwd, Nektar::StdRegions::eDir1BwdDir1_Dir2BwdDir2, Nektar::StdRegions::eDir1BwdDir1_Dir2FwdDir2, Nektar::StdRegions::eDir1BwdDir2_Dir2BwdDir1, Nektar::StdRegions::eDir1BwdDir2_Dir2FwdDir1, Nektar::StdRegions::eFwd, Nektar::LibUtilities::eHexahedron, Nektar::LibUtilities::ePrism, Nektar::LibUtilities::ePtsSegBlock, Nektar::LibUtilities::ePtsTetBlock, Nektar::LibUtilities::ePtsTriBlock, Nektar::LibUtilities::ePyramid, Nektar::LibUtilities::eQuadrilateral, Nektar::LibUtilities::eSegment, Nektar::LibUtilities::eTetrahedron, Nektar::LibUtilities::eTriangle, GenOrthoModes(), Nektar::LibUtilities::StdSegData::getNumberOfCoefficients(), Nektar::LibUtilities::StdTriData::getNumberOfCoefficients(), Nektar::LibUtilities::StdQuadData::getNumberOfCoefficients(), Nektar::LibUtilities::StdHexData::getNumberOfCoefficients(), Nektar::LibUtilities::StdTetData::getNumberOfCoefficients(), Nektar::LibUtilities::StdPyrData::getNumberOfCoefficients(), Nektar::LibUtilities::StdPrismData::getNumberOfCoefficients(), Nektar::FieldUtils::Module::m_config, Nektar::FieldUtils::Module::m_f, Nektar::NullNekDouble1DArray, and SetHomogeneousConnectivity().

75 {
76  boost::ignore_unused(vm);
77 
78  int nel = m_f->m_exp[0]->GetExpSize();
79  if (!nel)
80  {
81  // Create empty PtsField
82  int nfields = m_f->m_variables.size();
83  int coordim = 3;
84 
85  Array<OneD, Array<OneD, NekDouble> > pts(nfields + coordim);
86  for (int i = 0; i < nfields + coordim; ++i)
87  {
88  pts[i] = Array<OneD, NekDouble>(0);
89  }
90  vector<Array<OneD, int> > ptsConn;
91 
92  m_f->m_fieldPts =
94  coordim, m_f->m_variables, pts);
95  m_f->m_fieldPts->SetPtsType(LibUtilities::ePtsTetBlock);
96  m_f->m_fieldPts->SetConnectivity(ptsConn);
97  return;
98  }
99 
100  int coordim = m_f->m_exp[0]->GetCoordim(0);
101  int shapedim = m_f->m_exp[0]->GetExp(0)->GetShapeDimension();
102  int npts = m_f->m_exp[0]->GetTotPoints();
103  Array<OneD, Array<OneD, NekDouble> > coords(3);
104 
105  // Check if we have a homogeneous expansion
106  bool homogeneous1D = false;
107  if (m_f->m_numHomogeneousDir == 1)
108  {
109  coordim++;
110  shapedim++;
111  homogeneous1D = true;
112  }
113  else if (m_f->m_numHomogeneousDir == 2)
114  {
115  ASSERTL0(false, "Homegeneous2D case not supported");
116  }
117 
118  // set up the number of points in each element
119  int newpoints = 0;
120  int newtotpoints = 0;
121 
122  Array<OneD, int> conn;
123  int prevNcoeffs = 0;
124  int prevNpoints = 0;
125  int cnt = 0;
126 
127  // identify face 1 connectivity for prisms
128  map<int, StdRegions::Orientation> face0orient;
129  set<int> prismorient;
131 
132  // prepare PtsField
133  vector<int> ppe;
134  vector<Array<OneD, int> > ptsConn;
135  int nfields;
136 
137  for (int i = 0; i < nel; ++i)
138  {
139  e = m_f->m_exp[0]->GetExp(i);
140  if (e->DetShapeType() == LibUtilities::ePrism)
141  {
142  StdRegions::Orientation forient = e->GetForient(0);
143  int fid = e->GetGeom()->GetFid(0);
144  if (face0orient.count(fid))
145  { // face 1 meeting face 1 so reverse this id
146  prismorient.insert(i);
147  }
148  else
149  {
150  // just store if Dir 1 is fwd or bwd
151  if ((forient == StdRegions::eDir1BwdDir1_Dir2FwdDir2) ||
155  {
156  face0orient[fid] = StdRegions::eBwd;
157  }
158  else
159  {
160  face0orient[fid] = StdRegions::eFwd;
161  }
162  }
163  }
164  }
165 
166  for (int i = 0; i < nel; ++i)
167  {
168  e = m_f->m_exp[0]->GetExp(i);
169  if (e->DetShapeType() == LibUtilities::ePrism)
170  {
171  int fid = e->GetGeom()->GetFid(2);
172  // check to see if face 2 meets face 1
173  if (face0orient.count(fid))
174  {
175  // check to see how face 2 is orientated
176  StdRegions::Orientation forient2 = e->GetForient(2);
177  StdRegions::Orientation forient0 = face0orient[fid];
178 
179  // If dir 1 or forient2 is bwd then check agains
180  // face 1 value
181  if ((forient2 == StdRegions::eDir1BwdDir1_Dir2FwdDir2) ||
182  (forient2 == StdRegions::eDir1BwdDir1_Dir2BwdDir2) ||
183  (forient2 == StdRegions::eDir1BwdDir2_Dir2FwdDir1) ||
185  {
186  if (forient0 == StdRegions::eFwd)
187  {
188  prismorient.insert(i);
189  }
190  }
191  else
192  {
193  if (forient0 == StdRegions::eBwd)
194  {
195  prismorient.insert(i);
196  }
197  }
198  }
199  }
200  }
201 
202  for (int i = 0; i < nel; ++i)
203  {
204  e = m_f->m_exp[0]->GetExp(i);
205  if (m_config["tetonly"].as<bool>())
206  {
207  if (m_f->m_exp[0]->GetExp(i)->DetShapeType() !=
209  {
210  continue;
211  }
212  }
213 
214  switch (e->DetShapeType())
215  {
217  {
218  int npoints0 = e->GetBasis(0)->GetNumPoints();
219 
220  newpoints =
222  }
223  break;
225  {
226  int np0 = e->GetBasis(0)->GetNumPoints();
227  int np1 = e->GetBasis(1)->GetNumPoints();
228  int np = max(np0, np1);
229  newpoints =
231  }
232  break;
234  {
235  int np0 = e->GetBasis(0)->GetNumPoints();
236  int np1 = e->GetBasis(1)->GetNumPoints();
237  int np = max(np0, np1);
238 
239  newpoints =
241  }
242  break;
244  {
245  int np0 = e->GetBasis(0)->GetNumPoints();
246  int np1 = e->GetBasis(1)->GetNumPoints();
247  int np2 = e->GetBasis(2)->GetNumPoints();
248  int np = max(np0, max(np1, np2));
249 
251  np, np, np);
252  }
253  break;
255  {
256  int np0 = e->GetBasis(0)->GetNumPoints();
257  int np1 = e->GetBasis(1)->GetNumPoints();
258  int np2 = e->GetBasis(2)->GetNumPoints();
259  int np = max(np0, max(np1, np2));
260 
262  np, np, np);
263  }
264  break;
266  {
267  int np0 = e->GetBasis(0)->GetNumPoints();
268  int np1 = e->GetBasis(1)->GetNumPoints();
269  int np2 = e->GetBasis(2)->GetNumPoints();
270  int np = max(np0, max(np1, np2));
271 
273  np, np, np);
274  }
275  break;
277  {
278  int np0 = e->GetBasis(0)->GetNumPoints();
279  int np1 = e->GetBasis(1)->GetNumPoints();
280  int np2 = e->GetBasis(2)->GetNumPoints();
281  int np = max(np0, max(np1, np2));
282 
284  np, np, np);
285  }
286  break;
287  default:
288  {
289  ASSERTL0(false, "Points not known");
290  }
291  }
292 
293  ppe.push_back(newpoints);
294  newtotpoints += newpoints;
295 
296  if (e->DetShapeType() == LibUtilities::ePrism)
297  {
298  bool standard = true;
299 
300  if (prismorient.count(i))
301  {
302  standard = false; // reverse direction
303  }
304 
305  e->GetSimplexEquiSpacedConnectivity(conn, standard);
306  }
307  else
308  {
309 
310  if ((prevNcoeffs != e->GetNcoeffs()) ||
311  (prevNpoints != e->GetTotPoints()))
312  {
313  prevNcoeffs = e->GetNcoeffs();
314  prevNpoints = e->GetTotPoints();
315 
316  e->GetSimplexEquiSpacedConnectivity(conn);
317  }
318  }
319  Array<OneD, int> newconn(conn.num_elements());
320  for (int j = 0; j < conn.num_elements(); ++j)
321  {
322  newconn[j] = conn[j] + cnt;
323  }
324 
325  ptsConn.push_back(newconn);
326  cnt += newpoints;
327  }
328 
329  nfields = m_f->m_variables.size();
330 
331  Array<OneD, Array<OneD, NekDouble> > pts(nfields + coordim);
332 
333  for (int i = 0; i < nfields + coordim; ++i)
334  {
335  pts[i] = Array<OneD, NekDouble>(newtotpoints);
336  }
337 
338  // Interpolate coordinates
339  for (int i = 0; i < coordim; ++i)
340  {
341  coords[i] = Array<OneD, NekDouble>(npts);
342  }
343 
344  for (int i = coordim; i < 3; ++i)
345  {
346  coords[i] = NullNekDouble1DArray;
347  }
348 
349  m_f->m_exp[0]->GetCoords(coords[0], coords[1], coords[2]);
350 
351  Array<OneD, NekDouble> tmp;
352 
353  for (int n = 0; n < coordim; ++n)
354  {
355  cnt = 0;
356  int cnt1 = 0;
357  for (int i = 0; i < nel; ++i)
358  {
359  m_f->m_exp[0]->GetExp(i)->PhysInterpToSimplexEquiSpaced(
360  coords[n] + cnt, tmp = pts[n] + cnt1);
361  cnt1 += ppe[i];
362  cnt += m_f->m_exp[0]->GetExp(i)->GetTotPoints();
363  }
364  }
365 
366  for (int n = 0; n < m_f->m_variables.size(); ++n)
367  {
368  cnt = 0;
369  int cnt1 = 0;
370 
371  if (m_config["modalenergy"].as<bool>())
372  {
373  Array<OneD, const NekDouble> phys = m_f->m_exp[n]->GetPhys();
374  for (int i = 0; i < nel; ++i)
375  {
376  GenOrthoModes(i, phys + cnt, tmp = pts[coordim + n] + cnt1);
377  cnt1 += ppe[i];
378  cnt += m_f->m_exp[0]->GetExp(i)->GetTotPoints();
379  }
380  }
381  else
382  {
383  Array<OneD, const NekDouble> phys = m_f->m_exp[n]->GetPhys();
384  for (int i = 0; i < nel; ++i)
385  {
386  m_f->m_exp[0]->GetExp(i)->PhysInterpToSimplexEquiSpaced(
387  phys + cnt, tmp = pts[coordim + n] + cnt1);
388  cnt1 += ppe[i];
389  cnt += m_f->m_exp[0]->GetExp(i)->GetTotPoints();
390  }
391  }
392  }
393 
395  coordim, m_f->m_variables, pts);
396  if (shapedim == 1)
397  {
398  m_f->m_fieldPts->SetPtsType(LibUtilities::ePtsSegBlock);
399  }
400 
401  if (shapedim == 2)
402  {
403  m_f->m_fieldPts->SetPtsType(LibUtilities::ePtsTriBlock);
404  }
405  else if (shapedim == 3)
406  {
407  m_f->m_fieldPts->SetPtsType(LibUtilities::ePtsTetBlock);
408  }
409  m_f->m_fieldPts->SetConnectivity(ptsConn);
410  if (homogeneous1D)
411  {
413  }
414 
415  // Clear m_exp
416  m_f->m_exp = vector<MultiRegions::ExpListSharedPtr>();
417 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
int getNumberOfCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:287
std::map< std::string, ConfigOption > m_config
List of configuration values.
static Array< OneD, NekDouble > NullNekDouble1DArray
int getNumberOfCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:194
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
int getNumberOfCoefficients(int Na, int Nb)
Definition: ShapeType.hpp:113
void GenOrthoModes(int n, const Array< OneD, const NekDouble > &phys, Array< OneD, NekDouble > &coeffs)
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:65
int getNumberOfCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:240
int getNumberOfCoefficients(int Na, int Nb)
Definition: ShapeType.hpp:137
int getNumberOfCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:159
FieldSharedPtr m_f
Field object.

◆ SetHomogeneousConnectivity()

void Nektar::FieldUtils::ProcessEquiSpacedOutput::SetHomogeneousConnectivity ( void  )
protected

Definition at line 419 of file ProcessEquiSpacedOutput.cpp.

References ASSERTL0, Nektar::StdRegions::eForwards, Nektar::LibUtilities::eFourier, Nektar::LibUtilities::eFourierEvenlySpaced, Nektar::LibUtilities::ePtsTetBlock, Nektar::LibUtilities::ePtsTriBlock, Nektar::LibUtilities::eQuadrilateral, Nektar::LibUtilities::eTriangle, Nektar::LibUtilities::StdTriData::getNumberOfCoefficients(), Nektar::LibUtilities::StdQuadData::getNumberOfCoefficients(), Nektar::FieldUtils::Module::m_f, CellMLToNektar.cellml_metadata::p, Vmath::Sadd(), and Vmath::Vcopy().

Referenced by GetModulePriority(), and Process().

420 {
422  int nel = m_f->m_exp[0]->GetPlane(0)->GetExpSize();
423  int nPlanes = m_f->m_exp[0]->GetZIDs().num_elements();
424  int npts = m_f->m_fieldPts->GetNpoints();
425  int nptsPerPlane = npts / nPlanes;
426  int coordim = 3;
427 
428  if (m_f->m_exp[0]->GetHomogeneousBasis()->GetBasisType() ==
430  m_f->m_exp[0]->GetHomogeneousBasis()->GetPointsType() ==
432  {
433  // Write points with extra plane
434  Array<OneD, Array<OneD, NekDouble> > pts;
435  m_f->m_fieldPts->GetPts(pts);
436  Array<OneD, Array<OneD, NekDouble> > newPts(pts.num_elements());
437  for (int i = 0; i < pts.num_elements(); i++)
438  {
439  newPts[i] = Array<OneD, NekDouble>(npts + nptsPerPlane);
440  // Copy old points
441  Vmath::Vcopy(npts, pts[i], 1, newPts[i], 1);
442  // Get new plane
443  Array<OneD, NekDouble> extraPlane(nptsPerPlane, newPts[i] + npts);
444  if (m_f->m_comm->GetColumnComm()->GetSize() == 1)
445  {
446  if ( i == (coordim-1))
447  {
448  // z-coordinate
449  Vmath::Sadd(nptsPerPlane, m_f->m_exp[0]->GetHomoLen(),
450  pts[i], 1, extraPlane, 1);
451  }
452  else
453  {
454  Vmath::Vcopy(nptsPerPlane, pts[i], 1, extraPlane, 1);
455  }
456  }
457  else
458  {
459  // Determine to and from rank for communication
460  int size = m_f->m_comm->GetColumnComm()->GetSize();
461  int rank = m_f->m_comm->GetColumnComm()->GetRank();
462  int fromRank = (rank + 1) % size;
463  int toRank = (rank == 0) ? size - 1 : rank - 1;
464  // Communicate using SendRecv
465  Array<OneD, NekDouble> send(nptsPerPlane, pts[i]);
466  m_f->m_comm->GetColumnComm()->SendRecv(toRank, send, fromRank,
467  extraPlane);
468  // Adjust z-coordinate of last process
469  if (i == (coordim-1) && (rank == size - 1) )
470  {
471  Vmath::Sadd(nptsPerPlane, m_f->m_exp[0]->GetHomoLen(),
472  extraPlane, 1, extraPlane, 1);
473  }
474  }
475  }
476  m_f->m_fieldPts->SetPts(newPts);
477  // Now extend plane connectivity
478  vector<Array<OneD, int> > oldConn;
479  Array<OneD, int> conn;
480  m_f->m_fieldPts->GetConnectivity(oldConn);
481  vector<Array<OneD, int> > newConn = oldConn;
482  int connPerPlane = oldConn.size() / nPlanes;
483  for (int i = 0; i < connPerPlane; i++)
484  {
485  conn = Array<OneD, int>(oldConn[i].num_elements());
486  for (int j = 0; j < conn.num_elements(); j++)
487  {
488  conn[j] = oldConn[i][j] + npts;
489  }
490  newConn.push_back(conn);
491  }
492  m_f->m_fieldPts->SetConnectivity(newConn);
493 
494  nPlanes++;
495  npts += nptsPerPlane;
496  }
497 
498  vector<Array<OneD, int> > oldConn;
499  vector<Array<OneD, int> > newConn;
500  Array<OneD, int> conn;
501  m_f->m_fieldPts->GetConnectivity(oldConn);
502 
503  // 2DH1D case
504  if (m_f->m_fieldPts->GetPtsType() == LibUtilities::ePtsTriBlock)
505  {
506  for(int i = 0; i < nel; ++i)
507  {
508  int nLines = oldConn[i].num_elements()/2;
509  // Create array for new connectivity
510  // (2 triangles between each plane for each line)
511  conn = Array<OneD, int> (2*3*nLines*(nPlanes-1));
512  int cnt = 0;
513  for(int n = 0; n<nLines; n++)
514  {
515  // Define new connectivity with triangles
516  for ( int p = 0; p<nPlanes-1; p++)
517  {
518  conn[cnt++] = oldConn[i+ p *nel][2*n+0];
519  conn[cnt++] = oldConn[i+ p *nel][2*n+1];
520  conn[cnt++] = oldConn[i+(p+1)*nel][2*n+0];
521 
522  conn[cnt++] = oldConn[i+ p *nel][2*n+1];
523  conn[cnt++] = oldConn[i+(p+1)*nel][2*n+0];
524  conn[cnt++] = oldConn[i+(p+1)*nel][2*n+1];
525  }
526  }
527  newConn.push_back(conn);
528  }
529  }
530  else if(m_f->m_fieldPts->GetPtsType() == LibUtilities::ePtsTetBlock)
531  {
532  // Get maximum number of points per direction in the mesh
533  int maxN = 0;
534  for(int i = 0; i < nel; ++i)
535  {
536  e = m_f->m_exp[0]->GetPlane(0)->GetExp(i);
537 
538  int np0 = e->GetBasis(0)->GetNumPoints();
539  int np1 = e->GetBasis(1)->GetNumPoints();
540  int np = max(np0,np1);
541  maxN = max(np, maxN);
542  }
543 
544  // Create a global numbering for points in plane 0
545  Array<OneD, int> vId(nptsPerPlane);
546  int cnt1=0;
547  int cnt2=0;
548  for(int i = 0; i < nel; ++i)
549  {
550  e = m_f->m_exp[0]->GetPlane(0)->GetExp(i);
551  int np0 = e->GetBasis(0)->GetNumPoints();
552  int np1 = e->GetBasis(1)->GetNumPoints();
553  int np = max(np0,np1);
554  switch(e->DetShapeType())
555  {
557  {
558  int newpoints = LibUtilities::StdTriData::
560 
561  // Vertex numbering
562  vId[cnt1] = e->GetGeom()->GetVid(0);
563  vId[cnt1+np-1] = e->GetGeom()->GetVid(1);
564  vId[cnt1+newpoints-1] = e->GetGeom()->GetVid(2);
565 
566  // Edge numbering
567  StdRegions::Orientation edgeOrient;
568  int edge1 = 0;
569  int edge2 = 0;
570  for (int n = 1; n < np-1; n++)
571  {
572  // Edge 0
573  edgeOrient = e->GetGeom()->GetEorient(0);
574  if (edgeOrient==StdRegions::eForwards)
575  {
576  vId[cnt1+n] = 4*nel +
577  maxN*e->GetGeom()->GetEid(0) + n;
578  }
579  else
580  {
581  vId[cnt1+np-1-n] = 4*nel +
582  maxN*e->GetGeom()->GetEid(0) + n;
583  }
584 
585  // Edge 1
586  edgeOrient = e->GetGeom()->GetEorient(1);
587  if (edgeOrient==StdRegions::eForwards)
588  {
589  edge1 += np-n;
590  vId[cnt1+np-1+edge1] = 4*nel +
591  maxN*e->GetGeom()->GetEid(1) + n;
592  }
593  else
594  {
595  edge1 += n;
596  vId[cnt1+newpoints-1-edge1] = 4*nel +
597  maxN*e->GetGeom()->GetEid(1) + n;
598  }
599 
600  // Edge 2
601  edgeOrient = e->GetGeom()->GetEorient(2);
602  if (edgeOrient==StdRegions::eForwards)
603  {
604  edge2 += n+1;
605  vId[cnt1+newpoints-1-edge2] = 4*nel +
606  maxN*e->GetGeom()->GetEid(2) + n;
607  }
608  else
609  {
610  edge2 += np+1-n;
611  vId[cnt1+edge2] = 4*nel +
612  maxN*e->GetGeom()->GetEid(2) + n;
613  }
614  }
615 
616  // Interior numbering
617  edge2 = 0;
618  for (int n = 1; n < np-1; n++)
619  {
620  edge2 += np+1-n;
621  for (int m = 1; m < np-n-1; m++)
622  {
623  vId[cnt1+edge2+m] = 4*nel + maxN*4*nel + cnt2;
624  cnt2++;
625  }
626  }
627  cnt1+= newpoints;
628  }
629  break;
631  {
632  int newpoints = LibUtilities::StdQuadData::
634  // Vertex numbering
635  vId[cnt1] = e->GetGeom()->GetVid(0);
636  vId[cnt1+np-1] = e->GetGeom()->GetVid(1);
637  vId[cnt1+np*np-1] = e->GetGeom()->GetVid(2);
638  vId[cnt1+np*(np-1)] = e->GetGeom()->GetVid(3);
639 
640  // Edge numbering
641  StdRegions::Orientation edgeOrient;
642  for (int n = 1; n < np-1; n++)
643  {
644  // Edge 0
645  edgeOrient = e->GetGeom()->GetEorient(0);
646  if (edgeOrient==StdRegions::eForwards)
647  {
648  vId[cnt1+n] = 4*nel +
649  maxN*e->GetGeom()->GetEid(0) + n;
650  }
651  else
652  {
653  vId[cnt1+np-1-n] = 4*nel +
654  maxN*e->GetGeom()->GetEid(0) + n;
655  }
656 
657  // Edge 1
658  edgeOrient = e->GetGeom()->GetEorient(1);
659  if (edgeOrient==StdRegions::eForwards)
660  {
661  vId[cnt1+np-1+n*np] = 4*nel +
662  maxN*e->GetGeom()->GetEid(1) + n;
663  }
664  else
665  {
666  vId[cnt1+np*np-1-n*np] = 4*nel +
667  maxN*e->GetGeom()->GetEid(1) + n;
668  }
669 
670  // Edge 2
671  edgeOrient = e->GetGeom()->GetEorient(2);
672  if (edgeOrient==StdRegions::eForwards)
673  {
674  vId[cnt1+np*np-1-n] = 4*nel +
675  maxN*e->GetGeom()->GetEid(2) + n;
676  }
677  else
678  {
679  vId[cnt1+np*(np-1)+n] = 4*nel +
680  maxN*e->GetGeom()->GetEid(2) + n;
681  }
682 
683  // Edge 3
684  edgeOrient = e->GetGeom()->GetEorient(3);
685  if (edgeOrient==StdRegions::eForwards)
686  {
687  vId[cnt1+np*(np-1)-n*np] = 4*nel +
688  maxN*e->GetGeom()->GetEid(3) + n;
689  }
690  else
691  {
692  vId[cnt1+n*np] = 4*nel +
693  maxN*e->GetGeom()->GetEid(3) + n;
694  }
695  }
696 
697  // Interior numbering
698  for (int n = 1; n < np-1; n++)
699  {
700  for (int m = 1; m < np-1; m++)
701  {
702  vId[cnt1+m*np+n] = 4*nel + maxN*4*nel + cnt2;
703  cnt2++;
704  }
705  }
706  cnt1+= newpoints;
707  }
708  break;
709  default:
710  {
711  ASSERTL0(false,"Points not known");
712  }
713  }
714  }
715 
716  // Crete new connectivity using homogeneous information
717  for(int i = 0; i < nel; ++i)
718  {
719  int nTris = oldConn[i].num_elements()/3;
720  // Create array for new connectivity
721  // (3 tetrahedra between each plane for each triangle)
722  conn = Array<OneD, int> (4*3*nTris*(nPlanes-1));
723  cnt2=0;
724  for(int n = 0; n<nTris; n++)
725  {
726  // Get id of vertices in this triangle (on plane 0)
727  int vId0 = vId[oldConn[i][3*n+0]];
728  int vId1 = vId[oldConn[i][3*n+1]];
729  int vId2 = vId[oldConn[i][3*n+2]];
730 
731  // Determine ordering based on global Id of pts
732  Array<OneD, int> rot(3);
733  if ( (vId0<vId1) && (vId0<vId2))
734  {
735  rot[0] = 0;
736  if (vId1<vId2)
737  {
738  rot[1] = 1;
739  rot[2] = 2;
740  }
741  else
742  {
743  rot[1] = 2;
744  rot[2] = 1;
745  }
746  }
747  else if ( (vId1<vId0) && (vId1<vId2))
748  {
749  rot[0] = 1;
750  if (vId0<vId2)
751  {
752  rot[1] = 0;
753  rot[2] = 2;
754  }
755  else
756  {
757  rot[1] = 2;
758  rot[2] = 0;
759  }
760  }
761  else
762  {
763  rot[0] = 2;
764  if (vId0<vId1)
765  {
766  rot[1] = 0;
767  rot[2] = 1;
768  }
769  else
770  {
771  rot[1] = 1;
772  rot[2] = 0;
773  }
774  }
775 
776  // Define new connectivity with tetrahedra
777  for ( int p = 0; p<nPlanes-1; p++)
778  {
779  conn[cnt2++] = oldConn[i+ p *nel][3*n+rot[0]];
780  conn[cnt2++] = oldConn[i+ p *nel][3*n+rot[1]];
781  conn[cnt2++] = oldConn[i+ p *nel][3*n+rot[2]];
782  conn[cnt2++] = oldConn[i+(p+1)*nel][3*n+rot[2]];
783 
784  conn[cnt2++] = oldConn[i+ p *nel][3*n+rot[0]];
785  conn[cnt2++] = oldConn[i+ p *nel][3*n+rot[1]];
786  conn[cnt2++] = oldConn[i+(p+1)*nel][3*n+rot[2]];
787  conn[cnt2++] = oldConn[i+(p+1)*nel][3*n+rot[1]];
788 
789  conn[cnt2++] = oldConn[i+ p *nel][3*n+rot[0]];
790  conn[cnt2++] = oldConn[i+(p+1)*nel][3*n+rot[1]];
791  conn[cnt2++] = oldConn[i+(p+1)*nel][3*n+rot[2]];
792  conn[cnt2++] = oldConn[i+(p+1)*nel][3*n+rot[0]];
793  }
794  }
795  newConn.push_back(conn);
796  }
797  }
798  else
799  {
800  ASSERTL0( false, "Points type not supported.");
801  }
802 
803  m_f->m_fieldPts->SetConnectivity(newConn);
804 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
Fourier Expansion .
Definition: BasisType.h:53
1D Evenly-spaced points using Fourier Fit
Definition: PointsType.h:65
int getNumberOfCoefficients(int Na, int Nb)
Definition: ShapeType.hpp:113
void Sadd(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Add vector y = alpha + x.
Definition: Vmath.cpp:318
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:65
int getNumberOfCoefficients(int Na, int Nb)
Definition: ShapeType.hpp:137
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1064
FieldSharedPtr m_f
Field object.

Member Data Documentation

◆ className

ModuleKey Nektar::FieldUtils::ProcessEquiSpacedOutput::className
static
Initial value:
=
ModuleKey(eProcessModule, "equispacedoutput"),
"Write data as equi-spaced output using simplices to represent the "
"data for connecting points")

Definition at line 56 of file ProcessEquiSpacedOutput.h.