Nektar++
TetExp.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: TetExp.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:
32//
33///////////////////////////////////////////////////////////////////////////////
34
35#include <boost/core/ignore_unused.hpp>
36
39#include <LocalRegions/TetExp.h>
41
42using namespace std;
43
44namespace Nektar
45{
46namespace LocalRegions
47{
48/**
49 * @class TetExp
50 * Defines a Tetrahedral local expansion.
51 */
52
53/**
54 * \brief Constructor using BasisKey class for quadrature points and
55 * order definition
56 *
57 * @param Ba Basis key for first coordinate.
58 * @param Bb Basis key for second coordinate.
59 * @param Bc Basis key for third coordinate.
60 */
62 const LibUtilities::BasisKey &Bb,
63 const LibUtilities::BasisKey &Bc,
65 : StdExpansion(LibUtilities::StdTetData::getNumberOfCoefficients(
66 Ba.GetNumModes(), Bb.GetNumModes(), Bc.GetNumModes()),
67 3, Ba, Bb, Bc),
68 StdExpansion3D(LibUtilities::StdTetData::getNumberOfCoefficients(
69 Ba.GetNumModes(), Bb.GetNumModes(), Bc.GetNumModes()),
70 Ba, Bb, Bc),
71 StdTetExp(Ba, Bb, Bc), Expansion(geom), Expansion3D(geom),
72 m_matrixManager(
73 std::bind(&Expansion3D::CreateMatrix, this, std::placeholders::_1),
74 std::string("TetExpMatrix")),
75 m_staticCondMatrixManager(std::bind(&Expansion::CreateStaticCondMatrix,
76 this, std::placeholders::_1),
77 std::string("TetExpStaticCondMatrix"))
78{
79}
80
81/**
82 * \brief Copy Constructor
83 */
85 : StdRegions::StdExpansion(T), StdRegions::StdExpansion3D(T),
86 StdRegions::StdTetExp(T), Expansion(T), Expansion3D(T),
87 m_matrixManager(T.m_matrixManager),
88 m_staticCondMatrixManager(T.m_staticCondMatrixManager)
89{
90}
91
92//-----------------------------
93// Integration Methods
94//-----------------------------
95/**
96 * \brief Integrate the physical point list \a inarray over region
97 *
98 * @param inarray Definition of function to be returned at
99 * quadrature point of expansion.
100 * @returns \f$\int^1_{-1}\int^1_{-1} \int^1_{-1}
101 * u(\eta_1, \eta_2, \eta_3) J[i,j,k] d \eta_1 d \eta_2 d \eta_3 \f$
102 * where \f$inarray[i,j,k] = u(\eta_{1i},\eta_{2j},\eta_{3k})
103 * \f$ and \f$ J[i,j,k] \f$ is the Jacobian evaluated at the quadrature
104 * point.
105 */
107{
108 int nquad0 = m_base[0]->GetNumPoints();
109 int nquad1 = m_base[1]->GetNumPoints();
110 int nquad2 = m_base[2]->GetNumPoints();
112 NekDouble retrunVal;
113 Array<OneD, NekDouble> tmp(nquad0 * nquad1 * nquad2);
114
115 // multiply inarray with Jacobian
116 if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
117 {
118 Vmath::Vmul(nquad0 * nquad1 * nquad2, &jac[0], 1,
119 (NekDouble *)&inarray[0], 1, &tmp[0], 1);
120 }
121 else
122 {
123 Vmath::Smul(nquad0 * nquad1 * nquad2, (NekDouble)jac[0],
124 (NekDouble *)&inarray[0], 1, &tmp[0], 1);
125 }
126
127 // call StdTetExp version;
128 retrunVal = StdTetExp::v_Integral(tmp);
129
130 return retrunVal;
131}
132
133//-----------------------------
134// Differentiation Methods
135//-----------------------------
136/**
137 * \brief Differentiate \a inarray in the three coordinate directions.
138 *
139 * @param inarray Input array of values at quadrature points to
140 * be differentiated.
141 * @param out_d0 Derivative in first coordinate direction.
142 * @param out_d1 Derivative in second coordinate direction.
143 * @param out_d2 Derivative in third coordinate direction.
144 */
149{
150 int TotPts = m_base[0]->GetNumPoints() * m_base[1]->GetNumPoints() *
151 m_base[2]->GetNumPoints();
152
154 m_metricinfo->GetDerivFactors(GetPointsKeys());
156 Array<OneD, NekDouble> Diff1 = Diff0 + TotPts;
157 Array<OneD, NekDouble> Diff2 = Diff1 + TotPts;
158
159 StdTetExp::v_PhysDeriv(inarray, Diff0, Diff1, Diff2);
160
161 if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
162 {
163 if (out_d0.size())
164 {
165 Vmath::Vmul(TotPts, &df[0][0], 1, &Diff0[0], 1, &out_d0[0], 1);
166 Vmath::Vvtvp(TotPts, &df[1][0], 1, &Diff1[0], 1, &out_d0[0], 1,
167 &out_d0[0], 1);
168 Vmath::Vvtvp(TotPts, &df[2][0], 1, &Diff2[0], 1, &out_d0[0], 1,
169 &out_d0[0], 1);
170 }
171
172 if (out_d1.size())
173 {
174 Vmath::Vmul(TotPts, &df[3][0], 1, &Diff0[0], 1, &out_d1[0], 1);
175 Vmath::Vvtvp(TotPts, &df[4][0], 1, &Diff1[0], 1, &out_d1[0], 1,
176 &out_d1[0], 1);
177 Vmath::Vvtvp(TotPts, &df[5][0], 1, &Diff2[0], 1, &out_d1[0], 1,
178 &out_d1[0], 1);
179 }
180
181 if (out_d2.size())
182 {
183 Vmath::Vmul(TotPts, &df[6][0], 1, &Diff0[0], 1, &out_d2[0], 1);
184 Vmath::Vvtvp(TotPts, &df[7][0], 1, &Diff1[0], 1, &out_d2[0], 1,
185 &out_d2[0], 1);
186 Vmath::Vvtvp(TotPts, &df[8][0], 1, &Diff2[0], 1, &out_d2[0], 1,
187 &out_d2[0], 1);
188 }
189 }
190 else // regular geometry
191 {
192 if (out_d0.size())
193 {
194 Vmath::Smul(TotPts, df[0][0], &Diff0[0], 1, &out_d0[0], 1);
195 Blas::Daxpy(TotPts, df[1][0], &Diff1[0], 1, &out_d0[0], 1);
196 Blas::Daxpy(TotPts, df[2][0], &Diff2[0], 1, &out_d0[0], 1);
197 }
198
199 if (out_d1.size())
200 {
201 Vmath::Smul(TotPts, df[3][0], &Diff0[0], 1, &out_d1[0], 1);
202 Blas::Daxpy(TotPts, df[4][0], &Diff1[0], 1, &out_d1[0], 1);
203 Blas::Daxpy(TotPts, df[5][0], &Diff2[0], 1, &out_d1[0], 1);
204 }
205
206 if (out_d2.size())
207 {
208 Vmath::Smul(TotPts, df[6][0], &Diff0[0], 1, &out_d2[0], 1);
209 Blas::Daxpy(TotPts, df[7][0], &Diff1[0], 1, &out_d2[0], 1);
210 Blas::Daxpy(TotPts, df[8][0], &Diff2[0], 1, &out_d2[0], 1);
211 }
212 }
213}
214
215//-----------------------------
216// Transforms
217//-----------------------------
218/**
219 * \brief Forward transform from physical quadrature space stored in
220 * \a inarray and evaluate the expansion coefficients and store
221 * in \a (this)->_coeffs
222 *
223 * @param inarray Array of physical quadrature points to be
224 * transformed.
225 * @param outarray Array of coefficients to update.
226 */
228 Array<OneD, NekDouble> &outarray)
229{
230 if ((m_base[0]->Collocation()) && (m_base[1]->Collocation()) &&
231 (m_base[2]->Collocation()))
232 {
233 Vmath::Vcopy(GetNcoeffs(), &inarray[0], 1, &outarray[0], 1);
234 }
235 else
236 {
237 IProductWRTBase(inarray, outarray);
238
239 // get Mass matrix inverse
241 DNekScalMatSharedPtr matsys = m_matrixManager[masskey];
242
243 // copy inarray in case inarray == outarray
244 DNekVec in(m_ncoeffs, outarray);
245 DNekVec out(m_ncoeffs, outarray, eWrapper);
246
247 out = (*matsys) * in;
248 }
249}
250
251//-----------------------------
252// Inner product functions
253//-----------------------------
254/**
255 * \brief Calculate the inner product of inarray with respect to the
256 * basis B=m_base0*m_base1*m_base2 and put into outarray:
257 *
258 * \f$ \begin{array}{rcl} I_{pqr} = (\phi_{pqr}, u)_{\delta}
259 * & = & \sum_{i=0}^{nq_0} \sum_{j=0}^{nq_1} \sum_{k=0}^{nq_2}
260 * \psi_{p}^{a} (\eta_{1i}) \psi_{pq}^{b} (\eta_{2j}) \psi_{pqr}^{c}
261 * (\eta_{3k}) w_i w_j w_k u(\eta_{1,i} \eta_{2,j} \eta_{3,k})
262 * J_{i,j,k}\\ & = & \sum_{i=0}^{nq_0} \psi_p^a(\eta_{1,i})
263 * \sum_{j=0}^{nq_1} \psi_{pq}^b(\eta_{2,j}) \sum_{k=0}^{nq_2}
264 * \psi_{pqr}^c u(\eta_{1i},\eta_{2j},\eta_{3k}) J_{i,j,k}
265 * \end{array} \f$ \n
266 * where
267 * \f$ \phi_{pqr} (\xi_1 , \xi_2 , \xi_3)
268 * = \psi_p^a (\eta_1) \psi_{pq}^b (\eta_2) \psi_{pqr}^c (\eta_3) \f$
269 * which can be implemented as \n
270 * \f$f_{pqr} (\xi_{3k})
271 * = \sum_{k=0}^{nq_3} \psi_{pqr}^c u(\eta_{1i},\eta_{2j},\eta_{3k})
272 * J_{i,j,k} = {\bf B_3 U} \f$ \n
273 * \f$ g_{pq} (\xi_{3k})
274 * = \sum_{j=0}^{nq_1} \psi_{pq}^b (\xi_{2j}) f_{pqr} (\xi_{3k})
275 * = {\bf B_2 F} \f$ \n
276 * \f$ (\phi_{pqr}, u)_{\delta}
277 * = \sum_{k=0}^{nq_0} \psi_{p}^a (\xi_{3k}) g_{pq} (\xi_{3k})
278 * = {\bf B_1 G} \f$
279 */
281 Array<OneD, NekDouble> &outarray)
282{
283 v_IProductWRTBase_SumFac(inarray, outarray);
284}
285
287 const Array<OneD, const NekDouble> &inarray,
288 Array<OneD, NekDouble> &outarray, bool multiplybyweights)
289{
290 const int nquad0 = m_base[0]->GetNumPoints();
291 const int nquad1 = m_base[1]->GetNumPoints();
292 const int nquad2 = m_base[2]->GetNumPoints();
293 const int order0 = m_base[0]->GetNumModes();
294 const int order1 = m_base[1]->GetNumModes();
295 Array<OneD, NekDouble> wsp(nquad1 * nquad2 * order0 +
296 nquad2 * order0 * (order1 + 1) / 2);
297
298 if (multiplybyweights)
299 {
300 Array<OneD, NekDouble> tmp(nquad0 * nquad1 * nquad2);
301
302 MultiplyByQuadratureMetric(inarray, tmp);
304 m_base[0]->GetBdata(), m_base[1]->GetBdata(), m_base[2]->GetBdata(),
305 tmp, outarray, wsp, true, true, true);
306 }
307 else
308 {
310 m_base[0]->GetBdata(), m_base[1]->GetBdata(), m_base[2]->GetBdata(),
311 inarray, outarray, wsp, true, true, true);
312 }
313}
314
315/**
316 * @brief Calculates the inner product \f$ I_{pqr} = (u,
317 * \partial_{x_i} \phi_{pqr}) \f$.
318 *
319 * The derivative of the basis functions is performed using the chain
320 * rule in order to incorporate the geometric factors. Assuming that
321 * the basis functions are a tensor product
322 * \f$\phi_{pqr}(\eta_1,\eta_2,\eta_3) =
323 * \phi_1(\eta_1)\phi_2(\eta_2)\phi_3(\eta_3)\f$, this yields the
324 * result
325 *
326 * \f[
327 * I_{pqr} = \sum_{j=1}^3 \left(u, \frac{\partial u}{\partial \eta_j}
328 * \frac{\partial \eta_j}{\partial x_i}\right)
329 * \f]
330 *
331 * In the prismatic element, we must also incorporate a second set of
332 * geometric factors which incorporate the collapsed co-ordinate
333 * system, so that
334 *
335 * \f[ \frac{\partial\eta_j}{\partial x_i} = \sum_{k=1}^3
336 * \frac{\partial\eta_j}{\partial\xi_k}\frac{\partial\xi_k}{\partial
337 * x_i} \f]
338 *
339 * These derivatives can be found on p152 of Sherwin & Karniadakis.
340 *
341 * @param dir Direction in which to take the derivative.
342 * @param inarray The function \f$ u \f$.
343 * @param outarray Value of the inner product.
344 */
346 const Array<OneD, const NekDouble> &inarray,
347 Array<OneD, NekDouble> &outarray)
348{
349 const int nquad0 = m_base[0]->GetNumPoints();
350 const int nquad1 = m_base[1]->GetNumPoints();
351 const int nquad2 = m_base[2]->GetNumPoints();
352 const int order0 = m_base[0]->GetNumModes();
353 const int order1 = m_base[1]->GetNumModes();
354 const int nqtot = nquad0 * nquad1 * nquad2;
355
356 Array<OneD, NekDouble> tmp1(nqtot);
357 Array<OneD, NekDouble> tmp2(nqtot);
358 Array<OneD, NekDouble> tmp3(nqtot);
359 Array<OneD, NekDouble> tmp4(nqtot);
361 Array<OneD, NekDouble> wsp(nquad1 * nquad2 * order0 +
362 nquad2 * order0 * (order1 + 1) / 2);
363
364 MultiplyByQuadratureMetric(inarray, tmp1);
365
367 tmp2D[0] = tmp2;
368 tmp2D[1] = tmp3;
369 tmp2D[2] = tmp4;
370
371 TetExp::v_AlignVectorToCollapsedDir(dir, tmp1, tmp2D);
372
373 IProductWRTBase_SumFacKernel(m_base[0]->GetDbdata(), m_base[1]->GetBdata(),
374 m_base[2]->GetBdata(), tmp2, outarray, wsp,
375 false, true, true);
376
377 IProductWRTBase_SumFacKernel(m_base[0]->GetBdata(), m_base[1]->GetDbdata(),
378 m_base[2]->GetBdata(), tmp3, tmp6, wsp, true,
379 false, true);
380
381 Vmath::Vadd(m_ncoeffs, tmp6, 1, outarray, 1, outarray, 1);
382
383 IProductWRTBase_SumFacKernel(m_base[0]->GetBdata(), m_base[1]->GetBdata(),
384 m_base[2]->GetDbdata(), tmp4, tmp6, wsp, true,
385 true, false);
386
387 Vmath::Vadd(m_ncoeffs, tmp6, 1, outarray, 1, outarray, 1);
388}
389
391 const int dir, const Array<OneD, const NekDouble> &inarray,
393{
394 int i, j;
395
396 const int nquad0 = m_base[0]->GetNumPoints();
397 const int nquad1 = m_base[1]->GetNumPoints();
398 const int nquad2 = m_base[2]->GetNumPoints();
399 const int nqtot = nquad0 * nquad1 * nquad2;
400
401 const Array<OneD, const NekDouble> &z0 = m_base[0]->GetZ();
402 const Array<OneD, const NekDouble> &z1 = m_base[1]->GetZ();
403 const Array<OneD, const NekDouble> &z2 = m_base[2]->GetZ();
404
405 Array<OneD, NekDouble> tmp2(nqtot);
406 Array<OneD, NekDouble> tmp3(nqtot);
407
409 m_metricinfo->GetDerivFactors(GetPointsKeys());
410
411 if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
412 {
413 Vmath::Vmul(nqtot, &df[3 * dir][0], 1, inarray.get(), 1, tmp2.get(), 1);
414 Vmath::Vmul(nqtot, &df[3 * dir + 1][0], 1, inarray.get(), 1, tmp3.get(),
415 1);
416 Vmath::Vmul(nqtot, &df[3 * dir + 2][0], 1, inarray.get(), 1,
417 outarray[2].get(), 1);
418 }
419 else
420 {
421 Vmath::Smul(nqtot, df[3 * dir][0], inarray.get(), 1, tmp2.get(), 1);
422 Vmath::Smul(nqtot, df[3 * dir + 1][0], inarray.get(), 1, tmp3.get(), 1);
423 Vmath::Smul(nqtot, df[3 * dir + 2][0], inarray.get(), 1,
424 outarray[2].get(), 1);
425 }
426
427 NekDouble g0, g1, g1a, g2, g3;
428 int k, cnt;
429
430 for (cnt = 0, k = 0; k < nquad2; ++k)
431 {
432 for (j = 0; j < nquad1; ++j)
433 {
434 g2 = 2.0 / (1.0 - z2[k]);
435 g1 = g2 / (1.0 - z1[j]);
436 g0 = 2.0 * g1;
437 g3 = (1.0 + z1[j]) * g2 * 0.5;
438
439 for (i = 0; i < nquad0; ++i, ++cnt)
440 {
441 g1a = g1 * (1 + z0[i]);
442
443 outarray[0][cnt] =
444 g0 * tmp2[cnt] + g1a * (tmp3[cnt] + outarray[2][cnt]);
445
446 outarray[1][cnt] = g2 * tmp3[cnt] + g3 * outarray[2][cnt];
447 }
448 }
449 }
450}
451
452//-----------------------------
453// Evaluation functions
454//-----------------------------
455
456/**
457 * Given the local cartesian coordinate \a Lcoord evaluate the
458 * value of physvals at this point by calling through to the
459 * StdExpansion method
460 */
462 const Array<OneD, const NekDouble> &Lcoord,
463 const Array<OneD, const NekDouble> &physvals)
464{
465 // Evaluate point in local (eta) coordinates.
466 return StdExpansion3D::v_PhysEvaluate(Lcoord, physvals);
467}
468
469/**
470 * @param coord Physical space coordinate
471 * @returns Evaluation of expansion at given coordinate.
472 */
474 const Array<OneD, const NekDouble> &physvals)
475{
476 ASSERTL0(m_geom, "m_geom not defined");
477
479
480 // Get the local (eta) coordinates of the point
481 m_geom->GetLocCoords(coord, Lcoord);
482
483 // Evaluate point in local (eta) coordinates.
484 return StdExpansion3D::v_PhysEvaluate(Lcoord, physvals);
485}
486
488 const Array<OneD, const NekDouble> &inarray,
489 std::array<NekDouble, 3> &firstOrderDerivs)
490{
491 Array<OneD, NekDouble> Lcoord(3);
492 ASSERTL0(m_geom, "m_geom not defined");
493 m_geom->GetLocCoords(coord, Lcoord);
494 return StdTetExp::v_PhysEvaluate(Lcoord, inarray, firstOrderDerivs);
495}
496
497/**
498 * \brief Get the coordinates "coords" at the local coordinates "Lcoords"
499 */
502{
503 int i;
504
505 ASSERTL1(Lcoords[0] <= -1.0 && Lcoords[0] >= 1.0 && Lcoords[1] <= -1.0 &&
506 Lcoords[1] >= 1.0 && Lcoords[2] <= -1.0 && Lcoords[2] >= 1.0,
507 "Local coordinates are not in region [-1,1]");
508
509 // m_geom->FillGeom(); // TODO: implement FillGeom()
510
511 for (i = 0; i < m_geom->GetCoordim(); ++i)
512 {
513 coords[i] = m_geom->GetCoord(i, Lcoords);
514 }
515}
516
518 Array<OneD, NekDouble> &coords_1,
519 Array<OneD, NekDouble> &coords_2)
520{
521 Expansion::v_GetCoords(coords_0, coords_1, coords_2);
522}
523
524//-----------------------------
525// Helper functions
526//-----------------------------
527
528/**
529 * \brief Return Shape of region, using ShapeType enum list.
530 */
532{
534}
535
537{
539 m_base[0]->GetBasisKey(), m_base[1]->GetBasisKey(),
540 m_base[2]->GetBasisKey());
541}
542
544{
546 m_base[0]->GetPointsKey());
548 m_base[1]->GetPointsKey());
550 m_base[2]->GetPointsKey());
551
553 bkey2);
554}
555
557 const NekDouble *data, const std::vector<unsigned int> &nummodes,
558 const int mode_offset, NekDouble *coeffs,
559 std::vector<LibUtilities::BasisType> &fromType)
560{
561 boost::ignore_unused(fromType);
562
563 int data_order0 = nummodes[mode_offset];
564 int fillorder0 = min(m_base[0]->GetNumModes(), data_order0);
565 int data_order1 = nummodes[mode_offset + 1];
566 int order1 = m_base[1]->GetNumModes();
567 int fillorder1 = min(order1, data_order1);
568 int data_order2 = nummodes[mode_offset + 2];
569 int order2 = m_base[2]->GetNumModes();
570 int fillorder2 = min(order2, data_order2);
571
572 switch (m_base[0]->GetBasisType())
573 {
575 {
576 int i, j;
577 int cnt = 0;
578 int cnt1 = 0;
579
581 "Extraction routine not set up for this basis");
583 "Extraction routine not set up for this basis");
584
585 Vmath::Zero(m_ncoeffs, coeffs, 1);
586 for (j = 0; j < fillorder0; ++j)
587 {
588 for (i = 0; i < fillorder1 - j; ++i)
589 {
590 Vmath::Vcopy(fillorder2 - j - i, &data[cnt], 1,
591 &coeffs[cnt1], 1);
592 cnt += data_order2 - j - i;
593 cnt1 += order2 - j - i;
594 }
595
596 // count out data for j iteration
597 for (i = fillorder1 - j; i < data_order1 - j; ++i)
598 {
599 cnt += data_order2 - j - i;
600 }
601
602 for (i = fillorder1 - j; i < order1 - j; ++i)
603 {
604 cnt1 += order2 - j - i;
605 }
606 }
607 }
608 break;
609 default:
610 ASSERTL0(false, "basis is either not set up or not "
611 "hierarchicial");
612 }
613}
614
615/**
616 * \brief Returns the physical values at the quadrature points of a face
617 */
618void TetExp::v_GetTracePhysMap(const int face, Array<OneD, int> &outarray)
619{
620 int nquad0 = m_base[0]->GetNumPoints();
621 int nquad1 = m_base[1]->GetNumPoints();
622 int nquad2 = m_base[2]->GetNumPoints();
623
624 int nq0 = 0;
625 int nq1 = 0;
626
627 // get forward aligned faces.
628 switch (face)
629 {
630 case 0:
631 {
632 nq0 = nquad0;
633 nq1 = nquad1;
634 if (outarray.size() != nq0 * nq1)
635 {
636 outarray = Array<OneD, int>(nq0 * nq1);
637 }
638
639 for (int i = 0; i < nquad0 * nquad1; ++i)
640 {
641 outarray[i] = i;
642 }
643
644 break;
645 }
646 case 1:
647 {
648 nq0 = nquad0;
649 nq1 = nquad2;
650 if (outarray.size() != nq0 * nq1)
651 {
652 outarray = Array<OneD, int>(nq0 * nq1);
653 }
654
655 // Direction A and B positive
656 for (int k = 0; k < nquad2; k++)
657 {
658 for (int i = 0; i < nquad0; ++i)
659 {
660 outarray[k * nquad0 + i] = (nquad0 * nquad1 * k) + i;
661 }
662 }
663 break;
664 }
665 case 2:
666 {
667 nq0 = nquad1;
668 nq1 = nquad2;
669 if (outarray.size() != nq0 * nq1)
670 {
671 outarray = Array<OneD, int>(nq0 * nq1);
672 }
673
674 // Directions A and B positive
675 for (int j = 0; j < nquad1 * nquad2; ++j)
676 {
677 outarray[j] = nquad0 - 1 + j * nquad0;
678 }
679 break;
680 }
681 case 3:
682 {
683 nq0 = nquad1;
684 nq1 = nquad2;
685 if (outarray.size() != nq0 * nq1)
686 {
687 outarray = Array<OneD, int>(nq0 * nq1);
688 }
689
690 // Directions A and B positive
691 for (int j = 0; j < nquad1 * nquad2; ++j)
692 {
693 outarray[j] = j * nquad0;
694 }
695 }
696 break;
697 default:
698 ASSERTL0(false, "face value (> 3) is out of range");
699 break;
700 }
701}
702
703/**
704 * \brief Compute the normal of a triangular face
705 */
707{
708 int i;
709 const SpatialDomains::GeomFactorsSharedPtr &geomFactors =
710 GetGeom()->GetMetricInfo();
711
713 for (int i = 0; i < ptsKeys.size(); ++i)
714 {
715 // Need at least 2 points for computing normals
716 if (ptsKeys[i].GetNumPoints() == 1)
717 {
718 LibUtilities::PointsKey pKey(2, ptsKeys[i].GetPointsType());
719 ptsKeys[i] = pKey;
720 }
721 }
722
723 SpatialDomains::GeomType type = geomFactors->GetGtype();
725 geomFactors->GetDerivFactors(ptsKeys);
726 const Array<OneD, const NekDouble> &jac = geomFactors->GetJac(ptsKeys);
727
728 LibUtilities::BasisKey tobasis0 = GetTraceBasisKey(face, 0);
729 LibUtilities::BasisKey tobasis1 = GetTraceBasisKey(face, 1);
730
731 // number of face quadrature points
732 int nq_face = tobasis0.GetNumPoints() * tobasis1.GetNumPoints();
733
734 int vCoordDim = GetCoordim();
735
738 for (i = 0; i < vCoordDim; ++i)
739 {
740 normal[i] = Array<OneD, NekDouble>(nq_face);
741 }
742
743 size_t nqb = nq_face;
744 size_t nbnd = face;
747
748 // Regular geometry case
749 if (type == SpatialDomains::eRegular ||
751 {
752 NekDouble fac;
753
754 // Set up normals
755 switch (face)
756 {
757 case 0:
758 {
759 for (i = 0; i < vCoordDim; ++i)
760 {
761 normal[i][0] = -df[3 * i + 2][0];
762 }
763
764 break;
765 }
766 case 1:
767 {
768 for (i = 0; i < vCoordDim; ++i)
769 {
770 normal[i][0] = -df[3 * i + 1][0];
771 }
772
773 break;
774 }
775 case 2:
776 {
777 for (i = 0; i < vCoordDim; ++i)
778 {
779 normal[i][0] =
780 df[3 * i][0] + df[3 * i + 1][0] + df[3 * i + 2][0];
781 }
782
783 break;
784 }
785 case 3:
786 {
787 for (i = 0; i < vCoordDim; ++i)
788 {
789 normal[i][0] = -df[3 * i][0];
790 }
791 break;
792 }
793 default:
794 ASSERTL0(false, "face is out of range (edge < 3)");
795 }
796
797 // normalise
798 fac = 0.0;
799 for (i = 0; i < vCoordDim; ++i)
800 {
801 fac += normal[i][0] * normal[i][0];
802 }
803 fac = 1.0 / sqrt(fac);
804 Vmath::Fill(nqb, fac, length, 1);
805
806 for (i = 0; i < vCoordDim; ++i)
807 {
808 Vmath::Fill(nq_face, fac * normal[i][0], normal[i], 1);
809 }
810 }
811 else
812 {
813 // Set up deformed normals
814 int j, k;
815
816 int nq0 = ptsKeys[0].GetNumPoints();
817 int nq1 = ptsKeys[1].GetNumPoints();
818 int nq2 = ptsKeys[2].GetNumPoints();
819 int nqtot;
820 int nq01 = nq0 * nq1;
821
822 // number of elemental quad points
823 if (face == 0)
824 {
825 nqtot = nq01;
826 }
827 else if (face == 1)
828 {
829 nqtot = nq0 * nq2;
830 }
831 else
832 {
833 nqtot = nq1 * nq2;
834 }
835
838
839 Array<OneD, NekDouble> faceJac(nqtot);
840 Array<OneD, NekDouble> normals(vCoordDim * nqtot, 0.0);
841
842 // Extract Jacobian along face and recover local derivates
843 // (dx/dr) for polynomial interpolation by multiplying m_gmat by
844 // jacobian
845 switch (face)
846 {
847 case 0:
848 {
849 for (j = 0; j < nq01; ++j)
850 {
851 normals[j] = -df[2][j] * jac[j];
852 normals[nqtot + j] = -df[5][j] * jac[j];
853 normals[2 * nqtot + j] = -df[8][j] * jac[j];
854 faceJac[j] = jac[j];
855 }
856
857 points0 = ptsKeys[0];
858 points1 = ptsKeys[1];
859 break;
860 }
861
862 case 1:
863 {
864 for (j = 0; j < nq0; ++j)
865 {
866 for (k = 0; k < nq2; ++k)
867 {
868 int tmp = j + nq01 * k;
869 normals[j + k * nq0] = -df[1][tmp] * jac[tmp];
870 normals[nqtot + j + k * nq0] = -df[4][tmp] * jac[tmp];
871 normals[2 * nqtot + j + k * nq0] =
872 -df[7][tmp] * jac[tmp];
873 faceJac[j + k * nq0] = jac[tmp];
874 }
875 }
876
877 points0 = ptsKeys[0];
878 points1 = ptsKeys[2];
879 break;
880 }
881
882 case 2:
883 {
884 for (j = 0; j < nq1; ++j)
885 {
886 for (k = 0; k < nq2; ++k)
887 {
888 int tmp = nq0 - 1 + nq0 * j + nq01 * k;
889 normals[j + k * nq1] =
890 (df[0][tmp] + df[1][tmp] + df[2][tmp]) * jac[tmp];
891 normals[nqtot + j + k * nq1] =
892 (df[3][tmp] + df[4][tmp] + df[5][tmp]) * jac[tmp];
893 normals[2 * nqtot + j + k * nq1] =
894 (df[6][tmp] + df[7][tmp] + df[8][tmp]) * jac[tmp];
895 faceJac[j + k * nq1] = jac[tmp];
896 }
897 }
898
899 points0 = ptsKeys[1];
900 points1 = ptsKeys[2];
901 break;
902 }
903
904 case 3:
905 {
906 for (j = 0; j < nq1; ++j)
907 {
908 for (k = 0; k < nq2; ++k)
909 {
910 int tmp = j * nq0 + nq01 * k;
911 normals[j + k * nq1] = -df[0][tmp] * jac[tmp];
912 normals[nqtot + j + k * nq1] = -df[3][tmp] * jac[tmp];
913 normals[2 * nqtot + j + k * nq1] =
914 -df[6][tmp] * jac[tmp];
915 faceJac[j + k * nq1] = jac[tmp];
916 }
917 }
918
919 points0 = ptsKeys[1];
920 points1 = ptsKeys[2];
921 break;
922 }
923
924 default:
925 ASSERTL0(false, "face is out of range (face < 3)");
926 }
927
928 Array<OneD, NekDouble> work(nq_face, 0.0);
929 // Interpolate Jacobian and invert
930 LibUtilities::Interp2D(points0, points1, faceJac,
931 tobasis0.GetPointsKey(), tobasis1.GetPointsKey(),
932 work);
933 Vmath::Sdiv(nq_face, 1.0, &work[0], 1, &work[0], 1);
934
935 // Interpolate normal and multiply by inverse Jacobian.
936 for (i = 0; i < vCoordDim; ++i)
937 {
938 LibUtilities::Interp2D(points0, points1, &normals[i * nqtot],
939 tobasis0.GetPointsKey(),
940 tobasis1.GetPointsKey(), &normal[i][0]);
941 Vmath::Vmul(nq_face, work, 1, normal[i], 1, normal[i], 1);
942 }
943
944 // Normalise to obtain unit normals.
945 Vmath::Zero(nq_face, work, 1);
946 for (i = 0; i < GetCoordim(); ++i)
947 {
948 Vmath::Vvtvp(nq_face, normal[i], 1, normal[i], 1, work, 1, work, 1);
949 }
950
951 Vmath::Vsqrt(nq_face, work, 1, work, 1);
952 Vmath::Sdiv(nq_face, 1.0, work, 1, work, 1);
953
954 Vmath::Vcopy(nqb, work, 1, length, 1);
955
956 for (i = 0; i < GetCoordim(); ++i)
957 {
958 Vmath::Vmul(nq_face, normal[i], 1, work, 1, normal[i], 1);
959 }
960 }
961}
962
963//-----------------------------
964// Operator creation functions
965//-----------------------------
967 Array<OneD, NekDouble> &outarray,
968 const StdRegions::StdMatrixKey &mkey)
969{
970 TetExp::v_HelmholtzMatrixOp_MatFree(inarray, outarray, mkey);
971}
972
974 Array<OneD, NekDouble> &outarray,
975 const StdRegions::StdMatrixKey &mkey)
976{
977 TetExp::v_LaplacianMatrixOp_MatFree(inarray, outarray, mkey);
978}
979
980void TetExp::v_LaplacianMatrixOp(const int k1, const int k2,
981 const Array<OneD, const NekDouble> &inarray,
982 Array<OneD, NekDouble> &outarray,
983 const StdRegions::StdMatrixKey &mkey)
984{
985 StdExpansion::LaplacianMatrixOp_MatFree(k1, k2, inarray, outarray, mkey);
986}
987
989 const StdRegions::StdMatrixKey &mkey)
990{
991 int nq = GetTotPoints();
992
993 // Calculate sqrt of the Jacobian
995 Array<OneD, NekDouble> sqrt_jac(nq);
996 if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
997 {
998 Vmath::Vsqrt(nq, jac, 1, sqrt_jac, 1);
999 }
1000 else
1001 {
1002 Vmath::Fill(nq, sqrt(jac[0]), sqrt_jac, 1);
1003 }
1004
1005 // Multiply array by sqrt(Jac)
1006 Vmath::Vmul(nq, sqrt_jac, 1, array, 1, array, 1);
1007
1008 // Apply std region filter
1009 StdTetExp::v_SVVLaplacianFilter(array, mkey);
1010
1011 // Divide by sqrt(Jac)
1012 Vmath::Vdiv(nq, array, 1, sqrt_jac, 1, array, 1);
1013}
1014
1015//-----------------------------
1016// Matrix creation functions
1017//-----------------------------
1019{
1020 DNekMatSharedPtr returnval;
1021
1022 switch (mkey.GetMatrixType())
1023 {
1031 returnval = Expansion3D::v_GenMatrix(mkey);
1032 break;
1033 default:
1034 returnval = StdTetExp::v_GenMatrix(mkey);
1035 }
1036
1037 return returnval;
1038}
1039
1041{
1042 LibUtilities::BasisKey bkey0 = m_base[0]->GetBasisKey();
1043 LibUtilities::BasisKey bkey1 = m_base[1]->GetBasisKey();
1044 LibUtilities::BasisKey bkey2 = m_base[2]->GetBasisKey();
1047
1048 return tmp->GetStdMatrix(mkey);
1049}
1050
1052{
1053 return m_matrixManager[mkey];
1054}
1055
1057{
1058 m_matrixManager.DeleteObject(mkey);
1059}
1060
1062{
1063 return m_staticCondMatrixManager[mkey];
1064}
1065
1067{
1068 m_staticCondMatrixManager.DeleteObject(mkey);
1069}
1070
1072 Array<OneD, NekDouble> &outarray,
1073 const StdRegions::StdMatrixKey &mkey)
1074{
1076
1077 if (inarray.get() == outarray.get())
1078 {
1080 Vmath::Vcopy(m_ncoeffs, inarray.get(), 1, tmp.get(), 1);
1081
1082 Blas::Dgemv('N', m_ncoeffs, m_ncoeffs, mat->Scale(),
1083 (mat->GetOwnedMatrix())->GetPtr().get(), m_ncoeffs,
1084 tmp.get(), 1, 0.0, outarray.get(), 1);
1085 }
1086 else
1087 {
1088 Blas::Dgemv('N', m_ncoeffs, m_ncoeffs, mat->Scale(),
1089 (mat->GetOwnedMatrix())->GetPtr().get(), m_ncoeffs,
1090 inarray.get(), 1, 0.0, outarray.get(), 1);
1091 }
1092}
1093
1095 const Array<OneD, const NekDouble> &inarray,
1097{
1098 // This implementation is only valid when there are no
1099 // coefficients associated to the Laplacian operator
1100 if (m_metrics.count(eMetricLaplacian00) == 0)
1101 {
1103 }
1104
1105 int nquad0 = m_base[0]->GetNumPoints();
1106 int nquad1 = m_base[1]->GetNumPoints();
1107 int nquad2 = m_base[2]->GetNumPoints();
1108 int nqtot = nquad0 * nquad1 * nquad2;
1109
1110 ASSERTL1(wsp.size() >= 6 * nqtot, "Insufficient workspace size.");
1111 ASSERTL1(m_ncoeffs <= nqtot, "Workspace not set up for ncoeffs > nqtot");
1112
1113 const Array<OneD, const NekDouble> &base0 = m_base[0]->GetBdata();
1114 const Array<OneD, const NekDouble> &base1 = m_base[1]->GetBdata();
1115 const Array<OneD, const NekDouble> &base2 = m_base[2]->GetBdata();
1116 const Array<OneD, const NekDouble> &dbase0 = m_base[0]->GetDbdata();
1117 const Array<OneD, const NekDouble> &dbase1 = m_base[1]->GetDbdata();
1118 const Array<OneD, const NekDouble> &dbase2 = m_base[2]->GetDbdata();
1119 const Array<OneD, const NekDouble> &metric00 =
1120 m_metrics[eMetricLaplacian00];
1121 const Array<OneD, const NekDouble> &metric01 =
1122 m_metrics[eMetricLaplacian01];
1123 const Array<OneD, const NekDouble> &metric02 =
1124 m_metrics[eMetricLaplacian02];
1125 const Array<OneD, const NekDouble> &metric11 =
1126 m_metrics[eMetricLaplacian11];
1127 const Array<OneD, const NekDouble> &metric12 =
1128 m_metrics[eMetricLaplacian12];
1129 const Array<OneD, const NekDouble> &metric22 =
1130 m_metrics[eMetricLaplacian22];
1131
1132 // Allocate temporary storage
1133 Array<OneD, NekDouble> wsp0(2 * nqtot, wsp);
1134 Array<OneD, NekDouble> wsp1(nqtot, wsp + 1 * nqtot);
1135 Array<OneD, NekDouble> wsp2(nqtot, wsp + 2 * nqtot);
1136 Array<OneD, NekDouble> wsp3(nqtot, wsp + 3 * nqtot);
1137 Array<OneD, NekDouble> wsp4(nqtot, wsp + 4 * nqtot);
1138 Array<OneD, NekDouble> wsp5(nqtot, wsp + 5 * nqtot);
1139
1140 // LAPLACIAN MATRIX OPERATION
1141 // wsp1 = du_dxi1 = D_xi1 * inarray = D_xi1 * u
1142 // wsp2 = du_dxi2 = D_xi2 * inarray = D_xi2 * u
1143 // wsp2 = du_dxi3 = D_xi3 * inarray = D_xi3 * u
1144 StdExpansion3D::PhysTensorDeriv(inarray, wsp0, wsp1, wsp2);
1145
1146 // wsp0 = k = g0 * wsp1 + g1 * wsp2 = g0 * du_dxi1 + g1 * du_dxi2
1147 // wsp2 = l = g1 * wsp1 + g2 * wsp2 = g0 * du_dxi1 + g1 * du_dxi2
1148 // where g0, g1 and g2 are the metric terms set up in the GeomFactors class
1149 // especially for this purpose
1150 Vmath::Vvtvvtp(nqtot, &metric00[0], 1, &wsp0[0], 1, &metric01[0], 1,
1151 &wsp1[0], 1, &wsp3[0], 1);
1152 Vmath::Vvtvp(nqtot, &metric02[0], 1, &wsp2[0], 1, &wsp3[0], 1, &wsp3[0], 1);
1153 Vmath::Vvtvvtp(nqtot, &metric01[0], 1, &wsp0[0], 1, &metric11[0], 1,
1154 &wsp1[0], 1, &wsp4[0], 1);
1155 Vmath::Vvtvp(nqtot, &metric12[0], 1, &wsp2[0], 1, &wsp4[0], 1, &wsp4[0], 1);
1156 Vmath::Vvtvvtp(nqtot, &metric02[0], 1, &wsp0[0], 1, &metric12[0], 1,
1157 &wsp1[0], 1, &wsp5[0], 1);
1158 Vmath::Vvtvp(nqtot, &metric22[0], 1, &wsp2[0], 1, &wsp5[0], 1, &wsp5[0], 1);
1159
1160 // outarray = m = (D_xi1 * B)^T * k
1161 // wsp1 = n = (D_xi2 * B)^T * l
1162 IProductWRTBase_SumFacKernel(dbase0, base1, base2, wsp3, outarray, wsp0,
1163 false, true, true);
1164 IProductWRTBase_SumFacKernel(base0, dbase1, base2, wsp4, wsp2, wsp0, true,
1165 false, true);
1166 Vmath::Vadd(m_ncoeffs, wsp2.get(), 1, outarray.get(), 1, outarray.get(), 1);
1167 IProductWRTBase_SumFacKernel(base0, base1, dbase2, wsp5, wsp2, wsp0, true,
1168 true, false);
1169 Vmath::Vadd(m_ncoeffs, wsp2.get(), 1, outarray.get(), 1, outarray.get(), 1);
1170}
1171
1172void TetExp::v_ComputeLaplacianMetric()
1173{
1174 if (m_metrics.count(eMetricQuadrature) == 0)
1175 {
1176 ComputeQuadratureMetric();
1177 }
1178
1179 int i, j;
1180 const unsigned int nqtot = GetTotPoints();
1181 const unsigned int dim = 3;
1182 const MetricType m[3][3] = {
1183 {eMetricLaplacian00, eMetricLaplacian01, eMetricLaplacian02},
1184 {eMetricLaplacian01, eMetricLaplacian11, eMetricLaplacian12},
1185 {eMetricLaplacian02, eMetricLaplacian12, eMetricLaplacian22}};
1186
1187 for (unsigned int i = 0; i < dim; ++i)
1188 {
1189 for (unsigned int j = i; j < dim; ++j)
1190 {
1191 m_metrics[m[i][j]] = Array<OneD, NekDouble>(nqtot);
1192 }
1193 }
1194
1195 // Define shorthand synonyms for m_metrics storage
1196 Array<OneD, NekDouble> g0(m_metrics[m[0][0]]);
1197 Array<OneD, NekDouble> g1(m_metrics[m[1][1]]);
1198 Array<OneD, NekDouble> g2(m_metrics[m[2][2]]);
1199 Array<OneD, NekDouble> g3(m_metrics[m[0][1]]);
1200 Array<OneD, NekDouble> g4(m_metrics[m[0][2]]);
1201 Array<OneD, NekDouble> g5(m_metrics[m[1][2]]);
1202
1203 // Allocate temporary storage
1204 Array<OneD, NekDouble> alloc(7 * nqtot, 0.0);
1205 Array<OneD, NekDouble> h0(alloc); // h0
1206 Array<OneD, NekDouble> h1(alloc + 1 * nqtot); // h1
1207 Array<OneD, NekDouble> h2(alloc + 2 * nqtot); // h2
1208 Array<OneD, NekDouble> h3(alloc + 3 * nqtot); // h3
1209 Array<OneD, NekDouble> wsp4(alloc + 4 * nqtot); // wsp4
1210 Array<OneD, NekDouble> wsp5(alloc + 5 * nqtot); // wsp5
1211 Array<OneD, NekDouble> wsp6(alloc + 6 * nqtot); // wsp6
1212 // Reuse some of the storage as workspace
1213 Array<OneD, NekDouble> wsp7(alloc); // wsp7
1214 Array<OneD, NekDouble> wsp8(alloc + 1 * nqtot); // wsp8
1215 Array<OneD, NekDouble> wsp9(alloc + 2 * nqtot); // wsp9
1216
1217 const Array<TwoD, const NekDouble> &df =
1218 m_metricinfo->GetDerivFactors(GetPointsKeys());
1219 const Array<OneD, const NekDouble> &z0 = m_base[0]->GetZ();
1220 const Array<OneD, const NekDouble> &z1 = m_base[1]->GetZ();
1221 const Array<OneD, const NekDouble> &z2 = m_base[2]->GetZ();
1222 const unsigned int nquad0 = m_base[0]->GetNumPoints();
1223 const unsigned int nquad1 = m_base[1]->GetNumPoints();
1224 const unsigned int nquad2 = m_base[2]->GetNumPoints();
1225
1226 for (j = 0; j < nquad2; ++j)
1227 {
1228 for (i = 0; i < nquad1; ++i)
1229 {
1230 Vmath::Fill(nquad0, 4.0 / (1.0 - z1[i]) / (1.0 - z2[j]),
1231 &h0[0] + i * nquad0 + j * nquad0 * nquad1, 1);
1232 Vmath::Fill(nquad0, 2.0 / (1.0 - z1[i]) / (1.0 - z2[j]),
1233 &h1[0] + i * nquad0 + j * nquad0 * nquad1, 1);
1234 Vmath::Fill(nquad0, 2.0 / (1.0 - z2[j]),
1235 &h2[0] + i * nquad0 + j * nquad0 * nquad1, 1);
1236 Vmath::Fill(nquad0, (1.0 + z1[i]) / (1.0 - z2[j]),
1237 &h3[0] + i * nquad0 + j * nquad0 * nquad1, 1);
1238 }
1239 }
1240 for (i = 0; i < nquad0; i++)
1241 {
1242 Blas::Dscal(nquad1 * nquad2, 1 + z0[i], &h1[0] + i, nquad0);
1243 }
1244
1245 // Step 3. Construct combined metric terms for physical space to
1246 // collapsed coordinate system.
1247 // Order of construction optimised to minimise temporary storage
1248 if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
1249 {
1250 // wsp4
1251 Vmath::Vadd(nqtot, &df[1][0], 1, &df[2][0], 1, &wsp4[0], 1);
1252 Vmath::Vvtvvtp(nqtot, &df[0][0], 1, &h0[0], 1, &wsp4[0], 1, &h1[0], 1,
1253 &wsp4[0], 1);
1254 // wsp5
1255 Vmath::Vadd(nqtot, &df[4][0], 1, &df[5][0], 1, &wsp5[0], 1);
1256 Vmath::Vvtvvtp(nqtot, &df[3][0], 1, &h0[0], 1, &wsp5[0], 1, &h1[0], 1,
1257 &wsp5[0], 1);
1258 // wsp6
1259 Vmath::Vadd(nqtot, &df[7][0], 1, &df[8][0], 1, &wsp6[0], 1);
1260 Vmath::Vvtvvtp(nqtot, &df[6][0], 1, &h0[0], 1, &wsp6[0], 1, &h1[0], 1,
1261 &wsp6[0], 1);
1262
1263 // g0
1264 Vmath::Vvtvvtp(nqtot, &wsp4[0], 1, &wsp4[0], 1, &wsp5[0], 1, &wsp5[0],
1265 1, &g0[0], 1);
1266 Vmath::Vvtvp(nqtot, &wsp6[0], 1, &wsp6[0], 1, &g0[0], 1, &g0[0], 1);
1267
1268 // g4
1269 Vmath::Vvtvvtp(nqtot, &df[2][0], 1, &wsp4[0], 1, &df[5][0], 1, &wsp5[0],
1270 1, &g4[0], 1);
1271 Vmath::Vvtvp(nqtot, &df[8][0], 1, &wsp6[0], 1, &g4[0], 1, &g4[0], 1);
1272
1273 // overwrite h0, h1, h2
1274 // wsp7 (h2f1 + h3f2)
1275 Vmath::Vvtvvtp(nqtot, &df[1][0], 1, &h2[0], 1, &df[2][0], 1, &h3[0], 1,
1276 &wsp7[0], 1);
1277 // wsp8 (h2f4 + h3f5)
1278 Vmath::Vvtvvtp(nqtot, &df[4][0], 1, &h2[0], 1, &df[5][0], 1, &h3[0], 1,
1279 &wsp8[0], 1);
1280 // wsp9 (h2f7 + h3f8)
1281 Vmath::Vvtvvtp(nqtot, &df[7][0], 1, &h2[0], 1, &df[8][0], 1, &h3[0], 1,
1282 &wsp9[0], 1);
1283
1284 // g3
1285 Vmath::Vvtvvtp(nqtot, &wsp4[0], 1, &wsp7[0], 1, &wsp5[0], 1, &wsp8[0],
1286 1, &g3[0], 1);
1287 Vmath::Vvtvp(nqtot, &wsp6[0], 1, &wsp9[0], 1, &g3[0], 1, &g3[0], 1);
1288
1289 // overwrite wsp4, wsp5, wsp6
1290 // g1
1291 Vmath::Vvtvvtp(nqtot, &wsp7[0], 1, &wsp7[0], 1, &wsp8[0], 1, &wsp8[0],
1292 1, &g1[0], 1);
1293 Vmath::Vvtvp(nqtot, &wsp9[0], 1, &wsp9[0], 1, &g1[0], 1, &g1[0], 1);
1294
1295 // g5
1296 Vmath::Vvtvvtp(nqtot, &df[2][0], 1, &wsp7[0], 1, &df[5][0], 1, &wsp8[0],
1297 1, &g5[0], 1);
1298 Vmath::Vvtvp(nqtot, &df[8][0], 1, &wsp9[0], 1, &g5[0], 1, &g5[0], 1);
1299
1300 // g2
1301 Vmath::Vvtvvtp(nqtot, &df[2][0], 1, &df[2][0], 1, &df[5][0], 1,
1302 &df[5][0], 1, &g2[0], 1);
1303 Vmath::Vvtvp(nqtot, &df[8][0], 1, &df[8][0], 1, &g2[0], 1, &g2[0], 1);
1304 }
1305 else
1306 {
1307 // wsp4
1308 Vmath::Svtsvtp(nqtot, df[0][0], &h0[0], 1, df[1][0] + df[2][0], &h1[0],
1309 1, &wsp4[0], 1);
1310 // wsp5
1311 Vmath::Svtsvtp(nqtot, df[3][0], &h0[0], 1, df[4][0] + df[5][0], &h1[0],
1312 1, &wsp5[0], 1);
1313 // wsp6
1314 Vmath::Svtsvtp(nqtot, df[6][0], &h0[0], 1, df[7][0] + df[8][0], &h1[0],
1315 1, &wsp6[0], 1);
1316
1317 // g0
1318 Vmath::Vvtvvtp(nqtot, &wsp4[0], 1, &wsp4[0], 1, &wsp5[0], 1, &wsp5[0],
1319 1, &g0[0], 1);
1320 Vmath::Vvtvp(nqtot, &wsp6[0], 1, &wsp6[0], 1, &g0[0], 1, &g0[0], 1);
1321
1322 // g4
1323 Vmath::Svtsvtp(nqtot, df[2][0], &wsp4[0], 1, df[5][0], &wsp5[0], 1,
1324 &g4[0], 1);
1325 Vmath::Svtvp(nqtot, df[8][0], &wsp6[0], 1, &g4[0], 1, &g4[0], 1);
1326
1327 // overwrite h0, h1, h2
1328 // wsp7 (h2f1 + h3f2)
1329 Vmath::Svtsvtp(nqtot, df[1][0], &h2[0], 1, df[2][0], &h3[0], 1,
1330 &wsp7[0], 1);
1331 // wsp8 (h2f4 + h3f5)
1332 Vmath::Svtsvtp(nqtot, df[4][0], &h2[0], 1, df[5][0], &h3[0], 1,
1333 &wsp8[0], 1);
1334 // wsp9 (h2f7 + h3f8)
1335 Vmath::Svtsvtp(nqtot, df[7][0], &h2[0], 1, df[8][0], &h3[0], 1,
1336 &wsp9[0], 1);
1337
1338 // g3
1339 Vmath::Vvtvvtp(nqtot, &wsp4[0], 1, &wsp7[0], 1, &wsp5[0], 1, &wsp8[0],
1340 1, &g3[0], 1);
1341 Vmath::Vvtvp(nqtot, &wsp6[0], 1, &wsp9[0], 1, &g3[0], 1, &g3[0], 1);
1342
1343 // overwrite wsp4, wsp5, wsp6
1344 // g1
1345 Vmath::Vvtvvtp(nqtot, &wsp7[0], 1, &wsp7[0], 1, &wsp8[0], 1, &wsp8[0],
1346 1, &g1[0], 1);
1347 Vmath::Vvtvp(nqtot, &wsp9[0], 1, &wsp9[0], 1, &g1[0], 1, &g1[0], 1);
1348
1349 // g5
1350 Vmath::Svtsvtp(nqtot, df[2][0], &wsp7[0], 1, df[5][0], &wsp8[0], 1,
1351 &g5[0], 1);
1352 Vmath::Svtvp(nqtot, df[8][0], &wsp9[0], 1, &g5[0], 1, &g5[0], 1);
1353
1354 // g2
1355 Vmath::Fill(nqtot,
1356 df[2][0] * df[2][0] + df[5][0] * df[5][0] +
1357 df[8][0] * df[8][0],
1358 &g2[0], 1);
1359 }
1360
1361 for (unsigned int i = 0; i < dim; ++i)
1362 {
1363 for (unsigned int j = i; j < dim; ++j)
1364 {
1365 MultiplyByQuadratureMetric(m_metrics[m[i][j]], m_metrics[m[i][j]]);
1366 }
1367 }
1368}
1369
1370/** @brief: This method gets all of the factors which are
1371 required as part of the Gradient Jump Penalty
1372 stabilisation and involves the product of the normal and
1373 geometric factors along the element trace.
1374*/
1375void TetExp::v_NormalTraceDerivFactors(
1376 Array<OneD, Array<OneD, NekDouble>> &d0factors,
1377 Array<OneD, Array<OneD, NekDouble>> &d1factors,
1378 Array<OneD, Array<OneD, NekDouble>> &d2factors)
1379{
1380 int nquad0 = GetNumPoints(0);
1381 int nquad1 = GetNumPoints(1);
1382 int nquad2 = GetNumPoints(2);
1383
1384 const Array<TwoD, const NekDouble> &df =
1385 m_metricinfo->GetDerivFactors(GetPointsKeys());
1386
1387 if (d0factors.size() != 4)
1388 {
1389 d0factors = Array<OneD, Array<OneD, NekDouble>>(4);
1390 d1factors = Array<OneD, Array<OneD, NekDouble>>(4);
1391 d2factors = Array<OneD, Array<OneD, NekDouble>>(4);
1392 }
1393
1394 if (d0factors[0].size() != nquad0 * nquad1)
1395 {
1396 d0factors[0] = Array<OneD, NekDouble>(nquad0 * nquad1);
1397 d1factors[0] = Array<OneD, NekDouble>(nquad0 * nquad1);
1398 d2factors[0] = Array<OneD, NekDouble>(nquad0 * nquad1);
1399 }
1400
1401 if (d0factors[1].size() != nquad0 * nquad2)
1402 {
1403 d0factors[1] = Array<OneD, NekDouble>(nquad0 * nquad2);
1404 d1factors[1] = Array<OneD, NekDouble>(nquad0 * nquad2);
1405 d2factors[1] = Array<OneD, NekDouble>(nquad0 * nquad2);
1406 }
1407
1408 if (d0factors[2].size() != nquad1 * nquad2)
1409 {
1410 d0factors[2] = Array<OneD, NekDouble>(nquad1 * nquad2);
1411 d0factors[3] = Array<OneD, NekDouble>(nquad1 * nquad2);
1412 d1factors[2] = Array<OneD, NekDouble>(nquad1 * nquad2);
1413 d1factors[3] = Array<OneD, NekDouble>(nquad1 * nquad2);
1414 d2factors[2] = Array<OneD, NekDouble>(nquad1 * nquad2);
1415 d2factors[3] = Array<OneD, NekDouble>(nquad1 * nquad2);
1416 }
1417
1418 // Outwards normals
1419 const Array<OneD, const Array<OneD, NekDouble>> &normal_0 =
1420 GetTraceNormal(0);
1421 const Array<OneD, const Array<OneD, NekDouble>> &normal_1 =
1422 GetTraceNormal(1);
1423 const Array<OneD, const Array<OneD, NekDouble>> &normal_2 =
1424 GetTraceNormal(2);
1425 const Array<OneD, const Array<OneD, NekDouble>> &normal_3 =
1426 GetTraceNormal(3);
1427
1428 int ncoords = normal_0.size();
1429
1430 // first gather together standard cartesian inner products
1431 if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
1432 {
1433 // face 0
1434 for (int i = 0; i < nquad0 * nquad1; ++i)
1435 {
1436 d0factors[0][i] = df[0][i] * normal_0[0][i];
1437 d1factors[0][i] = df[1][i] * normal_0[0][i];
1438 d2factors[0][i] = df[2][i] * normal_0[0][i];
1439 }
1440
1441 for (int n = 1; n < ncoords; ++n)
1442 {
1443 for (int i = 0; i < nquad0 * nquad1; ++i)
1444 {
1445 d0factors[0][i] += df[3 * n][i] * normal_0[n][i];
1446 d1factors[0][i] += df[3 * n + 1][i] * normal_0[n][i];
1447 d2factors[0][i] += df[3 * n + 2][i] * normal_0[n][i];
1448 }
1449 }
1450
1451 // face 1
1452 for (int j = 0; j < nquad2; ++j)
1453 {
1454 for (int i = 0; i < nquad0; ++i)
1455 {
1456 d0factors[1][j * nquad0 + i] = df[0][j * nquad0 * nquad1 + i] *
1457 normal_1[0][j * nquad0 + i];
1458 d1factors[1][j * nquad0 + i] = df[1][j * nquad0 * nquad1 + i] *
1459 normal_1[0][j * nquad0 + i];
1460 d2factors[1][j * nquad0 + i] = df[2][j * nquad0 * nquad1 + i] *
1461 normal_1[0][j * nquad0 + i];
1462 }
1463 }
1464
1465 for (int n = 1; n < ncoords; ++n)
1466 {
1467 for (int j = 0; j < nquad2; ++j)
1468 {
1469 for (int i = 0; i < nquad0; ++i)
1470 {
1471 d0factors[1][j * nquad0 + i] +=
1472 df[3 * n][j * nquad0 * nquad1 + i] *
1473 normal_1[0][j * nquad0 + i];
1474 d1factors[1][j * nquad0 + i] +=
1475 df[3 * n + 1][j * nquad0 * nquad1 + i] *
1476 normal_1[0][j * nquad0 + i];
1477 d2factors[1][j * nquad0 + i] +=
1478 df[3 * n + 2][j * nquad0 * nquad1 + i] *
1479 normal_1[0][j * nquad0 + i];
1480 }
1481 }
1482 }
1483
1484 // faces 2 and 3
1485 for (int j = 0; j < nquad2; ++j)
1486 {
1487 for (int i = 0; i < nquad1; ++i)
1488 {
1489 d0factors[2][j * nquad1 + i] =
1490 df[0][(j * nquad1 + i + 1) * nquad0 - 1] *
1491 normal_2[0][j * nquad1 + i];
1492 d1factors[2][j * nquad1 + i] =
1493 df[1][(j * nquad1 + i + 1) * nquad0 - 1] *
1494 normal_2[0][j * nquad1 + i];
1495 d2factors[2][j * nquad1 + i] =
1496 df[2][(j * nquad1 + i + 1) * nquad0 - 1] *
1497 normal_2[0][j * nquad1 + i];
1498
1499 d0factors[3][j * nquad1 + i] =
1500 df[0][(j * nquad1 + i) * nquad0] *
1501 normal_3[0][j * nquad1 + i];
1502 d1factors[3][j * nquad1 + i] =
1503 df[1][(j * nquad1 + i) * nquad0] *
1504 normal_3[0][j * nquad1 + i];
1505 d2factors[3][j * nquad1 + i] =
1506 df[2][(j * nquad1 + i) * nquad0] *
1507 normal_3[0][j * nquad1 + i];
1508 }
1509 }
1510
1511 for (int n = 1; n < ncoords; ++n)
1512 {
1513 for (int j = 0; j < nquad2; ++j)
1514 {
1515 for (int i = 0; i < nquad1; ++i)
1516 {
1517 d0factors[2][j * nquad1 + i] +=
1518 df[3 * n][(j * nquad1 + i + 1) * nquad0 - 1] *
1519 normal_2[n][j * nquad1 + i];
1520 d1factors[2][j * nquad1 + i] +=
1521 df[3 * n + 1][(j * nquad1 + i + 1) * nquad0 - 1] *
1522 normal_2[n][j * nquad1 + i];
1523 d2factors[2][j * nquad1 + i] +=
1524 df[3 * n + 2][(j * nquad1 + i + 1) * nquad0 - 1] *
1525 normal_2[n][j * nquad1 + i];
1526
1527 d0factors[3][j * nquad1 + i] +=
1528 df[3 * n][(j * nquad1 + i) * nquad0] *
1529 normal_3[n][j * nquad1 + i];
1530 d1factors[3][j * nquad1 + i] +=
1531 df[3 * n + 1][(j * nquad1 + i) * nquad0] *
1532 normal_3[n][j * nquad1 + i];
1533 d2factors[3][j * nquad1 + i] +=
1534 df[3 * n + 2][(j * nquad1 + i) * nquad0] *
1535 normal_3[n][j * nquad1 + i];
1536 }
1537 }
1538 }
1539 }
1540 else
1541 {
1542 // Face 0
1543 for (int i = 0; i < nquad0 * nquad1; ++i)
1544 {
1545 d0factors[0][i] = df[0][0] * normal_0[0][i];
1546 d1factors[0][i] = df[1][0] * normal_0[0][i];
1547 d2factors[0][i] = df[2][0] * normal_0[0][i];
1548 }
1549
1550 for (int n = 1; n < ncoords; ++n)
1551 {
1552 for (int i = 0; i < nquad0 * nquad1; ++i)
1553 {
1554 d0factors[0][i] += df[3 * n][0] * normal_0[n][i];
1555 d1factors[0][i] += df[3 * n + 1][0] * normal_0[n][i];
1556 d2factors[0][i] += df[3 * n + 2][0] * normal_0[n][i];
1557 }
1558 }
1559
1560 // face 1
1561 for (int i = 0; i < nquad0 * nquad2; ++i)
1562 {
1563 d0factors[1][i] = df[0][0] * normal_1[0][i];
1564 d1factors[1][i] = df[1][0] * normal_1[0][i];
1565 d2factors[1][i] = df[2][0] * normal_1[0][i];
1566 }
1567
1568 for (int n = 1; n < ncoords; ++n)
1569 {
1570 for (int i = 0; i < nquad0 * nquad2; ++i)
1571 {
1572 d0factors[1][i] += df[3 * n][0] * normal_1[n][i];
1573 d1factors[1][i] += df[3 * n + 1][0] * normal_1[n][i];
1574 d2factors[1][i] += df[3 * n + 2][0] * normal_1[n][i];
1575 }
1576 }
1577
1578 // faces 2 and 3
1579 for (int i = 0; i < nquad1 * nquad2; ++i)
1580 {
1581 d0factors[2][i] = df[0][0] * normal_2[0][i];
1582 d0factors[3][i] = df[0][0] * normal_3[0][i];
1583
1584 d1factors[2][i] = df[1][0] * normal_2[0][i];
1585 d1factors[3][i] = df[1][0] * normal_3[0][i];
1586
1587 d2factors[2][i] = df[2][0] * normal_2[0][i];
1588 d2factors[3][i] = df[2][0] * normal_3[0][i];
1589 }
1590
1591 for (int n = 1; n < ncoords; ++n)
1592 {
1593 for (int i = 0; i < nquad1 * nquad2; ++i)
1594 {
1595 d0factors[2][i] += df[3 * n][0] * normal_2[n][i];
1596 d0factors[3][i] += df[3 * n][0] * normal_3[n][i];
1597
1598 d1factors[2][i] += df[3 * n + 1][0] * normal_2[n][i];
1599 d1factors[3][i] += df[3 * n + 1][0] * normal_3[n][i];
1600
1601 d2factors[2][i] += df[3 * n + 2][0] * normal_2[n][i];
1602 d2factors[3][i] += df[3 * n + 2][0] * normal_3[n][i];
1603 }
1604 }
1605 }
1606}
1607} // namespace LocalRegions
1608} // 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
Describes the specification for a Basis.
Definition: Basis.h:47
int GetNumPoints() const
Return points order at which basis is defined.
Definition: Basis.h:122
PointsKey GetPointsKey() const
Return distribution of points.
Definition: Basis.h:139
Defines a specification for a set of points.
Definition: Points.h:55
virtual DNekMatSharedPtr v_GenMatrix(const StdRegions::StdMatrixKey &mkey) override
std::map< int, NormalVector > m_traceNormals
Definition: Expansion.h:278
std::map< int, Array< OneD, NekDouble > > m_elmtBndNormDirElmtLen
the element length in each element boundary(Vertex, edge or face) normal direction calculated based o...
Definition: Expansion.h:288
SpatialDomains::GeometrySharedPtr GetGeom() const
Definition: Expansion.cpp:171
SpatialDomains::GeometrySharedPtr m_geom
Definition: Expansion.h:275
virtual void v_GetCoords(Array< OneD, NekDouble > &coords_1, Array< OneD, NekDouble > &coords_2, Array< OneD, NekDouble > &coords_3) override
Definition: Expansion.cpp:535
SpatialDomains::GeomFactorsSharedPtr m_metricinfo
Definition: Expansion.h:276
DNekScalMatSharedPtr GetLocMatrix(const LocalRegions::MatrixKey &mkey)
Definition: Expansion.cpp:88
void v_ComputeTraceNormal(const int face) override
Compute the normal of a triangular face.
Definition: TetExp.cpp:706
virtual NekDouble v_PhysEvaluate(const Array< OneD, const NekDouble > &coords, const Array< OneD, const NekDouble > &physvals) override
Definition: TetExp.cpp:473
virtual NekDouble v_Integral(const Array< OneD, const NekDouble > &inarray) override
Integrate the physical point list inarray over region.
Definition: TetExp.cpp:106
virtual DNekScalMatSharedPtr v_GetLocMatrix(const MatrixKey &mkey) override
Definition: TetExp.cpp:1051
virtual NekDouble v_StdPhysEvaluate(const Array< OneD, const NekDouble > &Lcoord, const Array< OneD, const NekDouble > &physvals) override
Definition: TetExp.cpp:461
virtual void v_PhysDeriv(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &out_d0, Array< OneD, NekDouble > &out_d1, Array< OneD, NekDouble > &out_d2) override
Differentiate inarray in the three coordinate directions.
Definition: TetExp.cpp:145
void v_DropLocMatrix(const MatrixKey &mkey) override
Definition: TetExp.cpp:1056
LibUtilities::NekManager< MatrixKey, DNekScalBlkMat, MatrixKey::opLess > m_staticCondMatrixManager
Definition: TetExp.h:204
LibUtilities::NekManager< MatrixKey, DNekScalMat, MatrixKey::opLess > m_matrixManager
Definition: TetExp.h:202
virtual DNekMatSharedPtr v_GenMatrix(const StdRegions::StdMatrixKey &mkey) override
Definition: TetExp.cpp:1018
virtual void v_LaplacianMatrixOp(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::StdMatrixKey &mkey) override
Definition: TetExp.cpp:973
virtual void v_IProductWRTBase_SumFac(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool multiplybyweights=true) override
Definition: TetExp.cpp:286
virtual DNekScalBlkMatSharedPtr v_GetLocStaticCondMatrix(const MatrixKey &mkey) override
Definition: TetExp.cpp:1061
virtual void v_GetCoord(const Array< OneD, const NekDouble > &Lcoords, Array< OneD, NekDouble > &coords) override
Get the coordinates "coords" at the local coordinates "Lcoords".
Definition: TetExp.cpp:500
virtual void v_IProductWRTBase(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) override
Calculate the inner product of inarray with respect to the basis B=m_base0*m_base1*m_base2 and put in...
Definition: TetExp.cpp:280
virtual void v_FwdTrans(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) override
Forward transform from physical quadrature space stored in inarray and evaluate the expansion coeffic...
Definition: TetExp.cpp:227
virtual StdRegions::StdExpansionSharedPtr v_GetStdExp(void) const override
Definition: TetExp.cpp:536
virtual LibUtilities::ShapeType v_DetShapeType() const override
Return Shape of region, using ShapeType enum list.
Definition: TetExp.cpp:531
virtual DNekMatSharedPtr v_CreateStdMatrix(const StdRegions::StdMatrixKey &mkey) override
Definition: TetExp.cpp:1040
virtual void v_IProductWRTDerivBase(const int dir, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) override
Calculates the inner product .
Definition: TetExp.cpp:345
virtual StdRegions::StdExpansionSharedPtr v_GetLinStdExp(void) const override
Definition: TetExp.cpp:543
TetExp(const LibUtilities::BasisKey &Ba, const LibUtilities::BasisKey &Bb, const LibUtilities::BasisKey &Bc, const SpatialDomains::TetGeomSharedPtr &geom)
Constructor using BasisKey class for quadrature points and order definition.
Definition: TetExp.cpp:61
virtual void v_GetCoords(Array< OneD, NekDouble > &coords_1, Array< OneD, NekDouble > &coords_2, Array< OneD, NekDouble > &coords_3) override
Definition: TetExp.cpp:517
void GeneralMatrixOp_MatOp(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::StdMatrixKey &mkey)
Definition: TetExp.cpp:1071
void v_DropLocStaticCondMatrix(const MatrixKey &mkey) override
Definition: TetExp.cpp:1066
virtual void v_SVVLaplacianFilter(Array< OneD, NekDouble > &array, const StdRegions::StdMatrixKey &mkey) override
Definition: TetExp.cpp:988
virtual void v_AlignVectorToCollapsedDir(const int dir, const Array< OneD, const NekDouble > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray) override
Definition: TetExp.cpp:390
virtual void v_GetTracePhysMap(const int face, Array< OneD, int > &outarray) override
Returns the physical values at the quadrature points of a face.
Definition: TetExp.cpp:618
virtual void v_HelmholtzMatrixOp(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::StdMatrixKey &mkey) override
Definition: TetExp.cpp:966
virtual void v_LaplacianMatrixOp_MatFree_Kernel(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, Array< OneD, NekDouble > &wsp) override
Definition: TetExp.cpp:1094
virtual void v_ExtractDataToCoeffs(const NekDouble *data, const std::vector< unsigned int > &nummodes, const int mode_offset, NekDouble *coeffs, std::vector< LibUtilities::BasisType > &fromType) override
Definition: TetExp.cpp:556
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
void IProductWRTBase_SumFacKernel(const Array< OneD, const NekDouble > &base0, const Array< OneD, const NekDouble > &base1, const Array< OneD, const NekDouble > &base2, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, Array< OneD, NekDouble > &wsp, bool doCheckCollDir0, bool doCheckCollDir1, bool doCheckCollDir2)
virtual void v_HelmholtzMatrixOp_MatFree(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::StdMatrixKey &mkey) override
virtual void v_LaplacianMatrixOp_MatFree(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::StdMatrixKey &mkey) override
int GetNcoeffs(void) const
This function returns the total number of coefficients used in the expansion.
Definition: StdExpansion.h:130
int GetTotPoints() const
This function returns the total number of quadrature points used in the element.
Definition: StdExpansion.h:140
LibUtilities::BasisType GetBasisType(const int dir) const
This function returns the type of basis used in the dir direction.
Definition: StdExpansion.h:162
const LibUtilities::PointsKeyVector GetPointsKeys() const
const LibUtilities::BasisKey GetTraceBasisKey(const int i, int k=-1) const
This function returns the basis key belonging to the i-th trace.
Definition: StdExpansion.h:305
void IProductWRTBase(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
this function calculates the inner product of a given function f with the different modes of the expa...
Definition: StdExpansion.h:534
LibUtilities::PointsType GetPointsType(const int dir) const
This function returns the type of quadrature points used in the dir direction.
Definition: StdExpansion.h:211
int GetNumPoints(const int dir) const
This function returns the number of quadrature points in the dir direction.
Definition: StdExpansion.h:224
void MultiplyByQuadratureMetric(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: StdExpansion.h:729
Array< OneD, LibUtilities::BasisSharedPtr > m_base
MatrixType GetMatrixType() const
Definition: StdMatrixKey.h:87
LibUtilities::ShapeType DetShapeType() const
Definition: StdTetExp.h:64
static void Dgemv(const char &trans, const int &m, const int &n, const double &alpha, const double *a, const int &lda, const double *x, const int &incx, const double &beta, double *y, const int &incy)
BLAS level 2: Matrix vector multiply y = alpha A x plus beta y where A[m x n].
Definition: Blas.hpp:213
static void Daxpy(const int &n, const double &alpha, const double *x, const int &incx, const double *y, const int &incy)
BLAS level 1: y = alpha x plus y.
Definition: Blas.hpp:137
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
@ eModified_B
Principle Modified Functions .
Definition: BasisType.h:51
@ eModified_C
Principle Modified Functions .
Definition: BasisType.h:52
@ eModified_A
Principle Modified Functions .
Definition: BasisType.h:50
std::shared_ptr< GeomFactors > GeomFactorsSharedPtr
Pointer to a GeomFactors object.
Definition: GeomFactors.h:62
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.
std::shared_ptr< TetGeom > TetGeomSharedPtr
Definition: TetGeom.h:85
std::shared_ptr< StdTetExp > StdTetExpSharedPtr
Definition: StdTetExp.h:255
std::shared_ptr< StdExpansion > StdExpansionSharedPtr
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
std::shared_ptr< DNekScalMat > DNekScalMatSharedPtr
std::shared_ptr< DNekScalBlkMat > DNekScalBlkMatSharedPtr
Definition: NekTypeDefs.hpp:79
std::shared_ptr< DNekMat > DNekMatSharedPtr
Definition: NekTypeDefs.hpp:75
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 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 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 Sdiv(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha/x.
Definition: Vmath.cpp:319
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 Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:487
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