Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ProcessEquiSpacedOutput.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: ProcessEquiSpacedOutput.cpp
4 //
5 // For more information, please see: http://www.nektar.info/
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // License for the specific language governing rights and limitations under
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description: Set up fields as interpolation to equispaced output
33 //
34 ////////////////////////////////////////////////////////////////////////////////
35 #include <iostream>
36 #include <string>
37 using namespace std;
38 
40 
44 #include <StdRegions/StdQuadExp.h>
45 #include <StdRegions/StdTriExp.h>
46 #include <boost/math/special_functions/fpclassify.hpp>
47 
48 namespace Nektar
49 {
50 namespace FieldUtils
51 {
52 
53 ModuleKey ProcessEquiSpacedOutput::className =
55  ModuleKey(eProcessModule, "equispacedoutput"),
56  ProcessEquiSpacedOutput::create,
57  "Write data as equi-spaced output using simplices to represent the "
58  "data for connecting points");
59 
60 ProcessEquiSpacedOutput::ProcessEquiSpacedOutput(FieldSharedPtr f)
61  : ProcessModule(f)
62 {
63  f->m_setUpEquiSpacedFields = true;
64 
65  m_config["tetonly"] =
66  ConfigOption(true, "NotSet", "Only process tetrahedral elements");
67 
68  m_config["modalenergy"] =
69  ConfigOption(true, "NotSet", "Write output as modal energy");
70 }
71 
73 {
74 }
75 
76 void ProcessEquiSpacedOutput::Process(po::variables_map &vm)
77 {
79 }
80 
82 {
83  if (m_f->m_verbose)
84  {
85  if (m_f->m_comm->TreatAsRankZero())
86  {
87  cout << "Interpolating fields to equispaced..." << endl;
88  }
89  }
90  int nel = m_f->m_exp[0]->GetExpSize();
91  if (!nel)
92  {
93  m_f->m_fieldPts = LibUtilities::NullPtsField;
94  return;
95  }
96 
97  int coordim = m_f->m_exp[0]->GetCoordim(0);
98  int shapedim = m_f->m_exp[0]->GetExp(0)->GetShapeDimension();
99  int npts = m_f->m_exp[0]->GetTotPoints();
101 
102  // Check if we have a homogeneous expansion
103  bool homogeneous1D = false;
104  if (m_f->m_fielddef.size())
105  {
106  if (m_f->m_fielddef[0]->m_numHomogeneousDir == 1)
107  {
108  coordim++;
109  shapedim++;
110  homogeneous1D = true;
111  }
112  else if (m_f->m_fielddef[0]->m_numHomogeneousDir == 2)
113  {
114  ASSERTL0(false, "Homegeneous2D case not supported");
115  }
116  }
117  else
118  {
119  if (m_f->m_session->DefinesSolverInfo("HOMOGENEOUS"))
120  {
121  std::string HomoStr = m_f->m_session->GetSolverInfo("HOMOGENEOUS");
122 
123  if ((HomoStr == "HOMOGENEOUS1D") || (HomoStr == "Homogeneous1D") ||
124  (HomoStr == "1D") || (HomoStr == "Homo1D"))
125  {
126  coordim++;
127  shapedim++;
128  homogeneous1D = true;
129  }
130  if ((HomoStr == "HOMOGENEOUS2D") || (HomoStr == "Homogeneous2D") ||
131  (HomoStr == "2D") || (HomoStr == "Homo2D"))
132  {
133  ASSERTL0(false, "Homegeneous2D case not supported");
134  }
135  }
136  }
137 
138  // set up the number of points in each element
139  int newpoints = 0;
140  int newtotpoints = 0;
141 
142  Array<OneD, int> conn;
143  int prevNcoeffs = 0;
144  int prevNpoints = 0;
145  int cnt = 0;
146 
147  // identify face 1 connectivity for prisms
148  map<int, StdRegions::Orientation> face0orient;
149  set<int> prismorient;
151 
152  // prepare PtsField
153  vector<std::string> fieldNames;
154  vector<int> ppe;
155  vector<Array<OneD, int> > ptsConn;
156  int nfields;
157 
158  for (int i = 0; i < nel; ++i)
159  {
160  e = m_f->m_exp[0]->GetExp(i);
161  if (e->DetShapeType() == LibUtilities::ePrism)
162  {
163  StdRegions::Orientation forient = e->GetForient(0);
164  int fid = e->GetGeom()->GetFid(0);
165  if (face0orient.count(fid))
166  { // face 1 meeting face 1 so reverse this id
167  prismorient.insert(i);
168  }
169  else
170  {
171  // just store if Dir 1 is fwd or bwd
172  if ((forient == StdRegions::eDir1BwdDir1_Dir2FwdDir2) ||
176  {
177  face0orient[fid] = StdRegions::eBwd;
178  }
179  else
180  {
181  face0orient[fid] = StdRegions::eFwd;
182  }
183  }
184  }
185  }
186 
187  for (int i = 0; i < nel; ++i)
188  {
189  e = m_f->m_exp[0]->GetExp(i);
190  if (e->DetShapeType() == LibUtilities::ePrism)
191  {
192  int fid = e->GetGeom()->GetFid(2);
193  // check to see if face 2 meets face 1
194  if (face0orient.count(fid))
195  {
196  // check to see how face 2 is orientated
197  StdRegions::Orientation forient2 = e->GetForient(2);
198  StdRegions::Orientation forient0 = face0orient[fid];
199 
200  // If dir 1 or forient2 is bwd then check agains
201  // face 1 value
202  if ((forient2 == StdRegions::eDir1BwdDir1_Dir2FwdDir2) ||
203  (forient2 == StdRegions::eDir1BwdDir1_Dir2BwdDir2) ||
204  (forient2 == StdRegions::eDir1BwdDir2_Dir2FwdDir1) ||
206  {
207  if (forient0 == StdRegions::eFwd)
208  {
209  prismorient.insert(i);
210  }
211  }
212  else
213  {
214  if (forient0 == StdRegions::eBwd)
215  {
216  prismorient.insert(i);
217  }
218  }
219  }
220  }
221  }
222 
223  for (int i = 0; i < nel; ++i)
224  {
225  e = m_f->m_exp[0]->GetExp(i);
226  if (m_config["tetonly"].m_beenSet)
227  {
228  if (m_f->m_exp[0]->GetExp(i)->DetShapeType() !=
230  {
231  continue;
232  }
233  }
234 
235  switch (e->DetShapeType())
236  {
238  {
239  int npoints0 = e->GetBasis(0)->GetNumPoints();
240 
241  newpoints =
243  }
244  break;
246  {
247  int np0 = e->GetBasis(0)->GetNumPoints();
248  int np1 = e->GetBasis(1)->GetNumPoints();
249  int np = max(np0, np1);
250  newpoints =
252  }
253  break;
255  {
256  int np0 = e->GetBasis(0)->GetNumPoints();
257  int np1 = e->GetBasis(1)->GetNumPoints();
258  int np = max(np0, np1);
259 
260  newpoints =
262  }
263  break;
265  {
266  int np0 = e->GetBasis(0)->GetNumPoints();
267  int np1 = e->GetBasis(1)->GetNumPoints();
268  int np2 = e->GetBasis(2)->GetNumPoints();
269  int np = max(np0, max(np1, np2));
270 
272  np, np, np);
273  }
274  break;
276  {
277  int np0 = e->GetBasis(0)->GetNumPoints();
278  int np1 = e->GetBasis(1)->GetNumPoints();
279  int np2 = e->GetBasis(2)->GetNumPoints();
280  int np = max(np0, max(np1, np2));
281 
283  np, np, np);
284  }
285  break;
287  {
288  int np0 = e->GetBasis(0)->GetNumPoints();
289  int np1 = e->GetBasis(1)->GetNumPoints();
290  int np2 = e->GetBasis(2)->GetNumPoints();
291  int np = max(np0, max(np1, np2));
292 
294  np, np, np);
295  }
296  break;
298  {
299  int np0 = e->GetBasis(0)->GetNumPoints();
300  int np1 = e->GetBasis(1)->GetNumPoints();
301  int np2 = e->GetBasis(2)->GetNumPoints();
302  int np = max(np0, max(np1, np2));
303 
305  np, np, np);
306  }
307  break;
308  default:
309  {
310  ASSERTL0(false, "Points not known");
311  }
312  }
313 
314  ppe.push_back(newpoints);
315  newtotpoints += newpoints;
316 
317  if (e->DetShapeType() == LibUtilities::ePrism)
318  {
319  bool standard = true;
320 
321  if (prismorient.count(i))
322  {
323  standard = false; // reverse direction
324  }
325 
326  e->GetSimplexEquiSpacedConnectivity(conn, standard);
327  }
328  else
329  {
330 
331  if ((prevNcoeffs != e->GetNcoeffs()) ||
332  (prevNpoints != e->GetTotPoints()))
333  {
334  prevNcoeffs = e->GetNcoeffs();
335  prevNpoints = e->GetTotPoints();
336 
337  e->GetSimplexEquiSpacedConnectivity(conn);
338  }
339  }
340  Array<OneD, int> newconn(conn.num_elements());
341  for (int j = 0; j < conn.num_elements(); ++j)
342  {
343  newconn[j] = conn[j] + cnt;
344  }
345 
346  ptsConn.push_back(newconn);
347  cnt += newpoints;
348  }
349 
350  if (m_f->m_fielddef.size())
351  {
352  nfields = m_f->m_exp.size();
353  }
354  else // just the mesh points
355  {
356  nfields = 0;
357  }
358 
359  Array<OneD, Array<OneD, NekDouble> > pts(nfields + coordim);
360 
361  for (int i = 0; i < nfields + coordim; ++i)
362  {
363  pts[i] = Array<OneD, NekDouble>(newtotpoints);
364  }
365 
366  // Interpolate coordinates
367  for (int i = 0; i < coordim; ++i)
368  {
369  coords[i] = Array<OneD, NekDouble>(npts);
370  }
371 
372  for (int i = coordim; i < 3; ++i)
373  {
374  coords[i] = NullNekDouble1DArray;
375  }
376 
377  m_f->m_exp[0]->GetCoords(coords[0], coords[1], coords[2]);
378 
379  int nq1 = m_f->m_exp[0]->GetTotPoints();
380 
381  Array<OneD, NekDouble> x1(nq1);
382  Array<OneD, NekDouble> y1(nq1);
383  Array<OneD, NekDouble> z1(nq1);
384 
385  m_f->m_exp[0]->GetCoords(x1, y1, z1);
386 
388 
389  for (int n = 0; n < coordim; ++n)
390  {
391  cnt = 0;
392  int cnt1 = 0;
393  for (int i = 0; i < nel; ++i)
394  {
395  m_f->m_exp[0]->GetExp(i)->PhysInterpToSimplexEquiSpaced(
396  coords[n] + cnt, tmp = pts[n] + cnt1);
397  cnt1 += ppe[i];
398  cnt += m_f->m_exp[0]->GetExp(i)->GetTotPoints();
399  }
400  }
401 
402  if (m_f->m_fielddef.size())
403  {
404  ASSERTL0(m_f->m_fielddef[0]->m_fields.size() == m_f->m_exp.size(),
405  "More expansion defined than fields");
406 
407  for (int n = 0; n < m_f->m_exp.size(); ++n)
408  {
409  cnt = 0;
410  int cnt1 = 0;
411 
412  if (m_config["modalenergy"].m_beenSet)
413  {
414  Array<OneD, const NekDouble> phys = m_f->m_exp[n]->GetPhys();
415  for (int i = 0; i < nel; ++i)
416  {
417  GenOrthoModes(i, phys + cnt, tmp = pts[coordim + n] + cnt1);
418  cnt1 += ppe[i];
419  cnt += m_f->m_exp[0]->GetExp(i)->GetTotPoints();
420  }
421  }
422  else
423  {
424  Array<OneD, const NekDouble> phys = m_f->m_exp[n]->GetPhys();
425  for (int i = 0; i < nel; ++i)
426  {
427  m_f->m_exp[0]->GetExp(i)->PhysInterpToSimplexEquiSpaced(
428  phys + cnt, tmp = pts[coordim + n] + cnt1);
429  cnt1 += ppe[i];
430  cnt += m_f->m_exp[0]->GetExp(i)->GetTotPoints();
431  }
432  }
433 
434  // Set up Variable string.
435  fieldNames.push_back(m_f->m_fielddef[0]->m_fields[n]);
436  }
437  }
438 
440  coordim, fieldNames, pts);
441  if (shapedim == 1)
442  {
443  m_f->m_fieldPts->SetPtsType(LibUtilities::ePtsSegBlock);
444  }
445 
446  if (shapedim == 2)
447  {
448  m_f->m_fieldPts->SetPtsType(LibUtilities::ePtsTriBlock);
449  }
450  else if (shapedim == 3)
451  {
452  m_f->m_fieldPts->SetPtsType(LibUtilities::ePtsTetBlock);
453  }
454  m_f->m_fieldPts->SetConnectivity(ptsConn);
455  if (homogeneous1D)
456  {
458  }
459 }
460 
462 {
464  int nel = m_f->m_exp[0]->GetPlane(0)->GetExpSize();
465  int nPlanes = m_f->m_exp[0]->GetZIDs().num_elements();
466  int npts = m_f->m_fieldPts->GetNpoints();
467  int nptsPerPlane = npts / nPlanes;
468  int coordim = 3;
469 
470  if (m_f->m_exp[0]->GetHomogeneousBasis()->GetBasisType() ==
472  m_f->m_exp[0]->GetHomogeneousBasis()->GetPointsType() ==
474  {
475  // Write points with extra plane
477  m_f->m_fieldPts->GetPts(pts);
478  Array<OneD, Array<OneD, NekDouble> > newPts(pts.num_elements());
479  for (int i = 0; i < pts.num_elements(); i++)
480  {
481  newPts[i] = Array<OneD, NekDouble>(npts + nptsPerPlane);
482  // Copy old points
483  Vmath::Vcopy(npts, pts[i], 1, newPts[i], 1);
484  // Get new plane
485  Array<OneD, NekDouble> extraPlane(nptsPerPlane, newPts[i] + npts);
486  if (m_f->m_comm->GetColumnComm()->GetSize() == 1)
487  {
488  if ( i == (coordim-1))
489  {
490  // z-coordinate
491  Vmath::Sadd(nptsPerPlane, m_f->m_exp[0]->GetHomoLen(),
492  pts[i], 1, extraPlane, 1);
493  }
494  else
495  {
496  Vmath::Vcopy(nptsPerPlane, pts[i], 1, extraPlane, 1);
497  }
498  }
499  else
500  {
501  // Determine to and from rank for communication
502  int size = m_f->m_comm->GetColumnComm()->GetSize();
503  int rank = m_f->m_comm->GetColumnComm()->GetRank();
504  int fromRank = (rank + 1) % size;
505  int toRank = (rank == 0) ? size - 1 : rank - 1;
506  // Communicate using SendRecv
507  Array<OneD, NekDouble> send(nptsPerPlane, pts[i]);
508  m_f->m_comm->GetColumnComm()->SendRecv(toRank, send, fromRank,
509  extraPlane);
510  // Adjust z-coordinate of last process
511  if (i == (coordim-1) && (rank == size - 1) )
512  {
513  Vmath::Sadd(nptsPerPlane, m_f->m_exp[0]->GetHomoLen(),
514  extraPlane, 1, extraPlane, 1);
515  }
516  }
517  }
518  m_f->m_fieldPts->SetPts(newPts);
519  // Now extend plane connectivity
520  vector<Array<OneD, int> > oldConn;
521  Array<OneD, int> conn;
522  m_f->m_fieldPts->GetConnectivity(oldConn);
523  vector<Array<OneD, int> > newConn = oldConn;
524  int connPerPlane = oldConn.size() / nPlanes;
525  for (int i = 0; i < connPerPlane; i++)
526  {
527  conn = Array<OneD, int>(oldConn[i].num_elements());
528  for (int j = 0; j < conn.num_elements(); j++)
529  {
530  conn[j] = oldConn[i][j] + npts;
531  }
532  newConn.push_back(conn);
533  }
534  m_f->m_fieldPts->SetConnectivity(newConn);
535 
536  nPlanes++;
537  npts += nptsPerPlane;
538  }
539 
540  vector<Array<OneD, int> > oldConn;
541  vector<Array<OneD, int> > newConn;
542  Array<OneD, int> conn;
543  m_f->m_fieldPts->GetConnectivity(oldConn);
544 
545  // 2DH1D case
546  if (m_f->m_fieldPts->GetPtsType() == LibUtilities::ePtsTriBlock)
547  {
548  for(int i = 0; i < nel; ++i)
549  {
550  int nLines = oldConn[i].num_elements()/2;
551  // Create array for new connectivity
552  // (2 triangles between each plane for each line)
553  conn = Array<OneD, int> (2*3*nLines*(nPlanes-1));
554  int cnt = 0;
555  for(int n = 0; n<nLines; n++)
556  {
557  // Define new connectivity with triangles
558  for ( int p = 0; p<nPlanes-1; p++)
559  {
560  conn[cnt++] = oldConn[i+ p *nel][2*n+0];
561  conn[cnt++] = oldConn[i+ p *nel][2*n+1];
562  conn[cnt++] = oldConn[i+(p+1)*nel][2*n+0];
563 
564  conn[cnt++] = oldConn[i+ p *nel][2*n+1];
565  conn[cnt++] = oldConn[i+(p+1)*nel][2*n+0];
566  conn[cnt++] = oldConn[i+(p+1)*nel][2*n+1];
567  }
568  }
569  newConn.push_back(conn);
570  }
571  }
572  else if(m_f->m_fieldPts->GetPtsType() == LibUtilities::ePtsTetBlock)
573  {
574  // Get maximum number of points per direction in the mesh
575  int maxN = 0;
576  for(int i = 0; i < nel; ++i)
577  {
578  e = m_f->m_exp[0]->GetPlane(0)->GetExp(i);
579 
580  int np0 = e->GetBasis(0)->GetNumPoints();
581  int np1 = e->GetBasis(1)->GetNumPoints();
582  int np = max(np0,np1);
583  maxN = max(np, maxN);
584  }
585 
586  // Create a global numbering for points in plane 0
587  Array<OneD, int> vId(nptsPerPlane);
588  int cnt1=0;
589  int cnt2=0;
590  for(int i = 0; i < nel; ++i)
591  {
592  e = m_f->m_exp[0]->GetPlane(0)->GetExp(i);
593  int np0 = e->GetBasis(0)->GetNumPoints();
594  int np1 = e->GetBasis(1)->GetNumPoints();
595  int np = max(np0,np1);
596  switch(e->DetShapeType())
597  {
599  {
600  int newpoints = LibUtilities::StdTriData::
602 
603  // Vertex numbering
604  vId[cnt1] = e->GetGeom()->GetVid(0);
605  vId[cnt1+np-1] = e->GetGeom()->GetVid(1);
606  vId[cnt1+newpoints-1] = e->GetGeom()->GetVid(2);
607 
608  // Edge numbering
609  StdRegions::Orientation edgeOrient;
610  int edge1 = 0;
611  int edge2 = 0;
612  for (int n = 1; n < np-1; n++)
613  {
614  // Edge 0
615  edgeOrient = e->GetGeom()->GetEorient(0);
616  if (edgeOrient==StdRegions::eForwards)
617  {
618  vId[cnt1+n] = 4*nel +
619  maxN*e->GetGeom()->GetEid(0) + n;
620  }
621  else
622  {
623  vId[cnt1+np-1-n] = 4*nel +
624  maxN*e->GetGeom()->GetEid(0) + n;
625  }
626 
627  // Edge 1
628  edgeOrient = e->GetGeom()->GetEorient(1);
629  if (edgeOrient==StdRegions::eForwards)
630  {
631  edge1 += np-n;
632  vId[cnt1+np-1+edge1] = 4*nel +
633  maxN*e->GetGeom()->GetEid(1) + n;
634  }
635  else
636  {
637  edge1 += n;
638  vId[cnt1+newpoints-1-edge1] = 4*nel +
639  maxN*e->GetGeom()->GetEid(1) + n;
640  }
641 
642  // Edge 2
643  edgeOrient = e->GetGeom()->GetEorient(2);
644  if (edgeOrient==StdRegions::eForwards)
645  {
646  edge2 += n+1;
647  vId[cnt1+newpoints-1-edge2] = 4*nel +
648  maxN*e->GetGeom()->GetEid(2) + n;
649  }
650  else
651  {
652  edge2 += np+1-n;
653  vId[cnt1+edge2] = 4*nel +
654  maxN*e->GetGeom()->GetEid(2) + n;
655  }
656  }
657 
658  // Interior numbering
659  edge2 = 0;
660  for (int n = 1; n < np-1; n++)
661  {
662  edge2 += np+1-n;
663  for (int m = 1; m < np-n-1; m++)
664  {
665  vId[cnt1+edge2+m] = 4*nel + maxN*4*nel + cnt2;
666  cnt2++;
667  }
668  }
669  cnt1+= newpoints;
670  }
671  break;
673  {
674  int newpoints = LibUtilities::StdQuadData::
676  // Vertex numbering
677  vId[cnt1] = e->GetGeom()->GetVid(0);
678  vId[cnt1+np-1] = e->GetGeom()->GetVid(1);
679  vId[cnt1+np*np-1] = e->GetGeom()->GetVid(2);
680  vId[cnt1+np*(np-1)] = e->GetGeom()->GetVid(3);
681 
682  // Edge numbering
683  StdRegions::Orientation edgeOrient;
684  for (int n = 1; n < np-1; n++)
685  {
686  // Edge 0
687  edgeOrient = e->GetGeom()->GetEorient(0);
688  if (edgeOrient==StdRegions::eForwards)
689  {
690  vId[cnt1+n] = 4*nel +
691  maxN*e->GetGeom()->GetEid(0) + n;
692  }
693  else
694  {
695  vId[cnt1+np-1-n] = 4*nel +
696  maxN*e->GetGeom()->GetEid(0) + n;
697  }
698 
699  // Edge 1
700  edgeOrient = e->GetGeom()->GetEorient(1);
701  if (edgeOrient==StdRegions::eForwards)
702  {
703  vId[cnt1+np-1+n*np] = 4*nel +
704  maxN*e->GetGeom()->GetEid(1) + n;
705  }
706  else
707  {
708  vId[cnt1+np*np-1-n*np] = 4*nel +
709  maxN*e->GetGeom()->GetEid(1) + n;
710  }
711 
712  // Edge 2
713  edgeOrient = e->GetGeom()->GetEorient(2);
714  if (edgeOrient==StdRegions::eForwards)
715  {
716  vId[cnt1+np*np-1-n] = 4*nel +
717  maxN*e->GetGeom()->GetEid(2) + n;
718  }
719  else
720  {
721  vId[cnt1+np*(np-1)+n] = 4*nel +
722  maxN*e->GetGeom()->GetEid(2) + n;
723  }
724 
725  // Edge 3
726  edgeOrient = e->GetGeom()->GetEorient(3);
727  if (edgeOrient==StdRegions::eForwards)
728  {
729  vId[cnt1+np*(np-1)-n*np] = 4*nel +
730  maxN*e->GetGeom()->GetEid(3) + n;
731  }
732  else
733  {
734  vId[cnt1+n*np] = 4*nel +
735  maxN*e->GetGeom()->GetEid(3) + n;
736  }
737  }
738 
739  // Interior numbering
740  for (int n = 1; n < np-1; n++)
741  {
742  for (int m = 1; m < np-1; m++)
743  {
744  vId[cnt1+m*np+n] = 4*nel + maxN*4*nel + cnt2;
745  cnt2++;
746  }
747  }
748  cnt1+= newpoints;
749  }
750  break;
751  default:
752  {
753  ASSERTL0(false,"Points not known");
754  }
755  }
756  }
757 
758  // Crete new connectivity using homogeneous information
759  for(int i = 0; i < nel; ++i)
760  {
761  int nTris = oldConn[i].num_elements()/3;
762  // Create array for new connectivity
763  // (3 tetrahedra between each plane for each triangle)
764  conn = Array<OneD, int> (4*3*nTris*(nPlanes-1));
765  cnt2=0;
766  for(int n = 0; n<nTris; n++)
767  {
768  // Get id of vertices in this triangle (on plane 0)
769  int vId0 = vId[oldConn[i][3*n+0]];
770  int vId1 = vId[oldConn[i][3*n+1]];
771  int vId2 = vId[oldConn[i][3*n+2]];
772 
773  // Determine ordering based on global Id of pts
774  Array<OneD, int> rot(3);
775  if ( (vId0<vId1) && (vId0<vId2))
776  {
777  rot[0] = 0;
778  if (vId1<vId2)
779  {
780  rot[1] = 1;
781  rot[2] = 2;
782  }
783  else
784  {
785  rot[1] = 2;
786  rot[2] = 1;
787  }
788  }
789  else if ( (vId1<vId0) && (vId1<vId2))
790  {
791  rot[0] = 1;
792  if (vId0<vId2)
793  {
794  rot[1] = 0;
795  rot[2] = 2;
796  }
797  else
798  {
799  rot[1] = 2;
800  rot[2] = 0;
801  }
802  }
803  else
804  {
805  rot[0] = 2;
806  if (vId0<vId1)
807  {
808  rot[1] = 0;
809  rot[2] = 1;
810  }
811  else
812  {
813  rot[1] = 1;
814  rot[2] = 0;
815  }
816  }
817 
818  // Define new connectivity with tetrahedra
819  for ( int p = 0; p<nPlanes-1; p++)
820  {
821  conn[cnt2++] = oldConn[i+ p *nel][3*n+rot[0]];
822  conn[cnt2++] = oldConn[i+ p *nel][3*n+rot[1]];
823  conn[cnt2++] = oldConn[i+ p *nel][3*n+rot[2]];
824  conn[cnt2++] = oldConn[i+(p+1)*nel][3*n+rot[2]];
825 
826  conn[cnt2++] = oldConn[i+ p *nel][3*n+rot[0]];
827  conn[cnt2++] = oldConn[i+ p *nel][3*n+rot[1]];
828  conn[cnt2++] = oldConn[i+(p+1)*nel][3*n+rot[2]];
829  conn[cnt2++] = oldConn[i+(p+1)*nel][3*n+rot[1]];
830 
831  conn[cnt2++] = oldConn[i+ p *nel][3*n+rot[0]];
832  conn[cnt2++] = oldConn[i+(p+1)*nel][3*n+rot[1]];
833  conn[cnt2++] = oldConn[i+(p+1)*nel][3*n+rot[2]];
834  conn[cnt2++] = oldConn[i+(p+1)*nel][3*n+rot[0]];
835  }
836  }
837  newConn.push_back(conn);
838  }
839  }
840  else
841  {
842  ASSERTL0( false, "Points type not supported.");
843  }
844 
845  m_f->m_fieldPts->SetConnectivity(newConn);
846 }
847 
849  int n,
850  const Array<OneD, const NekDouble> &phys,
851  Array<OneD, NekDouble> &coeffs)
852 {
854  e = m_f->m_exp[0]->GetExp(n);
855 
856  switch (e->DetShapeType())
857  {
859  {
860  int np0 = e->GetBasis(0)->GetNumPoints();
861  int np1 = e->GetBasis(1)->GetNumPoints();
862  int np = max(np0, np1);
863 
864  // to ensure points are correctly projected to np need
865  // to increase the order slightly of coordinates
866  LibUtilities::PointsKey pa(np + 1, e->GetPointsType(0));
867  LibUtilities::PointsKey pb(np, e->GetPointsType(1));
868  Array<OneD, NekDouble> tophys(np * (np + 1));
869 
872  StdRegions::StdTriExp OrthoExp(Ba, Bb);
873 
874  // interpolate points to new phys points!
875  LibUtilities::Interp2D(e->GetBasis(0)->GetBasisKey(),
876  e->GetBasis(1)->GetBasisKey(), phys, Ba, Bb,
877  tophys);
878 
879  OrthoExp.FwdTrans(tophys, coeffs);
880  break;
881  }
883  {
884  int np0 = e->GetBasis(0)->GetNumPoints();
885  int np1 = e->GetBasis(1)->GetNumPoints();
886  int np = max(np0, np1);
887 
888  LibUtilities::PointsKey pa(np + 1, e->GetPointsType(0));
889  LibUtilities::PointsKey pb(np + 1, e->GetPointsType(1));
890  Array<OneD, NekDouble> tophys((np + 1) * (np + 1));
891 
894  StdRegions::StdQuadExp OrthoExp(Ba, Bb);
895 
896  // interpolate points to new phys points!
897  LibUtilities::Interp2D(e->GetBasis(0)->GetBasisKey(),
898  e->GetBasis(1)->GetBasisKey(), phys, Ba, Bb,
899  tophys);
900 
901  OrthoExp.FwdTrans(phys, coeffs);
902  break;
903  }
904  default:
905  ASSERTL0(false, "Shape needs setting up");
906  break;
907  }
908 }
909 }
910 }
map< string, ConfigOption > m_config
List of configuration values.
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:198
int getNumberOfCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:286
static Array< OneD, NekDouble > NullNekDouble1DArray
static boost::shared_ptr< DataType > AllocateSharedPtr()
Allocate a shared pointer from the memory pool.
Represents a command-line configuration option.
virtual void Process(po::variables_map &vm)
Write mesh to output file.
STL namespace.
pair< ModuleType, string > ModuleKey
Fourier Expansion .
Definition: BasisType.h:52
int getNumberOfCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:186
Principle Orthogonal Functions .
Definition: BasisType.h:47
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:116
1D Evenly-spaced points using Fourier Fit
Definition: PointsType.h:66
boost::shared_ptr< Field > FieldSharedPtr
Definition: Field.hpp:767
static std::string npts
Definition: InputFld.cpp:43
int getNumberOfCoefficients(int Na, int Nb)
Definition: ShapeType.hpp:111
Principle Orthogonal Functions .
Definition: BasisType.h:46
Defines a specification for a set of points.
Definition: Points.h:58
boost::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:68
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:315
void GenOrthoModes(int n, const Array< OneD, const NekDouble > &phys, Array< OneD, NekDouble > &coeffs)
int getNumberOfCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:232
static PtsFieldSharedPtr NullPtsField
Definition: PtsField.h:179
int getNumberOfCoefficients(int Na, int Nb)
Definition: ShapeType.hpp:132
int getNumberOfCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:151
Abstract base class for processing modules.
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1061
Describes the specification for a Basis.
Definition: Basis.h:50
ModuleFactory & GetModuleFactory()
FieldSharedPtr m_f
Field object.
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, tDescription pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:215
void FwdTrans(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
This function performs the Forward transformation from physical space to coefficient space...