Nektar++
NodalPrismElec.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File NodalPrismElec.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 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 //
31 // Description: 3D Nodal Prism eletrostatic Point Definitions
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
35 #include <boost/core/ignore_unused.hpp>
36 
41 #include <vector>
42 
43 namespace Nektar
44 {
45 namespace LibUtilities
46 {
47 
50 };
51 
52 namespace
53 {
54 bool isVertex(int t, int y, int npts)
55 {
56  return (t == 0 && y == 0) || (t == 1 && y == 0) || (t == 2 && y == 0) ||
57  (t == 0 && y == (npts - 1)) || (t == 1 && y == (npts - 1)) ||
58  (t == 2 && y == (npts - 1));
59 }
60 
61 bool isEdge_01(int t, int y, int npts)
62 {
63  return y == 0 && t > 2 && t <= npts;
64 }
65 
66 bool isEdge_12(int t, int y, int npts)
67 {
68  boost::ignore_unused(y, npts);
69  return t == 1;
70 }
71 
72 bool isEdge_23(int t, int y, int npts)
73 {
74  return y == (npts - 1) && t > 2 && t <= npts;
75 }
76 
77 bool isEdge_30(int t, int y, int npts)
78 {
79  boost::ignore_unused(y, npts);
80  return t == 0;
81 }
82 
83 bool isEdge_04(int t, int y, int npts)
84 {
85  return y == 0 && t >= 3 + 2 * (npts - 2) && t < 3 + 3 * (npts - 2);
86 }
87 
88 bool isEdge_14(int t, int y, int npts)
89 {
90  return y == 0 && t >= 3 + (npts - 2) && t < 3 + 2 * (npts - 2);
91 }
92 
93 bool isEdge_25(int t, int y, int npts)
94 {
95  return y == npts - 1 && t >= 3 + (npts - 2) && t < 3 + 2 * (npts - 2);
96 }
97 
98 bool isEdge_35(int t, int y, int npts)
99 {
100  return y == npts - 1 && t >= 3 + 2 * (npts - 2) && t < 3 + 3 * (npts - 2);
101 }
102 
103 bool isEdge_45(int t, int y, int npts)
104 {
105  boost::ignore_unused(y, npts);
106  return t == 2;
107 }
108 
109 bool isEdge(int t, int y, int npts)
110 {
111  return isEdge_01(t, y, npts) || isEdge_12(t, y, npts) ||
112  isEdge_23(t, y, npts) || isEdge_30(t, y, npts) ||
113  isEdge_04(t, y, npts) || isEdge_14(t, y, npts) ||
114  isEdge_25(t, y, npts) || isEdge_35(t, y, npts) ||
115  isEdge_45(t, y, npts);
116 }
117 
118 bool isFace_0123(int t, int y, int npts)
119 {
120  boost::ignore_unused(y);
121  return t < 3 + (npts - 2);
122 }
123 
124 bool isFace_014(int t, int y, int npts)
125 {
126  boost::ignore_unused(t, npts);
127  return y == 0;
128 }
129 
130 bool isFace_1254(int t, int y, int npts)
131 {
132  boost::ignore_unused(y);
133  return t < 3 + 2 * (npts - 2) && t >= 3 + (npts - 2);
134 }
135 
136 bool isFace_325(int t, int y, int npts)
137 {
138  boost::ignore_unused(t);
139  return y == (npts - 1);
140 }
141 
142 bool isFace_0354(int t, int y, int npts)
143 {
144  boost::ignore_unused(y);
145  return t < 3 + 3 * (npts - 2) && t >= 3 + 2 * (npts - 2);
146 }
147 
148 bool isFace(int t, int y, int npts)
149 {
150  return isFace_0123(t, y, npts) || isFace_014(t, y, npts) ||
151  isFace_1254(t, y, npts) || isFace_325(t, y, npts) ||
152  isFace_0354(t, y, npts);
153 }
154 }
155 
156 // Calculate evenly spaced number of points
158 {
159  // Allocate the storage for points
161 
162  // Populate m_points
163  unsigned int npts = GetNumPoints();
164 
166  Array<OneD, NekDouble> u1, v1;
167  LibUtilities::PointsManager()[pkey1]->GetPoints(u1, v1);
170  LibUtilities::PointsManager()[pkey2]->GetPoints(u);
171 
172  for (unsigned int y = 0, index = 0; y < npts; y++)
173  {
174  for (size_t t = 0; t < u1.num_elements(); t++, index++)
175  {
176  m_points[0][index] = u1[t];
177  m_points[1][index] = u[y];
178  m_points[2][index] = v1[t];
179  }
180  }
181 
184  npts - 1, m_points[0], m_points[1], m_points[2]);
185 }
186 
188 {
189  unsigned int npts = GetNumPoints();
190  using std::vector;
191  vector<int> vertex;
192  vector<int> iEdge_01; // interior edge 0
193  vector<int> iEdge_12; // interior edge 1
194  vector<int> iEdge_23; // interior edge 2
195  vector<int> iEdge_30; // interior edge 3
196  vector<int> iEdge_04; // interior edge 4
197  vector<int> iEdge_14; // interior edge 5
198  vector<int> iEdge_25; // interior edge 6
199  vector<int> iEdge_35; // interior edge 7
200  vector<int> iEdge_45; // interior edge 8
201  vector<int> iFace_0123; // interior face 0
202  vector<int> iFace_014; // interior face 1
203  vector<int> iFace_1254; // interior face 2
204  vector<int> iFace_325; // interior face 3
205  vector<int> iFace_0354; // interior face 4
206  vector<int> interiorVolumePoints; // interior volume points
207  vector<int> map;
208 
209  // Build the lattice prism left to right - bottom to top
210  for (unsigned int y = 0, index = 0; y < npts; y++)
211  {
212  for (unsigned int t = 0; t < npts * (npts + 1) / 2; t++, index++)
213  {
214  if (isVertex(t, y, npts))
215  {
216  vertex.push_back(index);
217  }
218  else if (isEdge(t, y, npts))
219  {
220  if (isEdge_01(t, y, npts))
221  {
222  iEdge_01.push_back(index);
223  }
224  else if (isEdge_12(t, y, npts))
225  {
226  iEdge_12.push_back(index);
227  }
228  else if (isEdge_23(t, y, npts))
229  {
230  iEdge_23.push_back(index);
231  }
232  else if (isEdge_30(t, y, npts))
233  {
234  iEdge_30.push_back(index);
235  }
236  else if (isEdge_04(t, y, npts))
237  {
238  iEdge_04.push_back(index);
239  }
240  else if (isEdge_14(t, y, npts))
241  {
242  iEdge_14.push_back(index);
243  }
244  else if (isEdge_25(t, y, npts))
245  {
246  iEdge_25.push_back(index);
247  }
248  else if (isEdge_35(t, y, npts))
249  {
250  iEdge_35.push_back(index);
251  }
252  else if (isEdge_45(t, y, npts))
253  {
254  iEdge_45.push_back(index);
255  }
256  }
257  else if (isFace(t, y, npts))
258  {
259  if (isFace_0123(t, y, npts))
260  {
261  iFace_0123.push_back(index);
262  }
263  else if (isFace_014(t, y, npts))
264  {
265  iFace_014.push_back(index);
266  }
267  else if (isFace_1254(t, y, npts))
268  {
269  iFace_1254.push_back(index);
270  }
271  else if (isFace_325(t, y, npts))
272  {
273  iFace_325.push_back(index);
274  }
275  else if (isFace_0354(t, y, npts))
276  {
277  iFace_0354.push_back(index);
278  }
279  }
280  else
281  {
282  interiorVolumePoints.push_back(index);
283  }
284  }
285  }
286 
287  // sort vertices
288  std::swap(vertex[2], vertex[4]);
289  // sort edges
290  std::reverse(iEdge_23.begin(), iEdge_23.end());
291  std::reverse(iEdge_30.begin(), iEdge_30.end());
292  std::reverse(iEdge_04.begin(), iEdge_04.end());
293  std::reverse(iEdge_35.begin(), iEdge_35.end());
294 
295  // faces
296  for (unsigned int i = 0; i < npts - 2; i++)
297  {
298  for (unsigned int j = i + 1; j < npts - 2; j++)
299  {
300  std::swap(iFace_1254[i * (npts - 2) + j],
301  iFace_1254[j * (npts - 2) + i]);
302  }
303  }
304  for (int i = 0; i < npts - 2; i++)
305  {
306  std::reverse(iFace_0354.begin() + (i * (npts - 2)),
307  iFace_0354.begin() + (i * (npts - 2) + npts - 2));
308  }
309  for (unsigned int i = 0; i < npts - 2; i++)
310  {
311  for (unsigned int j = i + 1; j < npts - 2; j++)
312  {
313  std::swap(iFace_0354[i * (npts - 2) + j],
314  iFace_0354[j * (npts - 2) + i]);
315  }
316  }
317 
318  for (unsigned int n = 0; n < vertex.size(); ++n)
319  {
320  map.push_back(vertex[n]);
321  }
322 
323  for (unsigned int n = 0; n < iEdge_01.size(); ++n)
324  {
325  map.push_back(iEdge_01[n]);
326  }
327 
328  for (unsigned int n = 0; n < iEdge_12.size(); ++n)
329  {
330  map.push_back(iEdge_12[n]);
331  }
332 
333  for (unsigned int n = 0; n < iEdge_23.size(); ++n)
334  {
335  map.push_back(iEdge_23[n]);
336  }
337 
338  for (unsigned int n = 0; n < iEdge_30.size(); ++n)
339  {
340  map.push_back(iEdge_30[n]);
341  }
342 
343  for (unsigned int n = 0; n < iEdge_04.size(); ++n)
344  {
345  map.push_back(iEdge_04[n]);
346  }
347 
348  for (unsigned int n = 0; n < iEdge_14.size(); ++n)
349  {
350  map.push_back(iEdge_14[n]);
351  }
352 
353  for (unsigned int n = 0; n < iEdge_25.size(); ++n)
354  {
355  map.push_back(iEdge_25[n]);
356  }
357 
358  for (unsigned int n = 0; n < iEdge_35.size(); ++n)
359  {
360  map.push_back(iEdge_35[n]);
361  }
362 
363  for (unsigned int n = 0; n < iEdge_45.size(); ++n)
364  {
365  map.push_back(iEdge_45[n]);
366  }
367 
368  for (unsigned int n = 0; n < iFace_0123.size(); ++n)
369  {
370  map.push_back(iFace_0123[n]);
371  }
372 
373  for (unsigned int n = 0; n < iFace_014.size(); ++n)
374  {
375  map.push_back(iFace_014[n]);
376  }
377 
378  for (unsigned int n = 0; n < iFace_1254.size(); ++n)
379  {
380  map.push_back(iFace_1254[n]);
381  }
382 
383  for (unsigned int n = 0; n < iFace_325.size(); ++n)
384  {
385  map.push_back(iFace_325[n]);
386  }
387 
388  for (unsigned int n = 0; n < iFace_0354.size(); ++n)
389  {
390  map.push_back(iFace_0354[n]);
391  }
392 
393  for (unsigned int n = 0; n < interiorVolumePoints.size(); ++n)
394  {
395  map.push_back(interiorVolumePoints[n]);
396  }
397 
398  Array<OneD, NekDouble> points[3];
402 
403  for (unsigned int index = 0; index < map.size(); ++index)
404  {
405  points[0][index] = m_points[0][index];
406  points[1][index] = m_points[1][index];
407  points[2][index] = m_points[2][index];
408  }
409 
410  for (unsigned int index = 0; index < map.size(); ++index)
411  {
412  m_points[0][index] = points[0][map[index]];
413  m_points[1][index] = points[1][map[index]];
414  m_points[2][index] = points[2][map[index]];
415  }
416 }
417 
419 {
420  // Allocate the storage for points
422 
423  typedef DataType T;
424 
425  // Solve the Vandermonde system of integrals for the weight vector
426  NekVector<T> w = m_util->GetWeights();
427 
429 }
430 
431 // ////////////////////////////////////////
432 // CalculateInterpMatrix()
434  const Array<OneD, const NekDouble> &xia,
435  const Array<OneD, const NekDouble> &yia,
437 {
439  xi[0] = xia;
440  xi[1] = yia;
441  xi[1] = zia;
442 
443  std::shared_ptr<NekMatrix<NekDouble> > mat =
444  m_util->GetInterpolationMatrix(xi);
445  Vmath::Vcopy(mat->GetRows() * mat->GetColumns(), mat->GetRawPtr(), 1,
446  &interp[0], 1);
447 }
448 
449 // ////////////////////////////////////////
450 // CalculateDerivMatrix()
452 {
453  // Allocate the derivative matrix.
455 
456  m_derivmatrix[0] = m_util->GetDerivMatrix(0);
457  m_derivmatrix[1] = m_util->GetDerivMatrix(1);
458  m_derivmatrix[2] = m_util->GetDerivMatrix(2);
459 }
460 
461 std::shared_ptr<PointsBaseType> NodalPrismElec::Create(const PointsKey &key)
462 {
463  std::shared_ptr<PointsBaseType> returnval(
465 
466  returnval->Initialize();
467 
468  return returnval;
469 }
470 
471 }
472 }
Array< OneD, DataType > m_weights
Definition: Points.h:382
static std::shared_ptr< PointsBaseType > Create(const PointsKey &key)
General purpose memory allocation routines with the ability to allocate from thread specific memory p...
void CalculateInterpMatrix(const Array< OneD, const NekDouble > &xi, const Array< OneD, const NekDouble > &yi, const Array< OneD, const NekDouble > &zi, Array< OneD, NekDouble > &interp)
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
PointsManagerT & PointsManager(void)
Defines a specification for a set of points.
Definition: Points.h:59
unsigned int GetTotNumPoints() const
Definition: Points.h:277
Array< OneD, DataType > m_points[3]
Definition: Points.h:381
bool RegisterCreator(const KeyType &key, const CreateFuncType &createFunc)
Register the given function and associate it with the key. The return value is just to facilitate cal...
Definition: NekManager.hpp:166
unsigned int GetRows() const
Definition: NekVector.cpp:215
MatrixSharedPtrType m_derivmatrix[3]
Definition: Points.h:383
std::shared_ptr< NodalUtilPrism > m_util
unsigned int GetNumPoints() const
Definition: Points.h:272
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1064
Array< OneD, DataType > & GetPtr()
Definition: NekVector.cpp:227
1D Gauss-Lobatto-Legendre quadrature points
Definition: PointsType.h:51
2D Nodal Electrostatic Points on a Triangle
Definition: PointsType.h:69
3D electrostatically spaced points on a Prism
Definition: PointsType.h:75