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
37#include <iomanip>
38
39namespace Nektar
40{
41namespace GlobalMapping
42{
43
44std::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,
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,
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,
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,
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
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
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,
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,
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 {
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,
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);
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 {
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 {
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
virtual GLOBAL_MAPPING_EXPORT void v_ApplyChristoffelCovar(const Array< OneD, Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray) override
virtual GLOBAL_MAPPING_EXPORT void v_CovarToCartesian(const Array< OneD, Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray) 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
Array< OneD, Array< OneD, NekDouble > > m_deriv
virtual GLOBAL_MAPPING_EXPORT void v_GetMetricTensor(Array< OneD, 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_ContravarFromCartesian(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_ContravarToCartesian(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_GetInvMetricTensor(Array< OneD, Array< OneD, NekDouble > > &outarray) override
Array< OneD, Array< OneD, NekDouble > > m_Christoffel
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
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:90
std::vector< double > d(NPUPPER *NPUPPER)
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:529
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:207
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:569
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:354
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:593
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:245
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:280
void Fill(int n, const T alpha, T *x, const int incx)
Fill a vector with a constant value.
Definition: Vmath.cpp:43
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1191
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:414