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