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