Nektar++
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 <string>
36 #include <iostream>
37 using namespace std;
38 
40 
44 #include <boost/math/special_functions/fpclassify.hpp>
45 #include <StdRegions/StdQuadExp.h>
46 #include <StdRegions/StdTriExp.h>
47 
48 namespace Nektar
49 {
50 namespace Utilities
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 data for connecting points");
58 
59 
60 ProcessEquiSpacedOutput::ProcessEquiSpacedOutput(FieldSharedPtr f)
61  : ProcessModule(f)
62 {
63  f->m_setUpEquiSpacedFields = true;
64 
65  m_config["tetonly"] = ConfigOption(true, "NotSet",
66  "Only process tetrahedral elements");
67 
68  m_config["modalenergy"] = ConfigOption(true,"NotSet","Write output as modal energy");
69 
70 }
71 
73 {
74 }
75 
76 void ProcessEquiSpacedOutput::Process(po::variables_map &vm)
77 {
79 }
80 
81 
83 {
84 
85  if(m_f->m_verbose)
86  {
87  cout << "Interpolating fields to equispaced" << endl;
88  }
89 
90  int coordim = m_f->m_exp[0]->GetCoordim(0);
91  int shapedim = m_f->m_exp[0]->GetExp(0)->GetShapeDimension();
92  int npts = m_f->m_exp[0]->GetTotPoints();
94 
95  int nel = m_f->m_exp[0]->GetExpSize();
96 
97  // set up the number of points in each element
98  int newpoints;
99  int newtotpoints = 0;
100 
101  Array<OneD,int> conn;
102  int prevNcoeffs = 0;
103  int prevNpoints = 0;
104  int cnt = 0;
105 
106  // identify face 1 connectivity for prisms
107  map<int,StdRegions::Orientation > face0orient;
108  set<int> prismorient;
110 
111  // prepare PtsField
112  vector<std::string> fieldNames;
113  vector<int> ppe;
114  vector<Array<OneD, int> > ptsConn;
115  int nfields;
116 
117  for(int i = 0; i < nel; ++i)
118  {
119  e = m_f->m_exp[0]->GetExp(i);
120  if(e->DetShapeType() == LibUtilities::ePrism)
121  {
122  StdRegions::Orientation forient = e->GetForient(0);
123  int fid = e->GetGeom()->GetFid(0);
124  if(face0orient.count(fid))
125  { // face 1 meeting face 1 so reverse this id
126  prismorient.insert(i);
127  }
128  else
129  {
130  // just store if Dir 1 is fwd or bwd
131  if((forient == StdRegions::eDir1BwdDir1_Dir2FwdDir2) ||
135  {
136  face0orient[fid] = StdRegions::eBwd;
137  }
138  else
139  {
140  face0orient[fid] = StdRegions::eFwd;
141  }
142  }
143  }
144  }
145 
146  for(int i = 0; i < nel; ++i)
147  {
148  e = m_f->m_exp[0]->GetExp(i);
149  if(e->DetShapeType() == LibUtilities::ePrism)
150  {
151  int fid = e->GetGeom()->GetFid(2);
152  // check to see if face 2 meets face 1
153  if(face0orient.count(fid))
154  {
155  // check to see how face 2 is orientated
156  StdRegions::Orientation forient2 = e->GetForient(2);
157  StdRegions::Orientation forient0 = face0orient[fid];
158 
159  // If dir 1 or forient2 is bwd then check agains
160  // face 1 value
161  if((forient2 == StdRegions::eDir1BwdDir1_Dir2FwdDir2) ||
162  (forient2 == StdRegions::eDir1BwdDir1_Dir2BwdDir2) ||
163  (forient2 == StdRegions::eDir1BwdDir2_Dir2FwdDir1) ||
165  {
166  if(forient0 == StdRegions::eFwd)
167  {
168  prismorient.insert(i);
169  }
170  }
171  else
172  {
173  if(forient0 == StdRegions::eBwd)
174  {
175  prismorient.insert(i);
176  }
177  }
178  }
179  }
180  }
181 
182  for(int i = 0; i < nel; ++i)
183  {
184  e = m_f->m_exp[0]->GetExp(i);
185  if(m_config["tetonly"].m_beenSet)
186  {
187  if(m_f->m_exp[0]->GetExp(i)->DetShapeType() !=
189  {
190  continue;
191  }
192  }
193 
194  ppe.push_back(newpoints);
195  newtotpoints += newpoints;
196 
197  switch(e->DetShapeType())
198  {
200  {
201  int npoints0 = e->GetBasis(0)->GetNumPoints();
202 
203  newpoints = LibUtilities::StdSegData::
204  getNumberOfCoefficients(npoints0);
205  }
206  break;
208  {
209  int np0 = e->GetBasis(0)->GetNumPoints();
210  int np1 = e->GetBasis(1)->GetNumPoints();
211  int np = max(np0,np1);
212  newpoints = LibUtilities::StdTriData::
214  }
215  break;
217  {
218  int np0 = e->GetBasis(0)->GetNumPoints();
219  int np1 = e->GetBasis(1)->GetNumPoints();
220  int np = max(np0,np1);
221 
222  newpoints = LibUtilities::StdQuadData::
224  }
225  break;
227  {
228  int np0 = e->GetBasis(0)->GetNumPoints();
229  int np1 = e->GetBasis(1)->GetNumPoints();
230  int np2 = e->GetBasis(2)->GetNumPoints();
231  int np = max(np0,max(np1,np2));
232 
233  newpoints = LibUtilities::StdTetData::
234  getNumberOfCoefficients(np,np,np);
235  }
236  break;
238  {
239  int np0 = e->GetBasis(0)->GetNumPoints();
240  int np1 = e->GetBasis(1)->GetNumPoints();
241  int np2 = e->GetBasis(2)->GetNumPoints();
242  int np = max(np0,max(np1,np2));
243 
244  newpoints = LibUtilities::StdPrismData::
245  getNumberOfCoefficients(np,np,np);
246  }
247  break;
249  {
250  int np0 = e->GetBasis(0)->GetNumPoints();
251  int np1 = e->GetBasis(1)->GetNumPoints();
252  int np2 = e->GetBasis(2)->GetNumPoints();
253  int np = max(np0,max(np1,np2));
254 
255  newpoints = LibUtilities::StdPyrData::
256  getNumberOfCoefficients(np,np,np);
257  }
258  break;
260  {
261  int np0 = e->GetBasis(0)->GetNumPoints();
262  int np1 = e->GetBasis(1)->GetNumPoints();
263  int np2 = e->GetBasis(2)->GetNumPoints();
264  int np = max(np0,max(np1,np2));
265 
266  newpoints = LibUtilities::StdPyrData::
267  getNumberOfCoefficients(np,np,np);
268  }
269  break;
270  default:
271  {
272  ASSERTL0(false,"Points not known");
273  }
274  }
275 
276  if(e->DetShapeType() == LibUtilities::ePrism)
277  {
278  bool standard = true;
279 
280  if(prismorient.count(i))
281  {
282  standard = false; // reverse direction
283  }
284 
285  e->GetSimplexEquiSpacedConnectivity(conn,standard);
286  }
287  else
288  {
289 
290  if((prevNcoeffs != e->GetNcoeffs()) ||
291  (prevNpoints != e->GetTotPoints()))
292  {
293  prevNcoeffs = e->GetNcoeffs();
294  prevNpoints = e->GetTotPoints();
295 
296  e->GetSimplexEquiSpacedConnectivity(conn);
297  }
298  }
299  Array<OneD, int> newconn(conn.num_elements());
300  for(int j = 0; j < conn.num_elements(); ++j)
301  {
302  newconn[j] = conn[j] + cnt;
303  }
304 
305  ptsConn.push_back(newconn);
306  cnt += newpoints;
307  }
308 
309  if(m_f->m_fielddef.size())
310  {
311  nfields = m_f->m_exp.size();
312  }
313  else // just the mesh points
314  {
315  nfields = 0;
316  }
317 
318  Array<OneD, Array<OneD, NekDouble> > pts(nfields + coordim);
319 
320  for(int i = 0; i < nfields + coordim; ++i)
321  {
322  pts[i] = Array<OneD, NekDouble>(newtotpoints);
323  }
324 
325  // Interpolate coordinates
326  for(int i = 0; i < coordim; ++i)
327  {
328  coords[i] = Array<OneD, NekDouble>(npts);
329  }
330 
331  for(int i = coordim; i < 3; ++i)
332  {
333  coords[i] = NullNekDouble1DArray;
334  }
335 
336  m_f->m_exp[0]->GetCoords(coords[0],coords[1],coords[2]);
337 
338  int nq1 = m_f->m_exp[0]->GetTotPoints();
339 
340  Array<OneD, NekDouble> x1(nq1);
341  Array<OneD, NekDouble> y1(nq1);
342  Array<OneD, NekDouble> z1(nq1);
343 
344  m_f->m_exp[0]->GetCoords(x1, y1, z1);
345 
346 
348 
349  for(int n = 0; n < coordim; ++n)
350  {
351  cnt = 0;
352  int cnt1 = 0;
353  for(int i = 0; i < nel; ++i)
354  {
355  m_f->m_exp[0]->GetExp(i)->PhysInterpToSimplexEquiSpaced(
356  coords[n] + cnt,
357  tmp = pts[n] + cnt1);
358  cnt1 += ppe[i];
359  cnt += m_f->m_exp[0]->GetExp(i)->GetTotPoints();
360  }
361  }
362 
363  if(m_f->m_fielddef.size())
364  {
365  ASSERTL0(m_f->m_fielddef[0]->m_fields.size() == m_f->m_exp.size(),
366  "More expansion defined than fields");
367 
368  for(int n = 0; n < m_f->m_exp.size(); ++n)
369  {
370  cnt = 0;
371  int cnt1 = 0;
372 
373  if(m_config["modalenergy"].m_beenSet)
374  {
375  Array<OneD, const NekDouble> phys = m_f->m_exp[n]->GetPhys();
376  for(int i = 0; i < nel; ++i)
377  {
378  GenOrthoModes(i,phys+cnt,tmp = pts[coordim + n] + cnt1);
379  cnt1 += ppe[i];
380  cnt += m_f->m_exp[0]->GetExp(i)->GetTotPoints();
381  }
382  }
383  else
384  {
385  Array<OneD, const NekDouble> phys = m_f->m_exp[n]->GetPhys();
386  for(int i = 0; i < nel; ++i)
387  {
388  m_f->m_exp[0]->GetExp(i)->PhysInterpToSimplexEquiSpaced(
389  phys + cnt,
390  tmp = pts[coordim + n] + cnt1);
391  cnt1 += ppe[i];
392  cnt += m_f->m_exp[0]->GetExp(i)->GetTotPoints();
393  }
394  }
395 
396  // Set up Variable string.
397  fieldNames.push_back(m_f->m_fielddef[0]->m_fields[n]);
398  }
399  }
400 
401  m_f->m_fieldPts = MemoryManager<LibUtilities::PtsField>::AllocateSharedPtr(coordim, fieldNames, pts);
402  if (shapedim == 2)
403  {
404  m_f->m_fieldPts->SetPtsType(LibUtilities::ePtsTriBlock);
405  }
406  else if (shapedim == 3)
407  {
408  m_f->m_fieldPts->SetPtsType(LibUtilities::ePtsTetBlock);
409  }
410  m_f->m_fieldPts->SetConnectivity(ptsConn);
411 }
412 
413 
415  int n,
416  const Array<OneD,const NekDouble> &phys,
417  Array<OneD, NekDouble> &coeffs)
418  {
420  e = m_f->m_exp[0]->GetExp(n);
421 
422  switch(e->DetShapeType())
423  {
425  {
426  int np0 = e->GetBasis(0)->GetNumPoints();
427  int np1 = e->GetBasis(1)->GetNumPoints();
428  int np = max(np0,np1);
429 
430  // to ensure points are correctly projected to np need
431  // to increase the order slightly of coordinates
432  LibUtilities::PointsKey pa(np+1,e->GetPointsType(0));
433  LibUtilities::PointsKey pb(np,e->GetPointsType(1));
434  Array<OneD, NekDouble> tophys(np*(np+1));
435 
438  StdRegions::StdTriExp OrthoExp(Ba,Bb);
439 
440  // interpolate points to new phys points!
441  LibUtilities::Interp2D(e->GetBasis(0)->GetBasisKey(),
442  e->GetBasis(1)->GetBasisKey(),
443  phys,Ba,Bb,tophys);
444 
445  OrthoExp.FwdTrans(tophys,coeffs);
446  break;
447  }
449  {
450  int np0 = e->GetBasis(0)->GetNumPoints();
451  int np1 = e->GetBasis(1)->GetNumPoints();
452  int np = max(np0,np1);
453 
454  LibUtilities::PointsKey pa(np+1,e->GetPointsType(0));
455  LibUtilities::PointsKey pb(np+1,e->GetPointsType(1));
456  Array<OneD, NekDouble> tophys((np+1)*(np+1));
457 
460  StdRegions::StdQuadExp OrthoExp(Ba,Bb);
461 
462  // interpolate points to new phys points!
463  LibUtilities::Interp2D(e->GetBasis(0)->GetBasisKey(),
464  e->GetBasis(1)->GetBasisKey(),
465  phys,Ba,Bb,tophys);
466 
467  OrthoExp.FwdTrans(phys,coeffs);
468  break;
469  }
470  default:
471  ASSERTL0(false,"Shape needs setting up");
472  break;
473  }
474  }
475 
476 }
477 }
478 
479 
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:135
int getNumberOfCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:286
pair< ModuleType, string > ModuleKey
static Array< OneD, NekDouble > NullNekDouble1DArray
static boost::shared_ptr< DataType > AllocateSharedPtr()
Allocate a shared pointer from the memory pool.
virtual void Process()=0
map< string, ConfigOption > m_config
List of configuration values.
STL namespace.
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:186
FieldSharedPtr m_f
Field object.
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
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< Field > FieldSharedPtr
Definition: Field.hpp:677
Represents a command-line configuration option.
int getNumberOfCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:232
int getNumberOfCoefficients(int Na, int Nb)
Definition: ShapeType.hpp:132
boost::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:68
Describes the specification for a Basis.
Definition: Basis.h:50
ModuleFactory & GetModuleFactory()
Abstract base class for processing modules.
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...