Nektar++
MappingGeneral.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File: MappingGeneral.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: Mapping of the type X = X(x,y), Y = Y(x,y)
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
36 #include <MultiRegions/ExpList.h>
37 #include <iomanip>
38 
39 namespace Nektar
40 {
41 namespace GlobalMapping
42 {
43 
44 std::string MappingGeneral::className =
46  "General", MappingGeneral::create,
47  "X = X(x,y,z), Y = Y(x,y,z), Z=Z(x,y,z)");
48 
49 /**
50  * @class MappingGeneral
51  * This class implements the most general mapping, defined by the transformation
52  * \f[ \bar{x} = \bar{x}(x,y,z) \f]
53  * \f[ \bar{y} = \bar{y}(x,y,z) \f]
54  * \f[ \bar{z} = \bar{z}(x,y,z) \f]
55  * where \f$(\bar{x},\bar{y},\bar{z})\f$ are the Cartesian (physical)
56  * coordinates and \f$(x,y,z)\f$ are the transformed (computational)
57  * coordinates.
58  */
62  : Mapping(pSession, pFields)
63 {
64 }
65 
66 /**
67  *
68  */
71  const TiXmlElement *pMapping)
72 {
73  Mapping::v_InitObject(pFields, pMapping);
74 
75  m_constantJacobian = false;
76 
78  "General Mapping needs at least 2 velocity components.");
79 }
80 
82  const Array<OneD, Array<OneD, NekDouble>> &inarray,
83  Array<OneD, Array<OneD, NekDouble>> &outarray)
84 {
85  int physTot = m_fields[0]->GetTotPoints();
86  int nvel = m_nConvectiveFields;
87 
88  for (int i = 0; i < nvel; i++)
89  {
90  outarray[i] = Array<OneD, NekDouble>(physTot, 0.0);
91  for (int j = 0; j < nvel; j++)
92  {
93  Vmath::Vvtvp(physTot, inarray[j], 1, m_deriv[i * nvel + j], 1,
94  outarray[i], 1, outarray[i], 1);
95  }
96  }
97 }
98 
100  const Array<OneD, Array<OneD, NekDouble>> &inarray,
101  Array<OneD, Array<OneD, NekDouble>> &outarray)
102 {
103  int physTot = m_fields[0]->GetTotPoints();
104  int nvel = m_nConvectiveFields;
105 
106  for (int i = 0; i < nvel; i++)
107  {
108  outarray[i] = Array<OneD, NekDouble>(physTot, 0.0);
109  for (int j = 0; j < nvel; j++)
110  {
111  Vmath::Vvtvp(physTot, inarray[j], 1, m_invDeriv[i * nvel + j], 1,
112  outarray[i], 1, outarray[i], 1);
113  }
114  }
115 }
116 
118  const Array<OneD, Array<OneD, NekDouble>> &inarray,
119  Array<OneD, Array<OneD, NekDouble>> &outarray)
120 {
121  int physTot = m_fields[0]->GetTotPoints();
122  int nvel = m_nConvectiveFields;
123 
124  for (int i = 0; i < nvel; i++)
125  {
126  outarray[i] = Array<OneD, NekDouble>(physTot, 0.0);
127  for (int j = 0; j < nvel; j++)
128  {
129  Vmath::Vvtvp(physTot, inarray[j], 1, m_invDeriv[j * nvel + i], 1,
130  outarray[i], 1, outarray[i], 1);
131  }
132  }
133 }
134 
136  const Array<OneD, Array<OneD, NekDouble>> &inarray,
137  Array<OneD, Array<OneD, NekDouble>> &outarray)
138 {
139  int physTot = m_fields[0]->GetTotPoints();
140  int nvel = m_nConvectiveFields;
141 
142  for (int i = 0; i < nvel; i++)
143  {
144  outarray[i] = Array<OneD, NekDouble>(physTot, 0.0);
145  for (int j = 0; j < nvel; j++)
146  {
147  Vmath::Vvtvp(physTot, inarray[j], 1, m_deriv[j * nvel + i], 1,
148  outarray[i], 1, outarray[i], 1);
149  }
150  }
151 }
152 
154 {
155  int physTot = m_fields[0]->GetTotPoints();
156  Vmath::Vcopy(physTot, m_jac, 1, outarray, 1);
157 }
158 
160  Array<OneD, Array<OneD, NekDouble>> &outarray)
161 {
162  int physTot = m_fields[0]->GetTotPoints();
163  int nvel = m_nConvectiveFields;
164 
165  for (int i = 0; i < nvel; i++)
166  {
167  for (int j = 0; j < nvel; j++)
168  {
169  outarray[i * nvel + j] = Array<OneD, NekDouble>(physTot, 0.0);
170  Vmath::Vcopy(physTot, m_metricTensor[i * nvel + j], 1,
171  outarray[i * nvel + j], 1);
172  }
173  }
174 }
175 
177  Array<OneD, Array<OneD, NekDouble>> &outarray)
178 {
179  int physTot = m_fields[0]->GetTotPoints();
180  int nvel = m_nConvectiveFields;
181 
182  for (int i = 0; i < nvel; i++)
183  {
184  for (int j = 0; j < nvel; j++)
185  {
186  outarray[i * nvel + j] = Array<OneD, NekDouble>(physTot, 0.0);
187  Vmath::Vcopy(physTot, m_invMetricTensor[i * nvel + j], 1,
188  outarray[i * nvel + j], 1);
189  }
190  }
191 }
192 
194  const Array<OneD, Array<OneD, NekDouble>> &inarray,
195  Array<OneD, Array<OneD, NekDouble>> &outarray)
196 {
197  int physTot = m_fields[0]->GetTotPoints();
198  int nvel = m_nConvectiveFields;
199 
200  // Calculate {i,jk} u^j
201  for (int i = 0; i < nvel; i++)
202  {
203  for (int k = 0; k < nvel; k++)
204  {
205  outarray[i * nvel + k] = Array<OneD, NekDouble>(physTot, 0.0);
206  for (int j = 0; j < nvel; j++)
207  {
208  Vmath::Vvtvp(physTot, inarray[j], 1,
209  m_Christoffel[i * nvel * nvel + j * nvel + k], 1,
210  outarray[i * nvel + k], 1, outarray[i * nvel + k],
211  1);
212  }
213  }
214  }
215 }
216 
218  const Array<OneD, Array<OneD, NekDouble>> &inarray,
219  Array<OneD, Array<OneD, NekDouble>> &outarray)
220 {
221  int physTot = m_fields[0]->GetTotPoints();
222  int nvel = m_nConvectiveFields;
223 
224  // Calculate {i,jk} u_i
225  for (int j = 0; j < nvel; j++)
226  {
227  for (int k = 0; k < nvel; k++)
228  {
229  outarray[j * nvel + k] = Array<OneD, NekDouble>(physTot, 0.0);
230  for (int i = 0; i < nvel; i++)
231  {
232  Vmath::Vvtvp(physTot, inarray[i], 1,
233  m_Christoffel[i * nvel * nvel + j * nvel + k], 1,
234  outarray[j * nvel + k], 1, outarray[j * nvel + k],
235  1);
236  }
237  }
238  }
239 }
240 
242 {
245 }
246 
248 {
249  int physTot = m_fields[0]->GetTotPoints();
250  int nvel = m_nConvectiveFields;
251 
252  // Set wavespace to false and store current value
253  bool wavespace = m_fields[0]->GetWaveSpace();
254  m_fields[0]->SetWaveSpace(false);
255 
256  // Allocate memory
261  for (int i = 0; i < m_metricTensor.size(); i++)
262  {
263  m_metricTensor[i] = Array<OneD, NekDouble>(physTot, 0.0);
264  m_invMetricTensor[i] = Array<OneD, NekDouble>(physTot, 0.0);
265  m_deriv[i] = Array<OneD, NekDouble>(physTot, 0.0);
266  m_invDeriv[i] = Array<OneD, NekDouble>(physTot, 0.0);
267  }
268  m_jac = Array<OneD, NekDouble>(physTot, 0.0);
269 
270  // First, calculate derivatives of the mapping -> dX^i/dx^j = c^i_j
271  for (int i = 0; i < nvel; i++)
272  {
273  for (int j = 0; j < nvel; j++)
274  {
275  m_fields[0]->PhysDeriv(MultiRegions::DirCartesianMap[j],
276  m_coords[i], m_deriv[i * nvel + j]);
277  }
278  }
279  // In Homogeneous case, m_deriv(2,2) needs to be set to 1
280  // because differentiation in wavespace is not valid for non-periodic field
281  if (m_fields[0]->GetExpType() == MultiRegions::e3DH1D)
282  {
283  Vmath::Fill(physTot, 1.0, m_deriv[2 * nvel + 2], 1);
284  }
285 
286  // Now calculate the metric tensor --> g_ij = sum_k { c^k_i c^k_j }
287  for (int i = 0; i < nvel; i++)
288  {
289  for (int j = 0; j < nvel; j++)
290  {
291  for (int k = 0; k < nvel; k++)
292  {
293  Vmath::Vvtvp(physTot, m_deriv[k * nvel + i], 1,
294  m_deriv[k * nvel + j], 1,
295  m_metricTensor[i * nvel + j], 1,
296  m_metricTensor[i * nvel + j], 1);
297  }
298  }
299  }
300 
301  // Put the adjoint of g in m_invMetricTensor
302  switch (nvel)
303  {
304  case 1:
305  Vmath::Fill(physTot, 1.0, m_invMetricTensor[0], 1);
306  break;
307  case 2:
308  Vmath::Vcopy(physTot, m_metricTensor[1 * nvel + 1], 1,
309  m_invMetricTensor[0 * nvel + 0], 1);
310  Vmath::Smul(physTot, -1.0, m_metricTensor[0 * nvel + 1], 1,
311  m_invMetricTensor[1 * nvel + 0], 1);
312  Vmath::Smul(physTot, -1.0, m_metricTensor[1 * nvel + 0], 1,
313  m_invMetricTensor[0 * nvel + 1], 1);
314  Vmath::Vcopy(physTot, m_metricTensor[0 * nvel + 0], 1,
315  m_invMetricTensor[1 * nvel + 1], 1);
316  break;
317  case 3:
318  {
319  int a, b, c, d, e, i, j;
320 
321  // Compute g^{ij} by computing Cofactors(g_ij)^T
322  for (i = 0; i < nvel; ++i)
323  {
324  for (j = 0; j < nvel; ++j)
325  {
326  a = ((i + 1) % nvel) * nvel + ((j + 1) % nvel);
327  b = ((i + 1) % nvel) * nvel + ((j + 2) % nvel);
328  c = ((i + 2) % nvel) * nvel + ((j + 1) % nvel);
329  d = ((i + 2) % nvel) * nvel + ((j + 2) % nvel);
330  e = i * nvel + j;
331  // a*d - b*c
332  Vmath::Vmul(physTot, m_metricTensor[b], 1,
333  m_metricTensor[c], 1, m_invMetricTensor[e], 1);
334  Vmath::Vvtvm(physTot, m_metricTensor[a], 1,
335  m_metricTensor[d], 1, m_invMetricTensor[e], 1,
336  m_invMetricTensor[e], 1);
337  }
338  }
339  break;
340  }
341  }
342 
343  // Compute g = det(g_{ij}) (= Jacobian squared) and store
344  // temporarily in m_jac.
345  for (int i = 0; i < nvel; ++i)
346  {
347  Vmath::Vvtvp(physTot, m_metricTensor[i], 1, m_invMetricTensor[i * nvel],
348  1, m_jac, 1, m_jac, 1);
349  }
350 
351  // Calculate g^ij (the inverse of g_ij) by dividing by jac
352  for (int i = 0; i < nvel * nvel; ++i)
353  {
354  Vmath::Vdiv(physTot, m_invMetricTensor[i], 1, m_jac, 1,
355  m_invMetricTensor[i], 1);
356  }
357 
358  // Compute the Jacobian = sqrt(g)
359  Vmath::Vsqrt(physTot, m_jac, 1, m_jac, 1);
360 
361  // Calculate the derivatives of the inverse transformation
362  // c'^j_i = dx^j/dX^i = sum_k {g^jk c^i_k}
363  for (int i = 0; i < nvel; ++i)
364  {
365  for (int j = 0; j < nvel; ++j)
366  {
367  for (int k = 0; k < nvel; ++k)
368  {
369  Vmath::Vvtvp(physTot, m_deriv[i * nvel + k], 1,
370  m_invMetricTensor[j * nvel + k], 1,
371  m_invDeriv[i * nvel + j], 1,
372  m_invDeriv[i * nvel + j], 1);
373  }
374  }
375  }
376 
377  // Restore value of wavespace
378  m_fields[0]->SetWaveSpace(wavespace);
379 }
380 
382 {
383  int physTot = m_fields[0]->GetTotPoints();
384  int nvel = m_nConvectiveFields;
385 
386  Array<OneD, Array<OneD, NekDouble>> gradG(nvel * nvel * nvel);
387  Array<OneD, Array<OneD, NekDouble>> tmp(nvel * nvel * nvel);
388  m_Christoffel = Array<OneD, Array<OneD, NekDouble>>(nvel * nvel * nvel);
389  // Allocate memory
390  for (int i = 0; i < gradG.size(); i++)
391  {
392  gradG[i] = Array<OneD, NekDouble>(physTot, 0.0);
393  tmp[i] = Array<OneD, NekDouble>(physTot, 0.0);
394  m_Christoffel[i] = Array<OneD, NekDouble>(physTot, 0.0);
395  }
396 
397  // Set wavespace to false and store current value
398  bool waveSpace = m_fields[0]->GetWaveSpace();
399  m_fields[0]->SetWaveSpace(false);
400 
401  // Calculate gradients of g_ij
402  for (int i = 0; i < nvel; i++)
403  {
404  for (int j = 0; j < nvel; j++)
405  {
406  for (int k = 0; k < nvel; k++)
407  {
408  m_fields[0]->PhysDeriv(MultiRegions::DirCartesianMap[k],
409  m_metricTensor[i * nvel + j],
410  gradG[i * nvel * nvel + j * nvel + k]);
411  }
412  }
413  }
414 
415  // Calculate tmp[p,j,k] = 1/2( gradG[pj,k]+ gradG[pk,j]-gradG[jk,p])
416  for (int p = 0; p < nvel; p++)
417  {
418  for (int j = 0; j < nvel; j++)
419  {
420  for (int k = 0; k < nvel; k++)
421  {
422  Vmath::Vadd(physTot, gradG[p * nvel * nvel + j * nvel + k], 1,
423  gradG[p * nvel * nvel + k * nvel + j], 1,
424  tmp[p * nvel * nvel + j * nvel + k], 1);
425  Vmath::Vsub(physTot, tmp[p * nvel * nvel + j * nvel + k], 1,
426  gradG[j * nvel * nvel + k * nvel + p], 1,
427  tmp[p * nvel * nvel + j * nvel + k], 1);
428  Vmath::Smul(physTot, 0.5, tmp[p * nvel * nvel + j * nvel + k],
429  1, tmp[p * nvel * nvel + j * nvel + k], 1);
430  }
431  }
432  }
433 
434  // Calculate Christoffel symbols = g^ip tmp[p,j,k]
435  for (int i = 0; i < nvel; i++)
436  {
437  for (int j = 0; j < nvel; j++)
438  {
439  for (int k = 0; k < nvel; k++)
440  {
441  for (int p = 0; p < nvel; p++)
442  {
443  Vmath::Vvtvp(
444  physTot, m_invMetricTensor[i * nvel + p], 1,
445  tmp[p * nvel * nvel + j * nvel + k], 1,
446  m_Christoffel[i * nvel * nvel + j * nvel + k], 1,
447  m_Christoffel[i * nvel * nvel + j * nvel + k], 1);
448  }
449  }
450  }
451  }
452  // Restore wavespace
453  m_fields[0]->SetWaveSpace(waveSpace);
454 }
455 
456 } // namespace GlobalMapping
457 } // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
static std::string className
Name of the class.
virtual GLOBAL_MAPPING_EXPORT void v_InitObject(const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields, const TiXmlElement *pMapping) override
Array< OneD, Array< OneD, NekDouble > > m_invDeriv
Array< OneD, Array< OneD, NekDouble > > m_metricTensor
virtual GLOBAL_MAPPING_EXPORT void v_GetJacobian(Array< OneD, NekDouble > &outarray) override
virtual GLOBAL_MAPPING_EXPORT void v_ApplyChristoffelContravar(const Array< OneD, Array< OneD, NekDouble >> &inarray, Array< OneD, Array< OneD, NekDouble >> &outarray) override
virtual GLOBAL_MAPPING_EXPORT void v_CovarFromCartesian(const Array< OneD, Array< OneD, NekDouble >> &inarray, Array< OneD, Array< OneD, NekDouble >> &outarray) override
virtual GLOBAL_MAPPING_EXPORT void v_ContravarToCartesian(const Array< OneD, Array< OneD, NekDouble >> &inarray, Array< OneD, Array< OneD, NekDouble >> &outarray) override
Array< OneD, Array< OneD, NekDouble > > m_deriv
virtual GLOBAL_MAPPING_EXPORT void v_ApplyChristoffelCovar(const Array< OneD, Array< OneD, NekDouble >> &inarray, Array< OneD, Array< OneD, NekDouble >> &outarray) override
Array< OneD, NekDouble > m_jac
Array< OneD, Array< OneD, NekDouble > > m_invMetricTensor
virtual GLOBAL_MAPPING_EXPORT void v_GetMetricTensor(Array< OneD, Array< OneD, NekDouble >> &outarray) override
Array< OneD, Array< OneD, NekDouble > > m_Christoffel
virtual GLOBAL_MAPPING_EXPORT void v_ContravarFromCartesian(const Array< OneD, Array< OneD, NekDouble >> &inarray, Array< OneD, Array< OneD, NekDouble >> &outarray) override
MappingGeneral(const LibUtilities::SessionReaderSharedPtr &pSession, const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields)
static GLOBAL_MAPPING_EXPORT MappingSharedPtr create(const LibUtilities::SessionReaderSharedPtr &pSession, const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields, const TiXmlElement *pMapping)
Creates an instance of this class.
virtual GLOBAL_MAPPING_EXPORT void v_UpdateGeomInfo() override
virtual GLOBAL_MAPPING_EXPORT void v_CovarToCartesian(const Array< OneD, Array< OneD, NekDouble >> &inarray, Array< OneD, Array< OneD, NekDouble >> &outarray) override
virtual GLOBAL_MAPPING_EXPORT void v_GetInvMetricTensor(Array< OneD, Array< OneD, NekDouble >> &outarray) override
Base class for mapping to be applied to the coordinate system.
Definition: Mapping.h:69
int m_nConvectiveFields
Number of velocity components.
Definition: Mapping.h:414
Array< OneD, Array< OneD, NekDouble > > m_coords
Array with the Cartesian coordinates.
Definition: Mapping.h:408
Array< OneD, MultiRegions::ExpListSharedPtr > m_fields
Definition: Mapping.h:406
virtual GLOBAL_MAPPING_EXPORT void v_InitObject(const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields, const TiXmlElement *pMapping)
Definition: Mapping.cpp:101
bool m_constantJacobian
Flag defining if the Jacobian is constant.
Definition: Mapping.h:423
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:198
MappingFactory & GetMappingFactory()
Declaration of the mapping factory singleton.
Definition: Mapping.cpp:53
std::shared_ptr< SessionReader > SessionReaderSharedPtr
MultiRegions::Direction const DirCartesianMap[]
Definition: ExpList.h:91
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
void Vsqrt(int n, const T *x, const int incx, T *y, const int incy)
sqrt y = sqrt(x)
Definition: Vmath.cpp:534
void Vmul(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Multiply vector z = x*y.
Definition: Vmath.cpp:209
void Vvtvp(int n, const T *w, const int incw, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
vvtvp (vector times vector plus vector): z = w*x + y
Definition: Vmath.cpp:574
void Vadd(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Add vector z = x+y.
Definition: Vmath.cpp:359
void Vvtvm(int n, const T *w, const int incw, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
vvtvm (vector times vector minus vector): z = w*x - y
Definition: Vmath.cpp:598
void Smul(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha*x.
Definition: Vmath.cpp:248
void Vdiv(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Multiply vector z = x/y.
Definition: Vmath.cpp:284
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
void Vsub(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Subtract vector z = x-y.
Definition: Vmath.cpp:419