Nektar++
GeomFactors.cpp
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////////////
2//
3// File: GeomFactors.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: Geometric factors base class.
32//
33////////////////////////////////////////////////////////////////////////////////
34
37
38namespace Nektar
39{
40namespace SpatialDomains
41{
42/**
43 * @class GeomFactors
44 *
45 * This class stores the various geometric factors associated with a
46 * specific element, necessary for fundamental integration and
47 * differentiation operations as well as edge and surface normals.
48 *
49 * Initially, these algorithms are provided with a mapping from the
50 * reference region element to the physical element. Practically, this
51 * is represented using a corresponding reference region element for
52 * each coordinate component. Note that for straight-sided elements,
53 * these elements will be of linear order. Curved elements are
54 * represented using higher-order coordinate mappings. This geometric
55 * order is in contrast to the order of the spectral/hp expansion order
56 * on the element.
57 *
58 * For application of the chain rule during differentiation we require
59 * the partial derivatives \f[\frac{\partial \xi_i}{\partial \chi_j}\f]
60 * evaluated at the physical points of the expansion basis. We also
61 * construct the inverse metric tensor \f$g^{ij}\f$ which, in the case
62 * of a domain embedded in a higher-dimensional space, supports the
63 * conversion of covariant quantities to contravariant quantities.
64 * When the expansion dimension is equal to the coordinate dimension the
65 * Jacobian of the mapping \f$\chi_j\f$ is a square matrix and
66 * consequently the required terms are the entries of the inverse of the
67 * Jacobian. However, in general this is not the case, so we therefore
68 * implement the construction of these terms following the derivation
69 * in Cantwell, et. al. \cite CaYaKiPeSh13. Given the coordinate maps
70 * \f$\chi_i\f$, this comprises of five steps
71 * -# Compute the terms of the Jacobian
72 * \f$\frac{\partial \chi_i}{\partial \xi_j}\f$.
73 * -# Compute the metric tensor
74 * \f$g_{ij}=\mathbf{t}_{(i)}\cdot\mathbf{t}_{(j)}\f$.
75 * -# Compute the square of the Jacobian determinant
76 * \f$g=|\mathbf{g}|\f$.
77 * -# Compute the inverse metric tensor \f$g^{ij}\f$.
78 * -# Compute the terms \f$\frac{\partial \xi_i}{\partial \chi_j}\f$.
79 */
80
81/**
82 * @param gtype Specified whether the geometry is regular or
83 * deformed.
84 * @param coordim Specifies the dimension of the coordinate
85 * system.
86 * @param Coords Coordinate maps of the element.
87 */
88GeomFactors::GeomFactors(const GeomType gtype, const int coordim,
90 const Array<OneD, Array<OneD, NekDouble>> &coords)
91 : m_type(gtype), m_expDim(xmap->GetShapeDimension()), m_coordDim(coordim),
92 m_valid(true), m_xmap(xmap), m_coords(coords)
93{
95}
96
97/**
98 * @param S An instance of a GeomFactors class from which
99 * to construct a new instance.
100 */
102 : m_type(S.m_type), m_expDim(S.m_expDim), m_coordDim(S.m_coordDim),
103 m_valid(S.m_valid), m_xmap(S.m_xmap), m_coords(S.m_coords)
104{
105}
106
107/**
108 *
109 */
111{
112}
113
114/**
115 * Member data equivalence is tested in the following order: shape type,
116 * expansion dimension, coordinate dimension and coordinates.
117 */
118bool operator==(const GeomFactors &lhs, const GeomFactors &rhs)
119{
120 if (!(lhs.m_type == rhs.m_type))
121 {
122 return false;
123 }
124
125 if (!(lhs.m_expDim == rhs.m_expDim))
126 {
127 return false;
128 }
129
130 if (!(lhs.m_coordDim == rhs.m_coordDim))
131 {
132 return false;
133 }
134
135 const Array<OneD, const NekDouble> jac_lhs =
136 lhs.ComputeJac(lhs.m_xmap->GetPointsKeys());
137 const Array<OneD, const NekDouble> jac_rhs =
138 rhs.ComputeJac(rhs.m_xmap->GetPointsKeys());
139 if (!(jac_lhs == jac_rhs))
140 {
141 return false;
142 }
143
144 return true;
145}
146
147/**
148 * Derivatives are computed at the geometry point distributions and
149 * interpolated to the target point distributions.
150 *
151 * @param tpoints Target point distributions.
152 * @returns Derivative of coordinate map evaluated at
153 * target point distributions.
154 */
156 const LibUtilities::PointsKeyVector &keyTgt) const
157{
158 ASSERTL1(keyTgt.size() == m_expDim,
159 "Dimension of target point distribution does not match "
160 "expansion dimension.");
161
162 int i = 0, j = 0;
163 int nqtot_map = 1;
164 int nqtot_tbasis = 1;
168
169 // Allocate storage and compute number of points
170 for (i = 0; i < m_expDim; ++i)
171 {
172 map_points[i] = m_xmap->GetBasis(i)->GetPointsKey();
173 nqtot_map *= map_points[i].GetNumPoints();
174 nqtot_tbasis *= keyTgt[i].GetNumPoints();
177 }
178
179 // Calculate local derivatives
180 for (i = 0; i < m_coordDim; ++i)
181 {
182 Array<OneD, NekDouble> tmp(nqtot_map);
183 // Transform from coefficient space to physical space
184 m_xmap->BwdTrans(m_coords[i], tmp);
185
186 // Allocate storage and take the derivative (calculated at the
187 // points as specified in 'Coords')
188 for (j = 0; j < m_expDim; ++j)
189 {
190 d_map[j][i] = Array<OneD, NekDouble>(nqtot_map);
191 deriv[j][i] = Array<OneD, NekDouble>(nqtot_tbasis);
192 m_xmap->StdPhysDeriv(j, tmp, d_map[j][i]);
193 }
194 }
195
196 for (i = 0; i < m_coordDim; ++i)
197 {
198 // Interpolate the derivatives:
199 // - from the points as defined in the mapping ('Coords')
200 // - to the points at which we want to know the metrics
201 // ('tbasis')
202 bool same = true;
203 for (j = 0; j < m_expDim; ++j)
204 {
205 same = same && (map_points[j] == keyTgt[j]);
206 }
207 if (same)
208 {
209 for (j = 0; j < m_expDim; ++j)
210 {
211 deriv[j][i] = d_map[j][i];
212 }
213 }
214 else
215 {
216 for (j = 0; j < m_expDim; ++j)
217 {
218 Interp(map_points, d_map[j][i], keyTgt, deriv[j][i]);
219 }
220 }
221 }
222
223 return deriv;
224}
225
226/**
227 * This routine returns an array of values specifying the Jacobian
228 * of the mapping at quadrature points in the element. The array
229 * is either of size 1 in the case of elements having #GeomType
230 * #eRegular, or of size equal to the number of quadrature points for
231 * #eDeformed elements.
232 *
233 * @returns Array containing the Jacobian of the coordinate
234 * mapping at the quadrature points of the element.
235 * @see GeomType
236 */
238 const LibUtilities::PointsKeyVector &keyTgt) const
239{
240 ASSERTL1(keyTgt.size() == m_expDim,
241 "Dimension of target point distribution does not match "
242 "expansion dimension.");
243
244 int i = 0, j = 0, k = 0, l = 0;
245 int ptsTgt = 1;
246
247 if (m_type == eDeformed)
248 {
249 // Allocate storage and compute number of points
250 for (i = 0; i < m_expDim; ++i)
251 {
252 ptsTgt *= keyTgt[i].GetNumPoints();
253 }
254 }
255
256 // Get derivative at geometry points
257 DerivStorage deriv = ComputeDeriv(keyTgt);
258
259 Array<TwoD, NekDouble> tmp(m_expDim * m_expDim, ptsTgt, 0.0);
260 Array<TwoD, NekDouble> gmat(m_expDim * m_expDim, ptsTgt, 0.0);
261 Array<OneD, NekDouble> jac(ptsTgt, 0.0);
262
263 // Compute g_{ij} as t_i \cdot t_j and store in tmp
264 for (i = 0, l = 0; i < m_expDim; ++i)
265 {
266 for (j = 0; j < m_expDim; ++j, ++l)
267 {
268 for (k = 0; k < m_coordDim; ++k)
269 {
270 Vmath::Vvtvp(ptsTgt, &deriv[i][k][0], 1, &deriv[j][k][0], 1,
271 &tmp[l][0], 1, &tmp[l][0], 1);
272 }
273 }
274 }
275
276 Adjoint(tmp, gmat);
277
278 // Compute g = det(g_{ij}) (= Jacobian squared) and store
279 // temporarily in m_jac.
280 for (i = 0; i < m_expDim; ++i)
281 {
282 Vmath::Vvtvp(ptsTgt, &tmp[i][0], 1, &gmat[i * m_expDim][0], 1, &jac[0],
283 1, &jac[0], 1);
284 }
285
286 // Compute the Jacobian = sqrt(g)
287 Vmath::Vsqrt(ptsTgt, &jac[0], 1, &jac[0], 1);
288
289 return jac;
290}
291
292/**
293 * This routine returns a two-dimensional array of values specifying
294 * the inverse metric terms associated with the coordinate mapping of
295 * the corresponding reference region to the physical element. These
296 * terms correspond to the \f$g^{ij}\f$ terms in \cite CaYaKiPeSh13 and,
297 * in the case of an embedded manifold, map covariant quantities to
298 * contravariant quantities. The leading index of the array is the index
299 * of the term in the tensor numbered as
300 * \f[\left(\begin{array}{ccc}
301 * 0 & 1 & 2 \\
302 * 1 & 3 & 4 \\
303 * 2 & 4 & 5
304 * \end{array}\right)\f].
305 * The second dimension is either of size 1 in the case of elements
306 * having #GeomType #eRegular, or of size equal to the number of
307 * quadrature points for #eDeformed elements.
308 *
309 * @see [Wikipedia "Covariance and Contravariance of Vectors"]
310 * (http://en.wikipedia.org/wiki/Covariance_and_contravariance_of_vectors)
311 * @returns Two-dimensional array containing the inverse
312 * metric tensor of the coordinate mapping.
313 */
315 const LibUtilities::PointsKeyVector &keyTgt) const
316{
317 ASSERTL1(keyTgt.size() == m_expDim,
318 "Dimension of target point distribution does not match "
319 "expansion dimension.");
320
321 int i = 0, j = 0, k = 0, l = 0;
322 int ptsTgt = 1;
323
324 if (m_type == eDeformed)
325 {
326 // Allocate storage and compute number of points
327 for (i = 0; i < m_expDim; ++i)
328 {
329 ptsTgt *= keyTgt[i].GetNumPoints();
330 }
331 }
332
333 // Get derivative at geometry points
334 DerivStorage deriv = ComputeDeriv(keyTgt);
335
336 Array<TwoD, NekDouble> tmp(m_expDim * m_expDim, ptsTgt, 0.0);
337 Array<TwoD, NekDouble> gmat(m_expDim * m_expDim, ptsTgt, 0.0);
338 Array<OneD, NekDouble> jac(ptsTgt, 0.0);
339
340 // Compute g_{ij} as t_i \cdot t_j and store in tmp
341 for (i = 0, l = 0; i < m_expDim; ++i)
342 {
343 for (j = 0; j < m_expDim; ++j, ++l)
344 {
345 for (k = 0; k < m_coordDim; ++k)
346 {
347 Vmath::Vvtvp(ptsTgt, &deriv[i][k][0], 1, &deriv[j][k][0], 1,
348 &tmp[l][0], 1, &tmp[l][0], 1);
349 }
350 }
351 }
352
353 Adjoint(tmp, gmat);
354
355 // Compute g = det(g_{ij}) (= Jacobian squared) and store
356 // temporarily in m_jac.
357 for (i = 0; i < m_expDim; ++i)
358 {
359 Vmath::Vvtvp(ptsTgt, &tmp[i][0], 1, &gmat[i * m_expDim][0], 1, &jac[0],
360 1, &jac[0], 1);
361 }
362
363 for (i = 0; i < m_expDim * m_expDim; ++i)
364 {
365 Vmath::Vdiv(ptsTgt, &gmat[i][0], 1, &jac[0], 1, &gmat[i][0], 1);
366 }
367
368 return gmat;
369}
370
371/**
372 * @param keyTgt Target point distributions.
373 * @returns Derivative factors evaluated at the target
374 * point distributions.
375 * A 1D example: /f$ Jac =(\partial x/ \partial \xi) /f$ ;
376 * /f$ factor = 1/Jac = (\partial \xi/ \partial x) /f$
377 */
379 const LibUtilities::PointsKeyVector &keyTgt) const
380{
381 ASSERTL1(keyTgt.size() == m_expDim,
382 "Dimension of target point distribution does not match "
383 "expansion dimension.");
384
385 int i = 0, j = 0, k = 0, l = 0;
386 int ptsTgt = 1;
387
388 if (m_type == eDeformed)
389 {
390 // Allocate storage and compute number of points
391 for (i = 0; i < m_expDim; ++i)
392 {
393 ptsTgt *= keyTgt[i].GetNumPoints();
394 }
395 }
396
397 // Get derivative at geometry points
398 DerivStorage deriv = ComputeDeriv(keyTgt);
399
400 Array<TwoD, NekDouble> tmp(m_expDim * m_expDim, ptsTgt, 0.0);
401 Array<TwoD, NekDouble> gmat(m_expDim * m_expDim, ptsTgt, 0.0);
402 Array<OneD, NekDouble> jac(ptsTgt, 0.0);
404
405 // Compute g_{ij} as t_i \cdot t_j and store in tmp
406 for (i = 0, l = 0; i < m_expDim; ++i)
407 {
408 for (j = 0; j < m_expDim; ++j, ++l)
409 {
410 for (k = 0; k < m_coordDim; ++k)
411 {
412 Vmath::Vvtvp(ptsTgt, &deriv[i][k][0], 1, &deriv[j][k][0], 1,
413 &tmp[l][0], 1, &tmp[l][0], 1);
414 }
415 }
416 }
417
418 Adjoint(tmp, gmat);
419
420 // Compute g = det(g_{ij}) (= Jacobian squared) and store
421 // temporarily in m_jac.
422 for (i = 0; i < m_expDim; ++i)
423 {
424 Vmath::Vvtvp(ptsTgt, &tmp[i][0], 1, &gmat[i * m_expDim][0], 1, &jac[0],
425 1, &jac[0], 1);
426 }
427
428 for (i = 0; i < m_expDim * m_expDim; ++i)
429 {
430 Vmath::Vdiv(ptsTgt, &gmat[i][0], 1, &jac[0], 1, &gmat[i][0], 1);
431 }
432
433 // Compute the Jacobian = sqrt(g)
434 Vmath::Vsqrt(ptsTgt, &jac[0], 1, &jac[0], 1);
435
436 // Compute the derivative factors
437 for (k = 0, l = 0; k < m_coordDim; ++k)
438 {
439 for (j = 0; j < m_expDim; ++j, ++l)
440 {
441 for (i = 0; i < m_expDim; ++i)
442 {
443 Vmath::Vvtvp(ptsTgt, &deriv[i][k][0], 1,
444 &gmat[m_expDim * i + j][0], 1, &factors[l][0], 1,
445 &factors[l][0], 1);
446 }
447 }
448 }
449
450 return factors;
451}
452
454 const LibUtilities::PointsKeyVector &keyTgt,
455 const SpatialDomains::GeomMMF MMFdir,
457 Array<OneD, Array<OneD, NekDouble>> &movingframes)
458{
459 ASSERTL1(keyTgt.size() == m_expDim,
460 "Dimension of target point distribution does not match "
461 "expansion dimension.");
462
463 int i = 0, k = 0;
464 int ptsTgt = 1;
465 int nq = 1;
466
467 for (i = 0; i < m_expDim; ++i)
468 {
469 nq *= keyTgt[i].GetNumPoints();
470 }
471
472 if (m_type == eDeformed)
473 {
474 // Allocate storage and compute number of points
475 for (i = 0; i < m_expDim; ++i)
476 {
477 ptsTgt *= keyTgt[i].GetNumPoints();
478 }
479 }
480
481 // Get derivative at geometry points
482 DerivStorage deriv = ComputeDeriv(keyTgt);
483
484 // number of moving frames is requited to be 3, even for surfaces
485 int MFdim = 3;
486
488
489 // Compute g_{ij} as t_i \cdot t_j and store in tmp
490 for (i = 0; i < MFdim; ++i)
491 {
493 for (k = 0; k < m_coordDim; ++k)
494 {
495 MFtmp[i][k] = Array<OneD, NekDouble>(nq);
496 }
497 }
498
499 // Compute g_{ij} as t_i \cdot t_j and store in tmp
500 for (i = 0; i < MFdim - 1; ++i)
501 {
502 for (k = 0; k < m_coordDim; ++k)
503 {
504 if (m_type == eDeformed)
505 {
506 Vmath::Vcopy(ptsTgt, &deriv[i][k][0], 1, &MFtmp[i][k][0], 1);
507 }
508 else
509 {
510 Vmath::Fill(nq, deriv[i][k][0], MFtmp[i][k], 1);
511 }
512 }
513 }
514
515 // Direction of MF1 is preserved: MF2 is considered in the same
516 // tangent plane as MF1. MF3 is computed by cross product of MF1
517 // and MF2. MF2 is consequently computed as the cross product of
518 // MF3 and MF1.
520 for (int k = 0; k < m_coordDim; k++)
521 {
522 PrincipleDir[k] = Array<OneD, NekDouble>(nq);
523 }
524
525 if (!(MMFdir == eLOCAL))
526 {
527 ComputePrincipleDirection(keyTgt, MMFdir, factors, PrincipleDir);
528 }
529
530 // MF3 = MF1 \times MF2
531 VectorCrossProd(MFtmp[0], MFtmp[1], MFtmp[2]);
532
533 // Normalizing MF3
534 VectorNormalise(MFtmp[2]);
535
536 if (!(MMFdir == eLOCAL))
537 {
538 Array<OneD, NekDouble> temp(nq, 0.0);
539
540 // Reorient MF1 along the PrincipleDir
541 for (i = 0; i < m_coordDim; ++i)
542 {
543 Vmath::Vvtvp(nq, MFtmp[2][i], 1, PrincipleDir[i], 1, temp, 1, temp,
544 1);
545 }
546 Vmath::Neg(nq, temp, 1);
547
548 // u2 = v2 - < u1 , v2 > ( u1 / < u1, u1 > )
549 for (i = 0; i < m_coordDim; ++i)
550 {
551 Vmath::Vvtvp(nq, temp, 1, MFtmp[2][i], 1, PrincipleDir[i], 1,
552 MFtmp[0][i], 1);
553 }
554 }
555
556 // Normalizing MF1
557 VectorNormalise(MFtmp[0]);
558
559 // MF2 = MF3 \times MF1
560 VectorCrossProd(MFtmp[2], MFtmp[0], MFtmp[1]);
561
562 // Normalizing MF2
563 VectorNormalise(MFtmp[1]);
564
565 for (i = 0; i < MFdim; ++i)
566 {
567 for (k = 0; k < m_coordDim; ++k)
568 {
569 Vmath::Vcopy(nq, &MFtmp[i][k][0], 1,
570 &movingframes[i * m_coordDim + k][0], 1);
571 }
572 }
573}
574
575/**
576 * Constructs the Jacobian as per Spencer's book p158 and tests if
577 * negative.
578 */
580{
581 // Jacobian test only makes sense when expdim = coorddim
582 // If one-dimensional then element is valid.
583 if (m_coordDim != m_expDim || m_expDim == 1)
584 {
585 m_valid = true;
586 return;
587 }
588
590 int nqtot = 1;
591 for (int i = 0; i < m_expDim; ++i)
592 {
593 p[i] = m_xmap->GetBasis(i)->GetPointsKey();
594 nqtot *= p[i].GetNumPoints();
595 }
596 int pts = (m_type == eRegular || m_type == eMovingRegular) ? 1 : nqtot;
597 Array<OneD, NekDouble> jac(pts, 0.0);
598
599 DerivStorage deriv = GetDeriv(p);
600
601 switch (m_expDim)
602 {
603 case 2:
604 {
605 Vmath::Vvtvvtm(pts, &deriv[0][0][0], 1, &deriv[1][1][0], 1,
606 &deriv[1][0][0], 1, &deriv[0][1][0], 1, &jac[0], 1);
607 break;
608 }
609 case 3:
610 {
611 Array<OneD, NekDouble> tmp(pts, 0.0);
612
613 Vmath::Vvtvvtm(pts, &deriv[1][1][0], 1, &deriv[2][2][0], 1,
614 &deriv[2][1][0], 1, &deriv[1][2][0], 1, &tmp[0], 1);
615 Vmath::Vvtvp(pts, &deriv[0][0][0], 1, &tmp[0], 1, &jac[0], 1,
616 &jac[0], 1);
617
618 Vmath::Vvtvvtm(pts, &deriv[2][1][0], 1, &deriv[0][2][0], 1,
619 &deriv[0][1][0], 1, &deriv[2][2][0], 1, &tmp[0], 1);
620 Vmath::Vvtvp(pts, &deriv[1][0][0], 1, &tmp[0], 1, &jac[0], 1,
621 &jac[0], 1);
622
623 Vmath::Vvtvvtm(pts, &deriv[0][1][0], 1, &deriv[1][2][0], 1,
624 &deriv[1][1][0], 1, &deriv[0][2][0], 1, &tmp[0], 1);
625 Vmath::Vvtvp(pts, &deriv[2][0][0], 1, &tmp[0], 1, &jac[0], 1,
626 &jac[0], 1);
627
628 break;
629 }
630 }
631
632 if (Vmath::Vmin(pts, &jac[0], 1) < 0)
633 {
634 m_valid = false;
635 }
636}
637
638/**
639 * @param map_points Source data point distribution.
640 * @param src Source data to be interpolated.
641 * @param tpoints Target data point distribution.
642 * @param tgt Target data storage.
643 */
646 const LibUtilities::PointsKeyVector &tgt_points,
647 Array<OneD, NekDouble> &tgt) const
648{
649 ASSERTL1(src_points.size() == tgt_points.size(),
650 "Dimension of target point distribution does not match "
651 "expansion dimension.");
652
653 switch (m_expDim)
654 {
655 case 1:
656 LibUtilities::Interp1D(src_points[0], src, tgt_points[0], tgt);
657 break;
658 case 2:
659 LibUtilities::Interp2D(src_points[0], src_points[1], src,
660 tgt_points[0], tgt_points[1], tgt);
661 break;
662 case 3:
663 LibUtilities::Interp3D(src_points[0], src_points[1], src_points[2],
664 src, tgt_points[0], tgt_points[1],
665 tgt_points[2], tgt);
666 break;
667 }
668}
669
670/**
671 * Input and output arrays are of dimension
672 * (m_expDim*m_expDim) x num_points. The first index of the input and
673 * output arrays are ordered row-by-row.
674 * @param src Input data array.
675 * @param tgt Storage for adjoint matrix data.
676 */
678 Array<TwoD, NekDouble> &tgt) const
679{
680 ASSERTL1(src.size() == tgt.size(),
681 "Source matrix is of different size to destination"
682 "matrix for computing adjoint.");
683
684 int n = src[0].size();
685 switch (m_expDim)
686 {
687 case 1:
688 Vmath::Fill(n, 1.0, &tgt[0][0], 1);
689 break;
690 case 2:
691 Vmath::Vcopy(n, &src[3][0], 1, &tgt[0][0], 1);
692 Vmath::Smul(n, -1.0, &src[1][0], 1, &tgt[1][0], 1);
693 Vmath::Smul(n, -1.0, &src[2][0], 1, &tgt[2][0], 1);
694 Vmath::Vcopy(n, &src[0][0], 1, &tgt[3][0], 1);
695 break;
696 case 3:
697 {
698 int a, b, c, d, e, i, j;
699
700 // Compute g^{ij} by computing Cofactors(g_ij)^T
701 for (i = 0; i < m_expDim; ++i)
702 {
703 for (j = 0; j < m_expDim; ++j)
704 {
705 a = ((i + 1) % m_expDim) * m_expDim + ((j + 1) % m_expDim);
706 b = ((i + 1) % m_expDim) * m_expDim + ((j + 2) % m_expDim);
707 c = ((i + 2) % m_expDim) * m_expDim + ((j + 1) % m_expDim);
708 d = ((i + 2) % m_expDim) * m_expDim + ((j + 2) % m_expDim);
709 e = j * m_expDim + i;
710 Vmath::Vvtvvtm(n, &src[a][0], 1, &src[d][0], 1, &src[b][0],
711 1, &src[c][0], 1, &tgt[e][0], 1);
712 }
713 }
714 break;
715 }
716 }
717}
718
719/**
720 *
721 */
723 const LibUtilities::PointsKeyVector &keyTgt,
724 const SpatialDomains::GeomMMF MMFdir,
727{
728 int nq = output[0].size();
729
731 for (int i = 0; i < m_coordDim; ++i)
732 {
733 output[i] = Array<OneD, NekDouble>(nq, 0.0);
734 }
735
736 // Construction of Connection
737 switch (MMFdir)
738 {
739 // projection to x-axis
740 case eTangentX:
741 {
742 Vmath::Fill(nq, 1.0, output[0], 1);
743 break;
744 }
745 case eTangentY:
746 {
747 Vmath::Fill(nq, 1.0, output[1], 1);
748 break;
749 }
750 case eTangentXY:
751 {
752 Vmath::Fill(nq, sqrt(2.0), output[0], 1);
753 Vmath::Fill(nq, sqrt(2.0), output[1], 1);
754 break;
755 }
756 case eTangentZ:
757 {
758 Vmath::Fill(nq, 1.0, output[2], 1);
759 break;
760 }
761 case eTangentCircular:
762 {
763 // Tangent direction depends on spatial location.
765 for (int k = 0; k < m_coordDim; k++)
766 {
767 x[k] = Array<OneD, NekDouble>(nq);
768 }
769
770 // m_coords are StdExpansions which store the mapping
771 // between the std element and the local element. Bwd
772 // transforming the std element minimum basis gives a
773 // minimum physical basis for geometry. Need to then
774 // interpolate this up to the quadrature basis.
775 int nqtot_map = 1;
777 for (int i = 0; i < m_expDim; ++i)
778 {
779 map_points[i] = m_xmap->GetBasis(i)->GetPointsKey();
780 nqtot_map *= map_points[i].GetNumPoints();
781 }
782 Array<OneD, NekDouble> tmp(nqtot_map);
783 for (int k = 0; k < m_coordDim; k++)
784 {
785 m_xmap->BwdTrans(m_coords[k], tmp);
786 Interp(map_points, tmp, keyTgt, x[k]);
787 }
788
789 // circular around the center of the domain
790 NekDouble radius, xc = 0.0, yc = 0.0, xdis, ydis;
791 NekDouble la, lb;
792
793 ASSERTL1(factors.size() >= 4, "factors is too short.");
794
795 la = factors[0];
796 lb = factors[1];
797 xc = factors[2];
798 yc = factors[3];
799
800 for (int i = 0; i < nq; i++)
801 {
802 xdis = x[0][i] - xc;
803 ydis = x[1][i] - yc;
804 radius = sqrt(xdis * xdis / la / la + ydis * ydis / lb / lb);
805 output[0][i] = ydis / radius;
806 output[1][i] = -1.0 * xdis / radius;
807 }
808 break;
809 }
811 {
812 // Tangent direction depends on spatial location.
814 for (int k = 0; k < m_coordDim; k++)
815 {
816 x[k] = Array<OneD, NekDouble>(nq);
817 }
818
819 int nqtot_map = 1;
821 for (int i = 0; i < m_expDim; ++i)
822 {
823 map_points[i] = m_xmap->GetBasis(i)->GetPointsKey();
824 nqtot_map *= map_points[i].GetNumPoints();
825 }
826 Array<OneD, NekDouble> tmp(nqtot_map);
827 for (int k = 0; k < m_coordDim; k++)
828 {
829 m_xmap->BwdTrans(m_coords[k], tmp);
830 Interp(map_points, tmp, keyTgt, x[k]);
831 }
832
833 // circular around the center of the domain
834 NekDouble xtan, ytan, mag;
835 for (int i = 0; i < nq; i++)
836 {
837 xtan = -1.0 * (x[1][i] * x[1][i] * x[1][i] + x[1][i]);
838 ytan = 2.0 * x[0][i];
839 mag = sqrt(xtan * xtan + ytan * ytan);
840 output[0][i] = xtan / mag;
841 output[1][i] = ytan / mag;
842 }
843 break;
844 }
846 {
847 // Tangent direction depends on spatial location.
849 for (int k = 0; k < m_coordDim; k++)
850 {
851 x[k] = Array<OneD, NekDouble>(nq);
852 }
853
854 int nqtot_map = 1;
856 for (int i = 0; i < m_expDim; ++i)
857 {
858 map_points[i] = m_xmap->GetBasis(i)->GetPointsKey();
859 nqtot_map *= map_points[i].GetNumPoints();
860 }
861 Array<OneD, NekDouble> tmp(nqtot_map);
862 for (int k = 0; k < m_coordDim; k++)
863 {
864 m_xmap->BwdTrans(m_coords[k], tmp);
865 Interp(map_points, tmp, keyTgt, x[k]);
866 }
867
868 // circular around the center of the domain
869 NekDouble xtan, ytan, mag;
870 for (int i = 0; i < nq; i++)
871 {
872 xtan = -2.0 * x[1][i] * x[1][i] * x[1][i] + x[1][i];
873 ytan = sqrt(3.0) * x[0][i];
874 mag = sqrt(xtan * xtan + ytan * ytan);
875 output[0][i] = xtan / mag;
876 output[1][i] = ytan / mag;
877 }
878 break;
879 }
880 default:
881 {
882 break;
883 }
884 }
885}
886
887/**
888 *
889 */
891{
892 int ndim = array.size();
893 ASSERTL0(ndim > 0, "Number of components must be > 0.");
894 for (int i = 1; i < ndim; ++i)
895 {
896 ASSERTL0(array[i].size() == array[0].size(),
897 "Array size mismatch in coordinates.");
898 }
899
900 int nq = array[0].size();
901 Array<OneD, NekDouble> norm(nq, 0.0);
902
903 // Compute the norm of each vector.
904 for (int i = 0; i < ndim; ++i)
905 {
906 Vmath::Vvtvp(nq, array[i], 1, array[i], 1, norm, 1, norm, 1);
907 }
908
909 Vmath::Vsqrt(nq, norm, 1, norm, 1);
910
911 // Normalise the vectors by the norm
912 for (int i = 0; i < ndim; ++i)
913 {
914 Vmath::Vdiv(nq, array[i], 1, norm, 1, array[i], 1);
915 }
916}
917
918/**
919 * @brief Computes the vector cross-product in 3D of \a v1 and \a v2,
920 * storing the result in \a v3.
921 *
922 * @param v1 First input vector.
923 * @param v2 Second input vector.
924 * @param v3 Output vector computed to be orthogonal to
925 * both \a v1 and \a v2.
926 */
928 const Array<OneD, const Array<OneD, NekDouble>> &v1,
929 const Array<OneD, const Array<OneD, NekDouble>> &v2,
931{
932 ASSERTL0(v1.size() == 3, "Input 1 has dimension not equal to 3.");
933 ASSERTL0(v2.size() == 3, "Input 2 has dimension not equal to 3.");
934 ASSERTL0(v3.size() == 3, "Output vector has dimension not equal to 3.");
935
936 int nq = v1[0].size();
937 Array<OneD, NekDouble> temp(nq);
938
939 Vmath::Vmul(nq, v1[2], 1, v2[1], 1, temp, 1);
940 Vmath::Vvtvm(nq, v1[1], 1, v2[2], 1, temp, 1, v3[0], 1);
941
942 Vmath::Vmul(nq, v1[0], 1, v2[2], 1, temp, 1);
943 Vmath::Vvtvm(nq, v1[2], 1, v2[0], 1, temp, 1, v3[1], 1);
944
945 Vmath::Vmul(nq, v1[1], 1, v2[0], 1, temp, 1);
946 Vmath::Vvtvm(nq, v1[0], 1, v2[1], 1, temp, 1, v3[2], 1);
947}
948
949} // namespace SpatialDomains
950} // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:249
Calculation and storage of geometric factors associated with the mapping from StdRegions reference el...
Definition: GeomFactors.h:74
DerivStorage ComputeDeriv(const LibUtilities::PointsKeyVector &keyTgt) const
Array< TwoD, NekDouble > ComputeDerivFactors(const LibUtilities::PointsKeyVector &keyTgt) const
Return the derivative of the reference coordinates with respect to the mapping, .
void Adjoint(const Array< TwoD, const NekDouble > &src, Array< TwoD, NekDouble > &tgt) const
Compute the transpose of the cofactors matrix.
int m_coordDim
Dimension of coordinate system.
Definition: GeomFactors.h:133
void CheckIfValid()
Tests if the element is valid and not self-intersecting.
void Interp(const LibUtilities::PointsKeyVector &src_points, const Array< OneD, const NekDouble > &src, const LibUtilities::PointsKeyVector &tgt_points, Array< OneD, NekDouble > &tgt) const
Perform interpolation of data between two point distributions.
Array< OneD, NekDouble > ComputeJac(const LibUtilities::PointsKeyVector &keyTgt) const
Return the Jacobian of the mapping and cache the result.
int m_expDim
Dimension of expansion.
Definition: GeomFactors.h:131
Array< TwoD, NekDouble > ComputeGmat(const LibUtilities::PointsKeyVector &keyTgt) const
Computes the Laplacian coefficients .
void ComputePrincipleDirection(const LibUtilities::PointsKeyVector &keyTgt, const SpatialDomains::GeomMMF MMFdir, const Array< OneD, const NekDouble > &CircCentre, Array< OneD, Array< OneD, NekDouble > > &output)
bool m_valid
Validity of element (Jacobian positive)
Definition: GeomFactors.h:135
StdRegions::StdExpansionSharedPtr m_xmap
Stores information about the expansion.
Definition: GeomFactors.h:141
GeomFactors(const GeomType gtype, const int coordim, const StdRegions::StdExpansionSharedPtr &xmap, const Array< OneD, Array< OneD, NekDouble > > &coords)
Constructor for GeomFactors class.
Definition: GeomFactors.cpp:88
DerivStorage GetDeriv(const LibUtilities::PointsKeyVector &keyTgt)
Return the derivative of the mapping with respect to the reference coordinates, .
Definition: GeomFactors.h:218
GeomType m_type
Type of geometry (e.g. eRegular, eDeformed, eMovingRegular).
Definition: GeomFactors.h:129
Array< OneD, Array< OneD, NekDouble > > m_coords
Stores coordinates of the geometry.
Definition: GeomFactors.h:143
void ComputeMovingFrames(const LibUtilities::PointsKeyVector &keyTgt, const SpatialDomains::GeomMMF MMFdir, const Array< OneD, const NekDouble > &CircCentre, Array< OneD, Array< OneD, NekDouble > > &movingframes)
void VectorNormalise(Array< OneD, Array< OneD, NekDouble > > &array)
void VectorCrossProd(const Array< OneD, const Array< OneD, NekDouble > > &v1, const Array< OneD, const Array< OneD, NekDouble > > &v2, Array< OneD, Array< OneD, NekDouble > > &v3)
Computes the vector cross-product in 3D of v1 and v2, storing the result in v3.
void Interp1D(const BasisKey &fbasis0, const Array< OneD, const NekDouble > &from, const BasisKey &tbasis0, Array< OneD, NekDouble > &to)
this function interpolates a 1D function evaluated at the quadrature points of the basis fbasis0 to ...
Definition: Interp.cpp:49
void Interp3D(const BasisKey &fbasis0, const BasisKey &fbasis1, const BasisKey &fbasis2, const Array< OneD, const NekDouble > &from, const BasisKey &tbasis0, const BasisKey &tbasis1, const BasisKey &tbasis2, Array< OneD, NekDouble > &to)
this function interpolates a 3D function evaluated at the quadrature points of the 3D basis,...
Definition: Interp.cpp:164
void Interp2D(const BasisKey &fbasis0, const BasisKey &fbasis1, const Array< OneD, const NekDouble > &from, const BasisKey &tbasis0, const BasisKey &tbasis1, Array< OneD, NekDouble > &to)
this function interpolates a 2D function evaluated at the quadrature points of the 2D basis,...
Definition: Interp.cpp:103
std::vector< PointsKey > PointsKeyVector
Definition: Points.h:236
GeomMMF
Principle direction for MMF.
@ eLOCAL
No Principal direction.
@ eTangentIrregular
Circular around the centre of domain.
@ eTangentX
X coordinate direction.
@ eTangentCircular
Circular around the centre of domain.
@ eTangentNonconvex
Circular around the centre of domain.
@ eTangentXY
XY direction.
@ eTangentZ
Z coordinate direction.
@ eTangentY
Y coordinate direction.
bool operator==(const GeomFactors &lhs, const GeomFactors &rhs)
Equivalence test for GeomFactors objects.
GeomType
Indicates the type of element geometry.
@ eRegular
Geometry is straight-sided with constant geometric factors.
@ eMovingRegular
Currently unused.
@ eDeformed
Geometry is curved or has non-constant factors.
Array< OneD, Array< OneD, Array< OneD, NekDouble > > > DerivStorage
Storage type for derivative of mapping.
Definition: GeomFactors.h:68
std::shared_ptr< StdExpansion > StdExpansionSharedPtr
std::vector< double > d(NPUPPER *NPUPPER)
StdRegions::ConstFactorMap factors
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
double NekDouble
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 Neg(int n, T *x, const int incx)
Negate x = -x.
Definition: Vmath.cpp:513
T Vmin(int n, const T *x, const int incx)
Return the minimum element in x - called vmin to avoid conflict with min.
Definition: Vmath.cpp:1045
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 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 Vvtvvtm(int n, const T *v, int incv, const T *w, int incw, const T *x, int incx, const T *y, int incy, T *z, int incz)
vvtvvtm (vector times vector minus vector times vector):
Definition: Vmath.cpp:716
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
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:294