Nektar++
CoalescedGeomData.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File: CoalescedGeomData.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: Coalesced geometry data definition
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
37 
38 #include <LocalRegions/Expansion.h>
39 
40 using namespace std;
41 
42 namespace Nektar
43 {
44 namespace Collections
45 {
46 
47 CoalescedGeomData::CoalescedGeomData(void)
48 {
49 }
50 
51 CoalescedGeomData::~CoalescedGeomData(void)
52 {
53 }
54 
55 const Array<OneD, const NekDouble> &CoalescedGeomData::GetJac(
56  vector<StdRegions::StdExpansionSharedPtr> &pCollExp)
57 {
58 
59  if (m_oneDGeomData.count(eJac) == 0)
60  {
61 
62  LibUtilities::PointsKeyVector ptsKeys = pCollExp[0]->GetPointsKeys();
63  int nElmts = pCollExp.size();
64 
65  // set up Cached Jacobians to be continuous
66  int npts = 1;
67  for (int i = 0; i < ptsKeys.size(); ++i)
68  {
69  npts *= ptsKeys[i].GetNumPoints();
70  }
71 
72  if (IsDeformed(pCollExp))
73  {
74  Array<OneD, NekDouble> newjac(npts * nElmts);
75 
76  // copy Jacobians into a continuous list and set new chatched value
77  int cnt = 0;
78  for (int i = 0; i < nElmts; ++i)
79  {
80  const StdRegions::StdExpansion *sep = &(*pCollExp[i]);
81  const LocalRegions::Expansion *lep =
82  dynamic_cast<const LocalRegions::Expansion *>(sep);
83 
85  lep->GetMetricInfo()->GetJac(ptsKeys);
86 
87  Vmath::Vcopy(npts, &jac[0], 1, &newjac[cnt], 1);
88 
89  cnt += npts;
90  }
91 
92  m_oneDGeomData[eJac] = newjac;
93  }
94  else
95  {
96  Array<OneD, NekDouble> newjac(nElmts);
97  // copy Jacobians into a continuous list
98  for (int i = 0; i < nElmts; ++i)
99  {
100  const StdRegions::StdExpansion *sep = &(*pCollExp[i]);
101  const LocalRegions::Expansion *lep =
102  dynamic_cast<const LocalRegions::Expansion *>(sep);
103 
104  const Array<OneD, const NekDouble> jac =
105  lep->GetMetricInfo()->GetJac(ptsKeys);
106 
107  newjac[i] = jac[0];
108  }
109  m_oneDGeomData[eJac] = newjac;
110  }
111  }
112 
113  return m_oneDGeomData[eJac];
114 }
115 
116 const std::shared_ptr<VecVec_t> CoalescedGeomData::GetJacInterLeave(
117  vector<StdRegions::StdExpansionSharedPtr> &pCollExp, int nElmt)
118 {
119 
120  if (m_oneDGeomDataInterLeave.count(eJac) == 0)
121  {
122  const Array<OneD, const NekDouble> jac = GetJac(pCollExp);
123  int jacsize = jac.size();
124 
125  ASSERTL1(nElmt % vec_t::width == 0,
126  "Number of elements not divisible by vector "
127  "width, padding not yet implemented.");
128  int nBlocks = nElmt / vec_t::width;
129 
130  VecVec_t newjac;
131 
132  LibUtilities::PointsKeyVector ptsKeys = pCollExp[0]->GetPointsKeys();
133 
134  // set up Cached Jacobians to be continuous
135  int nq = 1;
136  for (int i = 0; i < ptsKeys.size(); ++i)
137  {
138  nq *= ptsKeys[i].GetNumPoints();
139  }
140 
141  if (IsDeformed(pCollExp))
142  {
143 
144  newjac.resize(nBlocks * nq);
145 
146  alignas(vec_t::alignment) NekDouble tmp[vec_t::width];
147 
148  for (size_t block = 0; block < nBlocks; ++block)
149  {
150  size_t nblock_width = block * nq * vec_t::width;
151  for (size_t q = 0; q < nq; q++)
152  {
153  for (int j = 0; j < vec_t::width; ++j)
154  {
155  if (nblock_width + nq * j + q < jacsize)
156  {
157  tmp[j] = jac[nblock_width + nq * j + q];
158  }
159  else
160  {
161  tmp[j] = 0.0;
162  }
163  }
164 
165  // Order is [block][quadpt]
166  newjac[block * nq + q].load(&tmp[0]);
167  }
168  }
169  }
170  else
171  {
172  newjac.resize(nBlocks);
173 
174  alignas(vec_t::alignment) NekDouble tmp[vec_t::width];
175  for (size_t i = 0; i < nBlocks; ++i)
176  {
177  for (int j = 0; j < vec_t::width; ++j)
178  {
179  if (vec_t::width * i + j < jacsize)
180  {
181  tmp[j] = jac[vec_t::width * i + j];
182  }
183  else
184  {
185  tmp[j] = 0.0;
186  }
187  }
188 
189  newjac[i].load(&tmp[0]);
190  }
191  }
192 
193  m_oneDGeomDataInterLeave[eJac] =
195  }
196 
197  return m_oneDGeomDataInterLeave[eJac];
198 }
199 
200 const Array<OneD, const NekDouble> &CoalescedGeomData::GetJacWithStdWeights(
201  vector<StdRegions::StdExpansionSharedPtr> &pCollExp)
202 {
203  if (m_oneDGeomData.count(eJacWithStdWeights) == 0)
204  {
205  LibUtilities::PointsKeyVector ptsKeys = pCollExp[0]->GetPointsKeys();
206  int nElmts = pCollExp.size();
207 
208  // set up Cached Jacobians to be continuous
209  int npts = 1;
210  for (int i = 0; i < ptsKeys.size(); ++i)
211  {
212  npts *= ptsKeys[i].GetNumPoints();
213  }
214 
215  Array<OneD, NekDouble> newjac(npts * nElmts), tmp;
216 
217  // copy Jacobians into a continuous list and set new chatched value
218  int cnt = 0;
219  for (int i = 0; i < nElmts; ++i)
220  {
221  const StdRegions::StdExpansion *sep = &(*pCollExp[i]);
222  const LocalRegions::Expansion *lep =
223  dynamic_cast<const LocalRegions::Expansion *>(sep);
224 
225  const Array<OneD, const NekDouble> jac =
226  lep->GetMetricInfo()->GetJac(ptsKeys);
227 
228  if (lep->GetMetricInfo()->GetGtype() == SpatialDomains::eDeformed)
229  {
230  Vmath::Vcopy(npts, &jac[0], 1, &newjac[cnt], 1);
231  }
232  else
233  {
234  Vmath::Fill(npts, jac[0], &newjac[cnt], 1);
235  }
236 
237  pCollExp[0]->MultiplyByStdQuadratureMetric(newjac + cnt,
238  tmp = newjac + cnt);
239  cnt += npts;
240  }
241 
242  m_oneDGeomData[eJacWithStdWeights] = newjac;
243  }
244 
245  return m_oneDGeomData[eJacWithStdWeights];
246 }
247 
248 const Array<TwoD, const NekDouble> &CoalescedGeomData::GetDerivFactors(
249  vector<StdRegions::StdExpansionSharedPtr> &pCollExp)
250 {
251  if (m_twoDGeomData.count(eDerivFactors) == 0)
252  {
253  LibUtilities::PointsKeyVector ptsKeys = pCollExp[0]->GetPointsKeys();
254 
255  int nElmts = pCollExp.size();
256  const int coordim = pCollExp[0]->GetCoordim();
257  int dim = ptsKeys.size();
258 
259  // set up Cached Jacobians to be continuous
260  int npts = 1;
261  for (int i = 0; i < dim; ++i)
262  {
263  npts *= ptsKeys[i].GetNumPoints();
264  }
265 
266  Array<TwoD, NekDouble> newDFac;
267 
268  if (IsDeformed(pCollExp))
269  {
270  newDFac = Array<TwoD, NekDouble>(dim * coordim, npts * nElmts);
271  }
272  else
273  {
274  newDFac = Array<TwoD, NekDouble>(dim * coordim, nElmts);
275  }
276 
277  // copy Jacobians into a continuous list and set new chatched value
278  int cnt = 0;
279  for (int i = 0; i < nElmts; ++i)
280  {
281  const StdRegions::StdExpansion *sep = &(*pCollExp[i]);
282  const LocalRegions::Expansion *lep =
283  dynamic_cast<const LocalRegions::Expansion *>(sep);
284 
285  const Array<TwoD, const NekDouble> Dfac =
286  lep->GetMetricInfo()->GetDerivFactors(ptsKeys);
287 
288  if (IsDeformed(pCollExp))
289  {
290  for (int j = 0; j < dim * coordim; ++j)
291  {
292  Vmath::Vcopy(npts, &Dfac[j][0], 1, &newDFac[j][cnt], 1);
293  }
294  }
295  else
296  {
297  for (int j = 0; j < dim * coordim; ++j)
298  {
299  newDFac[j][i] = Dfac[j][0];
300  }
301  }
302  cnt += npts;
303  }
304 
305  m_twoDGeomData[eDerivFactors] = newDFac;
306  }
307 
308  return m_twoDGeomData[eDerivFactors];
309 }
310 
311 const std::shared_ptr<VecVec_t> CoalescedGeomData::GetDerivFactorsInterLeave(
312  vector<StdRegions::StdExpansionSharedPtr> &pCollExp, int nElmt)
313 {
314  if (m_twoDGeomDataInterLeave.count(eDerivFactors) == 0)
315  {
316  ASSERTL1(nElmt % vec_t::width == 0,
317  "Number of elements not divisible by vector "
318  "width, padding not yet implemented.");
319 
320  int nBlocks = nElmt / vec_t::width;
321 
322  LibUtilities::PointsKeyVector ptsKeys = pCollExp[0]->GetPointsKeys();
323  const int coordim = pCollExp[0]->GetCoordim();
324  int dim = ptsKeys.size();
325 
326  unsigned int n_df = coordim * dim;
327  alignas(vec_t::alignment) NekDouble vec[vec_t::width];
328 
329  const Array<TwoD, const NekDouble> df = GetDerivFactors(pCollExp);
330  int dfsize = df.GetColumns();
331 
332  VecVec_t newdf;
333 
334  int nq = 1;
335  for (int i = 0; i < dim; ++i)
336  {
337  nq *= ptsKeys[i].GetNumPoints();
338  }
339 
340  if (IsDeformed(pCollExp))
341  {
342  newdf.resize(nBlocks * n_df * nq);
343  auto *df_ptr = &newdf[0];
344  for (int e = 0; e < nBlocks; ++e)
345  {
346  for (int q = 0; q < nq; q++)
347  {
348  for (int dir = 0; dir < n_df; ++dir, ++df_ptr)
349  {
350  for (int j = 0; j < vec_t::width; ++j)
351  {
352  // manage padding
353  if ((vec_t::width * e + j) * nq + q < dfsize)
354  {
355  vec[j] =
356  df[dir][(vec_t::width * e + j) * nq + q];
357  }
358  else
359  {
360  vec[j] = 0.0;
361  }
362  }
363  (*df_ptr).load(&vec[0]);
364  }
365  }
366  }
367  }
368  else
369  {
370  newdf.resize(nBlocks * n_df);
371  for (int e = 0; e < nBlocks; ++e)
372  {
373  for (int dir = 0; dir < n_df; ++dir)
374  {
375  for (int j = 0; j < vec_t::width; ++j)
376  {
377  // padding
378  if (vec_t::width * e + j < dfsize)
379  {
380  vec[j] = df[dir][vec_t::width * e + j];
381  }
382  else
383  {
384  vec[j] = 0.0;
385  }
386  }
387  // Must have all vec_t::width elemnts aligned to do a load.
388  newdf[e * n_df + dir].load(&vec[0]);
389  }
390  }
391  }
392 
393  m_twoDGeomDataInterLeave[eDerivFactors] =
395  }
396 
397  return m_twoDGeomDataInterLeave[eDerivFactors];
398 }
399 
400 bool CoalescedGeomData::IsDeformed(
401  vector<StdRegions::StdExpansionSharedPtr> &pCollExp)
402 {
403  if (!m_isDeformedSet)
404  {
405  LibUtilities::PointsKeyVector ptsKeys = pCollExp[0]->GetPointsKeys();
406  const StdRegions::StdExpansion *sep = &(*pCollExp[0]);
407  const LocalRegions::Expansion *lep =
408  dynamic_cast<const LocalRegions::Expansion *>(sep);
409 
410  const Array<OneD, const NekDouble> jac =
411  lep->GetMetricInfo()->GetJac(ptsKeys);
412 
413  m_deformed =
414  lep->GetMetricInfo()->GetGtype() == SpatialDomains::eDeformed;
415  }
416 
417  return m_deformed;
418 }
419 
420 } // namespace Collections
421 } // namespace Nektar
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:249
const SpatialDomains::GeomFactorsSharedPtr & GetMetricInfo() const
Definition: Expansion.cpp:250
General purpose memory allocation routines with the ability to allocate from thread specific memory p...
The base class for all shapes.
Definition: StdExpansion.h:71
std::vector< vec_t, tinysimd::allocator< vec_t > > VecVec_t
std::vector< PointsKey > PointsKeyVector
Definition: Points.h:250
@ eDeformed
Geometry is curved or has non-constant factors.
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
double NekDouble
void Fill(int n, const T alpha, T *x, const int incx)
Fill a vector with a constant value.
Definition: Vmath.cpp:45
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1255