Nektar++
NodalTetEvenlySpaced.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: NodalTetEvenlySpaced.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 Tetrahedron Evenly Spaced Point Definitions
32//
33///////////////////////////////////////////////////////////////////////////////
34
35#include <boost/core/ignore_unused.hpp>
36
38#include <vector>
39
40namespace Nektar
41{
42namespace LibUtilities
43{
47
48namespace
49{
50// construct the geometory and set the coordinate of tetrahedron
51// edges and vertices are ordered as anticlockwise
52
53bool isVertex(size_t x, size_t y, size_t z, size_t npts)
54{
55 return (x == 0 && y == 0 && z == 0) ||
56 (x == (npts - 1) && y == 0 && z == 0) ||
57 (x == 0 && y == (npts - 1) && z == 0) ||
58 (x == 0 && y == 0 && z == (npts - 1));
59}
60
61bool isEdge_01(size_t x, size_t y, size_t z, size_t npts)
62{ // edge 0
63 boost::ignore_unused(x, npts);
64 return y == 0 && z == 0;
65}
66
67bool isEdge_12(size_t x, size_t y, size_t z, size_t npts)
68{ // edge 1
69 return z == 0 && x + y == npts - 1;
70}
71
72bool isEdge_20(size_t x, size_t y, size_t z, size_t npts)
73{ // edge 2
74 boost::ignore_unused(y, npts);
75 return x == 0 && z == 0;
76}
77
78bool isEdge_03(size_t x, size_t y, size_t z, size_t npts)
79{ // edge 3
80 boost::ignore_unused(z, npts);
81 return x == 0 && y == 0;
82}
83
84bool isEdge_13(size_t x, size_t y, size_t z, size_t npts)
85{ // edge 4
86 return y == 0 && x + z == npts - 1;
87}
88
89bool isEdge_23(size_t x, size_t y, size_t z, size_t npts)
90{ // edge 5
91 return x == 0 && y + z == npts - 1;
92}
93
94bool isEdge(size_t x, size_t y, size_t z, size_t npts)
95{
96 return isEdge_01(x, y, z, npts) || isEdge_12(x, y, z, npts) ||
97 isEdge_20(x, y, z, npts) || isEdge_03(x, y, z, npts) ||
98 isEdge_13(x, y, z, npts) || isEdge_23(x, y, z, npts);
99}
100
101bool isFace_012(size_t x, size_t y, size_t z, size_t npts)
102{ // bottom face (face 0)
103 boost::ignore_unused(x, y, npts);
104 return z == 0;
105}
106
107bool isFace_013(size_t x, size_t y, size_t z, size_t npts)
108{ // face 1
109 boost::ignore_unused(x, z, npts);
110 return y == 0;
111}
112
113bool isFace_123(size_t x, size_t y, size_t z, size_t npts)
114{ // face 2
115 return x + y + z == npts - 1;
116}
117
118bool isFace_203(size_t x, size_t y, size_t z, size_t npts)
119{ // face 3
120 boost::ignore_unused(y, z, npts);
121 return x == 0;
122}
123
124bool isFace(size_t x, size_t y, size_t z, size_t npts)
125{
126 return isFace_012(x, y, z, npts) || isFace_013(x, y, z, npts) ||
127 isFace_123(x, y, z, npts) || isFace_203(x, y, z, npts);
128}
129} // namespace
130
131// Calculate evenly spaced number of points
133{
134 // Allocate the storage for points
136
137 // Populate m_points
138 size_t npts = GetNumPoints();
139 NekDouble delta = 2.0 / (npts - 1.0);
140 for (size_t z = 0, index = 0; z < npts; ++z)
141 {
142 for (size_t y = 0; y < npts - z; ++y)
143 {
144 for (size_t x = 0; x < npts - z - y; ++x, ++index)
145 {
146 NekDouble xi = -1.0 + x * delta;
147 NekDouble yi = -1.0 + y * delta;
148 NekDouble zi = -1.0 + z * delta;
149
150 m_points[0][index] = xi;
151 m_points[1][index] = yi;
152 m_points[2][index] = zi;
153 }
154 }
155 }
156
159 npts - 1, m_points[0], m_points[1], m_points[2]);
160}
161
163{
164 size_t npts = GetNumPoints();
165 using std::vector;
166 vector<int> vertex;
167 vector<int> iEdge_01; // interior edge 0
168 vector<int> iEdge_12; // interior edge 1
169 vector<int> iEdge_20; // interior edge 2
170 vector<int> iEdge_03; // interior edge 3
171 vector<int> iEdge_13; // interior edge 4
172 vector<int> iEdge_23; // interior edge 5
173 vector<int> iFace_012; // interior face 0
174 vector<int> iFace_013; // interior face 1
175 vector<int> iFace_123; // interior face 2
176 vector<int> iFace_203; // interior face 3
177 vector<int> interiorVolumePoints; // interior volume points
178 vector<int> map;
179
180 // Build the lattice tetrahedron left to right - bottom to top
181 for (size_t z = 0, index = 0; z < npts; ++z)
182 {
183 for (size_t y = 0; y < npts - z; ++y)
184 {
185 for (size_t x = 0; x < npts - z - y; ++x, ++index)
186 {
187
188 if (isVertex(x, y, z, npts))
189 { // vertex
190
191 vertex.push_back(index);
192 }
193 else if (isEdge(x, y, z, npts))
194 { // interior edge
195
196 if (isEdge_01(x, y, z, npts))
197 { // interior edge 0
198
199 iEdge_01.push_back(index);
200 }
201 else if (isEdge_12(x, y, z, npts))
202 { // interior edge 1
203
204 iEdge_12.push_back(index);
205 }
206 else if (isEdge_20(x, y, z, npts))
207 { // interior edge 2
208
209 iEdge_20.insert(iEdge_20.begin(), index);
210 }
211 else if (isEdge_03(x, y, z, npts))
212 { // interior edge 3
213
214 iEdge_03.push_back(index);
215 }
216 else if (isEdge_13(x, y, z, npts))
217 { // interior edge 4
218
219 iEdge_13.push_back(index);
220 }
221 else if (isEdge_23(x, y, z, npts))
222 { // interior edge 5
223
224 iEdge_23.push_back(index);
225 }
226 }
227 else if (isFace(x, y, z, npts))
228 { // interior face
229
230 if (isFace_012(x, y, z, npts))
231 { // interior face 0
232
233 iFace_012.push_back(index);
234 }
235 else if (isFace_013(x, y, z, npts))
236 { // interior face 1
237
238 iFace_013.push_back(index);
239 }
240 else if (isFace_123(x, y, z, npts))
241 { // interior face 2
242
243 iFace_123.push_back(index);
244 }
245 else if (isFace_203(x, y, z, npts))
246 { // interior face 3
247
248 iFace_203.push_back(index);
249 }
250 }
251 else
252 { // interior volume points
253
254 interiorVolumePoints.push_back(index);
255 }
256 }
257 }
258 }
259
260 // Mapping the vertex, edges, faces, interior volume points using the
261 // permutation matrix, so the points are ordered anticlockwise.
262 for (size_t n = 0; n < vertex.size(); ++n)
263 {
264
265 map.push_back(vertex[n]);
266 }
267
268 for (size_t n = 0; n < iEdge_01.size(); ++n)
269 {
270
271 map.push_back(iEdge_01[n]);
272 }
273
274 for (size_t n = 0; n < iEdge_12.size(); ++n)
275 {
276
277 map.push_back(iEdge_12[n]);
278 }
279
280 for (size_t n = 0; n < iEdge_20.size(); ++n)
281 {
282
283 map.push_back(iEdge_20[n]);
284 }
285
286 for (size_t n = 0; n < iEdge_03.size(); ++n)
287 {
288
289 map.push_back(iEdge_03[n]);
290 }
291
292 for (size_t n = 0; n < iEdge_13.size(); ++n)
293 {
294
295 map.push_back(iEdge_13[n]);
296 }
297
298 for (size_t n = 0; n < iEdge_23.size(); ++n)
299 {
300
301 map.push_back(iEdge_23[n]);
302 }
303
304 for (size_t n = 0; n < iFace_012.size(); ++n)
305 {
306
307 map.push_back(iFace_012[n]);
308 }
309
310 for (size_t n = 0; n < iFace_013.size(); ++n)
311 {
312
313 map.push_back(iFace_013[n]);
314 }
315
316 for (size_t n = 0; n < iFace_123.size(); ++n)
317 {
318
319 map.push_back(iFace_123[n]);
320 }
321
322 for (size_t n = 0; n < iFace_203.size(); ++n)
323 {
324
325 map.push_back(iFace_203[n]);
326 }
327
328 for (size_t n = 0; n < interiorVolumePoints.size(); ++n)
329 {
330
331 map.push_back(interiorVolumePoints[n]);
332 }
333
334 Array<OneD, NekDouble> points[3];
338 for (size_t index = 0; index < map.size(); ++index)
339 {
340
341 points[0][index] = m_points[0][index];
342 points[1][index] = m_points[1][index];
343 points[2][index] = m_points[2][index];
344 }
345
346 for (size_t index = 0; index < map.size(); ++index)
347 {
348
349 m_points[0][index] = points[0][map[index]];
350 m_points[1][index] = points[1][map[index]];
351 m_points[2][index] = points[2][map[index]];
352 }
353}
354
356{
357 // Allocate storage for points
359
360 typedef DataType T;
361
362 // Solve the Vandermonde system of integrals for the weight vector
363 NekVector<T> w = m_util->GetWeights();
364 m_weights = Array<OneD, T>(w.GetRows(), w.GetPtr());
365}
366
367// ////////////////////////////////////////
368// CalculateInterpMatrix()
373{
375 xi[0] = xia;
376 xi[1] = yia;
377 xi[2] = zia;
378
379 std::shared_ptr<NekMatrix<NekDouble>> mat =
380 m_util->GetInterpolationMatrix(xi);
381 Vmath::Vcopy(mat->GetRows() * mat->GetColumns(), mat->GetRawPtr(), 1,
382 &interp[0], 1);
383}
384
385// ////////////////////////////////////////
386// CalculateDerivMatrix()
388{
389 // Allocate the derivative matrix.
390 PointsBaseType::v_CalculateDerivMatrix();
391
392 m_derivmatrix[0] = m_util->GetDerivMatrix(0);
393 m_derivmatrix[1] = m_util->GetDerivMatrix(1);
394 m_derivmatrix[2] = m_util->GetDerivMatrix(2);
395}
396
397std::shared_ptr<PointsBaseType> NodalTetEvenlySpaced::Create(
398 const PointsKey &key)
399{
400 std::shared_ptr<PointsBaseType> returnval(
402
403 returnval->Initialize();
404
405 return returnval;
406}
407
408} // namespace LibUtilities
409} // namespace Nektar
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:169
virtual void v_CalculateDerivMatrix() override final
std::shared_ptr< NodalUtilTetrahedron > m_util
void CalculateInterpMatrix(const Array< OneD, const NekDouble > &xi, const Array< OneD, const NekDouble > &yi, const Array< OneD, const NekDouble > &zi, Array< OneD, NekDouble > &interp)
virtual void v_CalculateWeights() override final
static std::shared_ptr< PointsBaseType > Create(const PointsKey &key)
Array< OneD, DataType > m_points[3]
Storage for the point locations, allowing for up to a 3D points storage.
Definition: Points.h:361
MatrixSharedPtrType m_derivmatrix[3]
Derivative matrices.
Definition: Points.h:367
Array< OneD, DataType > m_weights
Quadrature weights for the weights.
Definition: Points.h:363
Defines a specification for a set of points.
Definition: Points.h:55
General purpose memory allocation routines with the ability to allocate from thread specific memory p...
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
PointsManagerT & PointsManager(void)
@ eNodalTetEvenlySpaced
3D Evenly-spaced points on a Tetrahedron
Definition: PointsType.h:86
std::vector< double > w(NPUPPER)
std::vector< double > z(NPUPPER)
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
double NekDouble
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1191