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