Nektar++
IProductWRTDerivBase.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: IProductWRTDerivBase.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: IProductWRTDerivBase operator implementations
32//
33///////////////////////////////////////////////////////////////////////////////
34
39#include <MatrixFreeOps/Operator.hpp>
40
41using namespace std;
42
43namespace Nektar::Collections
44{
45
53
54/**
55 * @brief Inner product deriv base help class to calculate the size of the
56 * collection that is given as an input and as an output to the
57 * IProductWRTDerivBase Operator. The size evaluation takes into account the
58 * conversion from the physical space to the coefficient space.
59 */
61{
62protected:
64 {
65 // expect input to be number of elements by the number of quad points
66 m_inputSize = m_numElmt * m_stdExp->GetTotPoints();
67 // expect input to be number of elements by the number of coefficients
68 m_outputSize = m_numElmt * m_stdExp->GetNcoeffs();
69 }
70};
71
72/**
73 * @brief Inner product WRT deriv base operator using standard matrix approach
74 */
75class IProductWRTDerivBase_StdMat final : virtual public Operator,
77{
78public:
80
82
83 void operator()(const Array<OneD, const NekDouble> &entry0,
84 Array<OneD, NekDouble> &entry1,
85 Array<OneD, NekDouble> &entry2,
86 Array<OneD, NekDouble> &entry3,
87 Array<OneD, NekDouble> &wsp) final
88 {
89 int nPhys = m_stdExp->GetTotPoints();
90 int ntot = m_numElmt * nPhys;
91 int nmodes = m_stdExp->GetNcoeffs();
95
96 in[0] = entry0;
97 in[1] = entry1;
98 in[2] = entry2;
99
100 output = (m_coordim == 3) ? entry3 : (m_coordim == 2) ? entry2 : entry1;
101
102 for (int i = 0; i < m_dim; ++i)
103 {
104 tmp[i] = wsp + i * ntot;
105 }
106
107 // calculate Iproduct WRT Std Deriv
108
109 // First component
110 if (m_isDeformed)
111 {
112 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
113 for (int i = 0; i < m_dim; ++i)
114 {
115 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
116 for (int j = 1; j < m_coordim; ++j)
117 {
118 Vmath::Vvtvp(ntot, m_derivFac[i + j * m_dim], 1, in[j], 1,
119 tmp[i], 1, tmp[i], 1);
120 }
121 }
122
123 Vmath::Vmul(ntot, m_jac, 1, tmp[0], 1, tmp[0], 1);
124 }
125 else
126 {
128 for (int e = 0; e < m_numElmt; ++e)
129 {
130 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
131 for (int i = 0; i < m_dim; ++i)
132 {
133 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
134 t = tmp[i] + e * m_nqe, 1);
135 for (int j = 1; j < m_coordim; ++j)
136 {
137 Vmath::Svtvp(m_nqe, m_derivFac[i + j * m_dim][e],
138 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
139 1, t = tmp[i] + e * m_nqe, 1);
140 }
141 }
142
143 Vmath::Smul(m_nqe, m_jac[e], tmp[0] + e * m_nqe, 1,
144 t = tmp[0] + e * m_nqe, 1);
145 }
146 }
147
148 Blas::Dgemm('N', 'N', m_iProdWRTStdDBase[0]->GetRows(), m_numElmt,
149 m_iProdWRTStdDBase[0]->GetColumns(), 1.0,
150 m_iProdWRTStdDBase[0]->GetRawPtr(),
151 m_iProdWRTStdDBase[0]->GetRows(), tmp[0].get(), nPhys, 0.0,
152 output.get(), nmodes);
153
154 // Other components
155 for (int i = 1; i < m_dim; ++i)
156 {
157 if (m_isDeformed)
158 {
159 Vmath::Vmul(ntot, m_jac, 1, tmp[i], 1, tmp[i], 1);
160 }
161 else
162 {
164 for (int e = 0; e < m_numElmt; ++e)
165 {
166 Vmath::Smul(m_nqe, m_jac[e], tmp[i] + e * m_nqe, 1,
167 t = tmp[i] + e * m_nqe, 1);
168 }
169 }
170 Blas::Dgemm('N', 'N', m_iProdWRTStdDBase[i]->GetRows(), m_numElmt,
171 m_iProdWRTStdDBase[i]->GetColumns(), 1.0,
172 m_iProdWRTStdDBase[i]->GetRawPtr(),
173 m_iProdWRTStdDBase[i]->GetRows(), tmp[i].get(), nPhys,
174 1.0, output.get(), nmodes);
175 }
176 }
177
178 void operator()([[maybe_unused]] int dir,
179 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
180 [[maybe_unused]] Array<OneD, NekDouble> &output,
181 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
182 {
183 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
184 }
185
186protected:
190 int m_dim;
192
193private:
195 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
197 : Operator(pCollExp, pGeomData, factors), IProductWRTDerivBase_Helper()
198 {
199 m_dim = pCollExp[0]->GetShapeDimension();
200 m_coordim = pCollExp[0]->GetCoordim();
201
202 m_nqe = m_stdExp->GetTotPoints();
203 int nmodes = m_stdExp->GetNcoeffs();
204
205 // set up a IProductWRTDerivBase StdMat.
207 for (int i = 0; i < m_dim; ++i)
208 {
209 Array<OneD, NekDouble> tmp(m_nqe), tmp1(nmodes);
212 for (int j = 0; j < m_nqe; ++j)
213 {
214 Vmath::Zero(m_nqe, tmp, 1);
215 tmp[j] = 1.0;
216 m_stdExp->IProductWRTDerivBase(i, tmp, tmp1);
217 Vmath::Vcopy(nmodes, &tmp1[0], 1,
218 &(m_iProdWRTStdDBase[i]->GetPtr())[0] + j * nmodes,
219 1);
220 }
221 }
222 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
223 m_jac = pGeomData->GetJac(pCollExp);
225 }
226};
227
228/// Factory initialisation for the IProductWRTDerivBase_StdMat operators
229OperatorKey IProductWRTDerivBase_StdMat::m_typeArr[] = {
232 IProductWRTDerivBase_StdMat::create, "IProductWRTDerivBase_StdMat_Seg"),
235 IProductWRTDerivBase_StdMat::create, "IProductWRTDerivBase_StdMat_Tri"),
238 IProductWRTDerivBase_StdMat::create,
239 "IProductWRTDerivBase_StdMat_NodalTri"),
242 IProductWRTDerivBase_StdMat::create,
243 "IProductWRTDerivBase_StdMat_Quad"),
246 IProductWRTDerivBase_StdMat::create, "IProductWRTDerivBase_StdMat_Tet"),
249 IProductWRTDerivBase_StdMat::create,
250 "IProductWRTDerivBase_StdMat_NodalTet"),
253 IProductWRTDerivBase_StdMat::create, "IProductWRTDerivBase_StdMat_Pyr"),
256 IProductWRTDerivBase_StdMat::create,
257 "IProductWRTDerivBase_StdMat_Prism"),
260 IProductWRTDerivBase_StdMat::create,
261 "IProductWRTDerivBase_StdMat_NodalPrism"),
264 IProductWRTDerivBase_StdMat::create, "IProductWRTDerivBase_StdMat_Hex"),
267 IProductWRTDerivBase_StdMat::create,
268 "IProductWRTDerivBase_SumFac_Pyr")};
269
270/**
271 * @brief Inner product operator using operator using matrix free operators.
272 */
273class IProductWRTDerivBase_MatrixFree final : virtual public Operator,
276{
277public:
279
281
282 void operator()(const Array<OneD, const NekDouble> &entry0,
283 Array<OneD, NekDouble> &entry1,
284 Array<OneD, NekDouble> &entry2,
285 Array<OneD, NekDouble> &entry3,
286 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
287 {
289
290 if (m_isPadded)
291 {
292 // copy into padded vector
293 switch (m_coordim)
294 {
295 case 1:
296 output = entry1;
297 Vmath::Vcopy(m_nIn, entry0, 1, m_input[0], 1);
298 break;
299 case 2:
300 output = entry2;
301 Vmath::Vcopy(m_nIn, entry0, 1, m_input[0], 1);
302 Vmath::Vcopy(m_nIn, entry1, 1, m_input[1], 1);
303 break;
304 case 3:
305 output = entry3;
306 Vmath::Vcopy(m_nIn, entry0, 1, m_input[0], 1);
307 Vmath::Vcopy(m_nIn, entry1, 1, m_input[1], 1);
308 Vmath::Vcopy(m_nIn, entry2, 1, m_input[2], 1);
309 break;
310 default:
311 NEKERROR(ErrorUtil::efatal, "m_coordim value not valid");
312 break;
313 }
314
315 // call op
316 (*m_oper)(m_input, m_output);
317 // copy out of padded vector
318 Vmath::Vcopy(m_nOut, m_output, 1, output, 1);
319 }
320 else
321 {
323
324 // copy into padded vector
325 switch (m_coordim)
326 {
327 case 1:
328 output = entry1;
329 input[0] = entry0;
330 break;
331 case 2:
332 output = entry2;
333 input[0] = entry0;
334 input[1] = entry1;
335 break;
336 case 3:
337 output = entry3;
338 input[0] = entry0;
339 input[1] = entry1;
340 input[2] = entry2;
341 break;
342 default:
343 NEKERROR(ErrorUtil::efatal, "coordim not valid");
344 break;
345 }
346
347 (*m_oper)(input, output);
348 }
349 }
350
351 void operator()([[maybe_unused]] int dir,
352 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
353 [[maybe_unused]] Array<OneD, NekDouble> &output,
354 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
355 {
356 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
357 }
358
359private:
360 std::shared_ptr<MatrixFree::IProductWRTDerivBase> m_oper;
361
363 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
365 : Operator(pCollExp, pGeomData, factors),
366 MatrixFreeMultiInOneOut(pCollExp[0]->GetCoordim(),
367 pCollExp[0]->GetStdExp()->GetTotPoints(),
368 pCollExp[0]->GetStdExp()->GetNcoeffs(),
369 pCollExp.size()),
371 {
372 // Check if deformed
373 const auto dim = pCollExp[0]->GetStdExp()->GetShapeDimension();
374
375 // Basis vector
376 std::vector<LibUtilities::BasisSharedPtr> basis(dim);
377 for (unsigned int i = 0; i < dim; ++i)
378 {
379 basis[i] = pCollExp[0]->GetBasis(i);
380 }
381
382 // Get shape type
383 auto shapeType = pCollExp[0]->GetStdExp()->DetShapeType();
384
385 // Generate operator string and create operator.
386 std::string op_string = "IProductWRTDerivBase";
387 op_string += MatrixFree::GetOpstring(shapeType, m_isDeformed);
389 op_string, basis, m_nElmtPad);
390
391 // Set Jacobian
392 oper->SetJac(pGeomData->GetJacInterLeave(pCollExp, m_nElmtPad));
393
394 // Set derivative factors
395 oper->SetDF(pGeomData->GetDerivFactorsInterLeave(pCollExp, m_nElmtPad));
396
397 m_oper =
398 std::dynamic_pointer_cast<MatrixFree::IProductWRTDerivBase>(oper);
399 ASSERTL0(m_oper, "Failed to cast pointer.");
400 }
401};
402
403/// Factory initialisation for the IProductWRTDerivBase_MatrixFree operators
404OperatorKey IProductWRTDerivBase_MatrixFree::m_typeArr[] = {
407 IProductWRTDerivBase_MatrixFree::create,
408 "IProductWRTDerivBase_MatrixFree_Seg"),
411 IProductWRTDerivBase_MatrixFree::create,
412 "IProductWRTDerivBase_MatrixFree_Quad"),
415 IProductWRTDerivBase_MatrixFree::create,
416 "IProductWRTDerivBase_MatrixFree_Tri"),
419 IProductWRTDerivBase_MatrixFree::create,
420 "IProductWRTDerivBase_MatrixFree_Hex"),
423 IProductWRTDerivBase_MatrixFree::create,
424 "IProductWRTDerivBase_MatrixFree_Prism"),
427 IProductWRTDerivBase_MatrixFree::create,
428 "IProductWRTDerivBase_MatrixFree_Pyr"),
431 IProductWRTDerivBase_MatrixFree::create,
432 "IProductWRTDerivBase_MatrixFree_Tet")};
433
434/**
435 * @brief Inner product WRT deriv base operator using element-wise operation
436 */
437class IProductWRTDerivBase_IterPerExp final : virtual public Operator,
439{
440public:
442
444
445 void operator()(const Array<OneD, const NekDouble> &entry0,
446 Array<OneD, NekDouble> &entry1,
447 Array<OneD, NekDouble> &entry2,
448 Array<OneD, NekDouble> &entry3,
449 Array<OneD, NekDouble> &wsp) final
450 {
451 unsigned int nPhys = m_stdExp->GetTotPoints();
452 unsigned int ntot = m_numElmt * nPhys;
453 unsigned int nmodes = m_stdExp->GetNcoeffs();
454 unsigned int nmax = max(ntot, m_numElmt * nmodes);
456 Array<OneD, NekDouble> output, tmp1;
458
459 in[0] = entry0;
460 in[1] = entry1;
461 in[2] = entry2;
462
463 output = (m_coordim == 3) ? entry3 : (m_coordim == 2) ? entry2 : entry1;
464
465 for (int i = 0; i < m_dim; ++i)
466 {
467 tmp[i] = wsp + i * nmax;
468 }
469
470 // calculate Iproduct WRT Std Deriv
471 // first component
472 if (m_isDeformed)
473 {
474 // calculate dx/dxi in[0] + dy/dxi in[2] + dz/dxi in[3]
475 for (int i = 0; i < m_dim; ++i)
476 {
477 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
478 for (int j = 1; j < m_coordim; ++j)
479 {
480 Vmath::Vvtvp(ntot, m_derivFac[i + j * m_dim], 1, in[j], 1,
481 tmp[i], 1, tmp[i], 1);
482 }
483 }
484
485 Vmath::Vmul(ntot, m_jac, 1, tmp[0], 1, tmp[0], 1);
486 }
487 else
488 {
490 for (int e = 0; e < m_numElmt; ++e)
491 {
492 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
493 for (int i = 0; i < m_dim; ++i)
494 {
495 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
496 t = tmp[i] + e * m_nqe, 1);
497 for (int j = 1; j < m_coordim; ++j)
498 {
499 Vmath::Svtvp(m_nqe, m_derivFac[i + j * m_dim][e],
500 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
501 1, t = tmp[i] + e * m_nqe, 1);
502 }
503 }
504
505 Vmath::Smul(m_nqe, m_jac[e], tmp[0] + e * m_nqe, 1,
506 t = tmp[0] + e * m_nqe, 1);
507 }
508 }
509
510 for (int n = 0; n < m_numElmt; ++n)
511 {
512 m_stdExp->IProductWRTDerivBase(0, tmp[0] + n * nPhys,
513 tmp1 = output + n * nmodes);
514 }
515
516 // other components
517 for (int i = 1; i < m_dim; ++i)
518 {
519 // multiply by Jacobian
520 if (m_isDeformed)
521 {
522 Vmath::Vmul(ntot, m_jac, 1, tmp[i], 1, tmp[i], 1);
523 }
524 else
525 {
527 for (int e = 0; e < m_numElmt; ++e)
528 {
529 Vmath::Smul(m_nqe, m_jac[e], tmp[i] + e * m_nqe, 1,
530 t = tmp[i] + e * m_nqe, 1);
531 }
532 }
533
534 for (int n = 0; n < m_numElmt; ++n)
535 {
536 m_stdExp->IProductWRTDerivBase(i, tmp[i] + n * nPhys, tmp[0]);
537 Vmath::Vadd(nmodes, tmp[0], 1, output + n * nmodes, 1,
538 tmp1 = output + n * nmodes, 1);
539 }
540 }
541 }
542
543 void operator()([[maybe_unused]] int dir,
544 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
545 [[maybe_unused]] Array<OneD, NekDouble> &output,
546 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
547 {
548 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
549 }
550
551protected:
554 int m_dim;
556
557private:
559 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
561 : Operator(pCollExp, pGeomData, factors), IProductWRTDerivBase_Helper()
562 {
563 m_dim = pCollExp[0]->GetShapeDimension();
564 m_coordim = pCollExp[0]->GetCoordim();
565
566 m_nqe = m_stdExp->GetTotPoints();
567
568 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
569 m_jac = pGeomData->GetJac(pCollExp);
571 }
572};
573
574/// Factory initialisation for the IProductWRTDerivBase_IterPerExp operators
575OperatorKey IProductWRTDerivBase_IterPerExp::m_typeArr[] = {
578 IProductWRTDerivBase_IterPerExp::create,
579 "IProductWRTDerivBase_IterPerExp_Seg"),
582 IProductWRTDerivBase_IterPerExp::create,
583 "IProductWRTDerivBase_IterPerExp_Tri"),
586 IProductWRTDerivBase_IterPerExp::create,
587 "IProductWRTDerivBase_IterPerExp_NodalTri"),
590 IProductWRTDerivBase_IterPerExp::create,
591 "IProductWRTDerivBase_IterPerExp_Quad"),
594 IProductWRTDerivBase_IterPerExp::create,
595 "IProductWRTDerivBase_IterPerExp_Tet"),
598 IProductWRTDerivBase_IterPerExp::create,
599 "IProductWRTDerivBase_IterPerExp_NodalTet"),
602 IProductWRTDerivBase_IterPerExp::create,
603 "IProductWRTDerivBase_IterPerExp_Pyr"),
606 IProductWRTDerivBase_IterPerExp::create,
607 "IProductWRTDerivBase_IterPerExp_Prism"),
610 IProductWRTDerivBase_IterPerExp::create,
611 "IProductWRTDerivBase_IterPerExp_NodalPrism"),
614 IProductWRTDerivBase_IterPerExp::create,
615 "IProductWRTDerivBase_IterPerExp_Hex")};
616
617/**
618 * @brief Inner product WRT deriv base operator using LocalRegions
619 * implementation.
620 */
621class IProductWRTDerivBase_NoCollection final : virtual public Operator,
623{
624public:
626
628
629 void operator()(const Array<OneD, const NekDouble> &entry0,
630 Array<OneD, NekDouble> &entry1,
631 Array<OneD, NekDouble> &entry2,
632 Array<OneD, NekDouble> &entry3,
633 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
634 {
635 unsigned int nmodes = m_expList[0]->GetNcoeffs();
636 unsigned int nPhys = m_expList[0]->GetTotPoints();
637 Array<OneD, NekDouble> tmp(nmodes), tmp1;
638
641 in[0] = entry0;
642 in[1] = entry1;
643 in[2] = entry2;
644
645 output = (m_coordim == 3) ? entry3 : (m_coordim == 2) ? entry2 : entry1;
646
647 for (int n = 0; n < m_numElmt; ++n)
648 {
649 m_expList[n]->IProductWRTDerivBase(0, in[0] + n * nPhys,
650 tmp1 = output + n * nmodes);
651 }
652
653 for (int i = 1; i < m_dim; ++i)
654 {
655 for (int n = 0; n < m_numElmt; ++n)
656 {
657 m_expList[n]->IProductWRTDerivBase(i, in[i] + n * nPhys, tmp);
658
659 Vmath::Vadd(nmodes, tmp, 1, output + n * nmodes, 1,
660 tmp1 = output + n * nmodes, 1);
661 }
662 }
663 }
664
665 void operator()([[maybe_unused]] int dir,
666 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
667 [[maybe_unused]] Array<OneD, NekDouble> &output,
668 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
669 {
670 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
671 }
672
673protected:
674 int m_dim;
676 vector<StdRegions::StdExpansionSharedPtr> m_expList;
677
678private:
680 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
682 : Operator(pCollExp, pGeomData, factors), IProductWRTDerivBase_Helper()
683 {
684 m_expList = pCollExp;
685 m_dim = pCollExp[0]->GetNumBases();
686 m_coordim = pCollExp[0]->GetCoordim();
687 }
688};
689
690/// Factory initialisation for the IProductWRTDerivBase_NoCollection operators
691OperatorKey IProductWRTDerivBase_NoCollection::m_typeArr[] = {
694 IProductWRTDerivBase_NoCollection::create,
695 "IProductWRTDerivBase_NoCollection_Seg"),
698 IProductWRTDerivBase_NoCollection::create,
699 "IProductWRTDerivBase_NoCollection_Tri"),
702 IProductWRTDerivBase_NoCollection::create,
703 "IProductWRTDerivBase_NoCollection_NodalTri"),
706 false),
707 IProductWRTDerivBase_NoCollection::create,
708 "IProductWRTDerivBase_NoCollection_Quad"),
711 IProductWRTDerivBase_NoCollection::create,
712 "IProductWRTDerivBase_NoCollection_Tet"),
715 IProductWRTDerivBase_NoCollection::create,
716 "IProductWRTDerivBase_NoCollection_NodalTet"),
719 IProductWRTDerivBase_NoCollection::create,
720 "IProductWRTDerivBase_NoCollection_Pyr"),
723 IProductWRTDerivBase_NoCollection::create,
724 "IProductWRTDerivBase_NoCollection_Prism"),
727 IProductWRTDerivBase_NoCollection::create,
728 "IProductWRTDerivBase_NoCollection_NodalPrism"),
731 IProductWRTDerivBase_NoCollection::create,
732 "IProductWRTDerivBase_NoCollection_Hex")};
733
734/**
735 * @brief Inner product WRT deriv base operator using sum-factorisation
736 * (Segment)
737 */
738class IProductWRTDerivBase_SumFac_Seg final : virtual public Operator,
740{
741public:
743
745
746 void operator()(const Array<OneD, const NekDouble> &entry0,
747 Array<OneD, NekDouble> &entry1,
748 Array<OneD, NekDouble> &entry2,
749 Array<OneD, NekDouble> &entry3,
750 Array<OneD, NekDouble> &wsp) final
751 {
754
755 output = (m_coordim == 3) ? entry3 : (m_coordim == 2) ? entry2 : entry1;
756
757 in[0] = entry0;
758 in[1] = entry1;
759 in[2] = entry2;
760
761 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
762 if (m_isDeformed)
763 {
764 Vmath::Vmul(m_wspSize, m_derivFac[0], 1, in[0], 1, wsp, 1);
765 for (int i = 1; i < m_coordim; ++i)
766 {
767 Vmath::Vvtvp(m_wspSize, m_derivFac[i], 1, in[i], 1, wsp, 1, wsp,
768 1);
769 }
770 }
771 else
772 {
774 for (int e = 0; e < m_numElmt; ++e)
775 {
776 Vmath::Smul(m_nquad0, m_derivFac[0][e], in[0] + e * m_nquad0, 1,
777 t = wsp + e * m_nquad0, 1);
778 }
779
780 for (int i = 1; i < m_coordim; ++i)
781 {
782 for (int e = 0; e < m_numElmt; ++e)
783 {
785 in[i] + e * m_nquad0, 1, wsp + e * m_nquad0, 1,
786 t = wsp + e * m_nquad0, 1);
787 }
788 }
789 }
790
791 Vmath::Vmul(m_wspSize, m_jacWStdW, 1, wsp, 1, wsp, 1);
792
793 // out = B0*in;
794 Blas::Dgemm('T', 'N', m_nmodes0, m_numElmt, m_nquad0, 1.0,
795 m_derbase0.get(), m_nquad0, &wsp[0], m_nquad0, 0.0,
796 &output[0], m_nmodes0);
797 }
798
799 void operator()([[maybe_unused]] int dir,
800 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
801 [[maybe_unused]] Array<OneD, NekDouble> &output,
802 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
803 {
804 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
805 }
806
807protected:
808 const int m_nquad0;
809 const int m_nmodes0;
814
815private:
817 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
819 : Operator(pCollExp, pGeomData, factors), IProductWRTDerivBase_Helper(),
820 m_nquad0(m_stdExp->GetNumPoints(0)),
821 m_nmodes0(m_stdExp->GetBasisNumModes(0)),
822 m_derbase0(m_stdExp->GetBasis(0)->GetDbdata())
823 {
824 m_coordim = pCollExp[0]->GetCoordim();
826 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
827 m_jacWStdW = pGeomData->GetJacWithStdWeights(pCollExp);
828 }
829};
830
831/// Factory initialisation for the IProductWRTDerivBase_SumFac_Seg operator
832OperatorKey IProductWRTDerivBase_SumFac_Seg::m_type =
835 IProductWRTDerivBase_SumFac_Seg::create,
836 "IProductWRTDerivBase_SumFac_Seg");
837
838/**
839 * @brief Inner product WRT deriv base operator using sum-factorisation (Quad)
840 */
841class IProductWRTDerivBase_SumFac_Quad final : virtual public Operator,
843{
844public:
846
848
849 void operator()(const Array<OneD, const NekDouble> &entry0,
850 Array<OneD, NekDouble> &entry1,
851 Array<OneD, NekDouble> &entry2,
852 Array<OneD, NekDouble> &entry3,
853 Array<OneD, NekDouble> &wsp) final
854 {
855 unsigned int nPhys = m_stdExp->GetTotPoints();
856 unsigned int ntot = m_numElmt * nPhys;
857 unsigned int nmodes = m_stdExp->GetNcoeffs();
858 unsigned int nmax = max(ntot, m_numElmt * nmodes);
860 Array<OneD, NekDouble> output, wsp1;
862
863 in[0] = entry0;
864 in[1] = entry1;
865 in[2] = entry2;
866
867 output = (m_coordim == 2) ? entry2 : entry3;
868
869 tmp[0] = wsp;
870 tmp[1] = wsp + nmax;
871 wsp1 = wsp + 2 * nmax;
872
873 if (m_isDeformed)
874 {
875 // calculate dx/dxi in[0] + dy/dxi in[1]
876 for (int i = 0; i < 2; ++i)
877 {
878 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
879 for (int j = 1; j < m_coordim; ++j)
880 {
881 Vmath::Vvtvp(ntot, m_derivFac[i + 2 * j], 1, in[j], 1,
882 tmp[i], 1, tmp[i], 1);
883 }
884 }
885 }
886 else
887 {
889 for (int e = 0; e < m_numElmt; ++e)
890 {
891 // calculate dx/dxi in[0] + dy/dxi in[1]
892 for (int i = 0; i < 2; ++i)
893 {
894 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
895 t = tmp[i] + e * m_nqe, 1);
896 for (int j = 1; j < m_coordim; ++j)
897 {
898 Vmath::Svtvp(m_nqe, m_derivFac[i + 2 * j][e],
899 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
900 1, t = tmp[i] + e * m_nqe, 1);
901 }
902 }
903 }
904 }
905 // Iproduct wrt derivative of base 1
908 tmp[0], output, wsp1);
909
910 // Iproduct wrt derivative of base 1
913 tmp[1], tmp[0], wsp1);
914
915 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
916 }
917
918 void operator()([[maybe_unused]] int dir,
919 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
920 [[maybe_unused]] Array<OneD, NekDouble> &output,
921 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
922 {
923 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
924 }
925
926protected:
927 const int m_nquad0;
928 const int m_nquad1;
929 const int m_nmodes0;
930 const int m_nmodes1;
931 const bool m_colldir0;
932 const bool m_colldir1;
940
941private:
943 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
945 : Operator(pCollExp, pGeomData, factors), IProductWRTDerivBase_Helper(),
946 m_nquad0(m_stdExp->GetNumPoints(0)),
947 m_nquad1(m_stdExp->GetNumPoints(1)),
948 m_nmodes0(m_stdExp->GetBasisNumModes(0)),
949 m_nmodes1(m_stdExp->GetBasisNumModes(1)),
950 m_colldir0(m_stdExp->GetBasis(0)->Collocation()),
951 m_colldir1(m_stdExp->GetBasis(1)->Collocation()),
952 m_base0(m_stdExp->GetBasis(0)->GetBdata()),
953 m_base1(m_stdExp->GetBasis(1)->GetBdata()),
954 m_derbase0(m_stdExp->GetBasis(0)->GetDbdata()),
955 m_derbase1(m_stdExp->GetBasis(1)->GetDbdata())
956 {
957 m_coordim = pCollExp[0]->GetCoordim();
958 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
959 m_jacWStdW = pGeomData->GetJacWithStdWeights(pCollExp);
960 m_wspSize =
962 }
963};
964
965/// Factory initialisation for the IProductWRTDerivBase_SumFac_Quad operator
966OperatorKey IProductWRTDerivBase_SumFac_Quad::m_type =
969 IProductWRTDerivBase_SumFac_Quad::create,
970 "IProductWRTDerivBase_IterPerExp_Quad");
971
972/**
973 * @brief Inner product WRT deriv base operator using sum-factorisation (Tri)
974 */
975class IProductWRTDerivBase_SumFac_Tri final : virtual public Operator,
977{
978public:
980
982
983 /**
984 * This method calculates:
985 *
986 * \f[ (d\phi/dx,in[0]) + (d\phi/dy,in[1]) \f]
987 *
988 * which can be represented in terms of local cartesian
989 * derivaties as:
990 *
991 * \f[ ((d\phi/d\xi_0\, d\xi_0/dx +
992 * d\phi/d\xi_1\, d\xi_1/dx),in[0]) + \f]
993 *
994 * \f[ ((d\phi/d\xi_0\, d\xi_0/dy +
995 * d\phi/d\xi_1\, d\xi_1/dy),in[1]) + \f]
996 *
997 * where we note that
998 *
999 * \f[ d\phi/d\xi_0 = d\phi/d\eta_0\, d\eta_0/d\xi_0 =
1000 * d\phi/d\eta_0 2/(1-\eta_1) \f]
1001 *
1002 * \f[ d\phi/d\xi_1 = d\phi/d\eta_1\, d\eta_1/d\xi_1 +
1003 * d\phi/d\eta_1\, d\eta_1/d\xi_1 = d\phi/d\eta_0 (1+\eta_0)/(1-\eta_1)
1004 * + d\phi/d\eta_1 \f]
1005 *
1006 * and so the full inner products are
1007 *
1008 * \f[ (d\phi/dx,in[0]) + (dphi/dy,in[1]) =
1009 * (d\phi/d\eta_0, ((2/(1-\eta_1) (d\xi_0/dx in[0] + d\xi_0/dy in[1])
1010 * + (1-\eta_0)/(1-\eta_1) (d\xi_1/dx in[0]+d\xi_1/dy in[1]))
1011 * + (d\phi/d\eta_1, (d\xi_1/dx in[0] + d\xi_1/dy in[1])) \f]
1012 *
1013 */
1014 void operator()(const Array<OneD, const NekDouble> &entry0,
1015 Array<OneD, NekDouble> &entry1,
1016 Array<OneD, NekDouble> &entry2,
1017 Array<OneD, NekDouble> &entry3,
1018 Array<OneD, NekDouble> &wsp) final
1019 {
1020 unsigned int nPhys = m_stdExp->GetTotPoints();
1021 unsigned int ntot = m_numElmt * nPhys;
1022 unsigned int nmodes = m_stdExp->GetNcoeffs();
1023 unsigned int nmax = max(ntot, m_numElmt * nmodes);
1025 Array<OneD, NekDouble> output, wsp1;
1027
1028 in[0] = entry0;
1029 in[1] = entry1;
1030 in[2] = entry2;
1031
1032 output = (m_coordim == 2) ? entry2 : entry3;
1033
1034 tmp[0] = wsp;
1035 tmp[1] = wsp + nmax;
1036 wsp1 = wsp + 2 * nmax;
1037
1038 if (m_isDeformed)
1039 {
1040 for (int i = 0; i < 2; ++i)
1041 {
1042 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
1043 for (int j = 1; j < m_coordim; ++j)
1044 {
1045 Vmath::Vvtvp(ntot, m_derivFac[i + 2 * j], 1, in[j], 1,
1046 tmp[i], 1, tmp[i], 1);
1047 }
1048 }
1049 }
1050 else
1051 {
1053 for (int e = 0; e < m_numElmt; ++e)
1054 {
1055 // calculate dx/dxi in[0] + dy/dxi in[1]
1056 for (int i = 0; i < 2; ++i)
1057 {
1058 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
1059 t = tmp[i] + e * m_nqe, 1);
1060 for (int j = 1; j < m_coordim; ++j)
1061 {
1062 Vmath::Svtvp(m_nqe, m_derivFac[i + 2 * j][e],
1063 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
1064 1, t = tmp[i] + e * m_nqe, 1);
1065 }
1066 }
1067 }
1068 }
1069
1070 // Multiply by factor: 2/(1-z1)
1071 for (int i = 0; i < m_numElmt; ++i)
1072 {
1073 // scale tmp[0] by geometric factor: 2/(1-z1)
1074 Vmath::Vmul(nPhys, &m_fac0[0], 1, tmp[0].get() + i * nPhys, 1,
1075 tmp[0].get() + i * nPhys, 1);
1076
1077 // scale tmp[1] by geometric factor (1+z0)/(1-z1)
1078 Vmath::Vvtvp(nPhys, &m_fac1[0], 1, tmp[1].get() + i * nPhys, 1,
1079 tmp[0].get() + i * nPhys, 1, tmp[0].get() + i * nPhys,
1080 1);
1081 }
1082
1083 // Iproduct wrt derivative of base 0
1085 m_nmodes1, m_derbase0, m_base1, m_jacWStdW, tmp[0], output,
1086 wsp1);
1087
1088 // Iproduct wrt derivative of base 1
1090 m_nmodes1, m_base0, m_derbase1, m_jacWStdW, tmp[1], tmp[0],
1091 wsp1);
1092
1093 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1094 }
1095
1096 void operator()([[maybe_unused]] int dir,
1097 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
1098 [[maybe_unused]] Array<OneD, NekDouble> &output,
1099 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
1100 {
1101 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
1102 }
1103
1104protected:
1105 const int m_nquad0;
1106 const int m_nquad1;
1107 const int m_nmodes0;
1108 const int m_nmodes1;
1109 const bool m_colldir0;
1110 const bool m_colldir1;
1121
1122private:
1124 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
1126 : Operator(pCollExp, pGeomData, factors), IProductWRTDerivBase_Helper(),
1127 m_nquad0(m_stdExp->GetNumPoints(0)),
1128 m_nquad1(m_stdExp->GetNumPoints(1)),
1129 m_nmodes0(m_stdExp->GetBasisNumModes(0)),
1130 m_nmodes1(m_stdExp->GetBasisNumModes(1)),
1131 m_colldir0(m_stdExp->GetBasis(0)->Collocation()),
1132 m_colldir1(m_stdExp->GetBasis(1)->Collocation()),
1133 m_base0(m_stdExp->GetBasis(0)->GetBdata()),
1134 m_base1(m_stdExp->GetBasis(1)->GetBdata()),
1135 m_derbase0(m_stdExp->GetBasis(0)->GetDbdata()),
1136 m_derbase1(m_stdExp->GetBasis(1)->GetDbdata())
1137 {
1138 m_coordim = pCollExp[0]->GetCoordim();
1139 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
1140 m_jacWStdW = pGeomData->GetJacWithStdWeights(pCollExp);
1141 m_wspSize =
1142 4 * m_numElmt * (max(m_nquad0 * m_nquad1, m_nmodes0 * m_nmodes1));
1143
1144 if (m_stdExp->GetBasis(0)->GetBasisType() == LibUtilities::eModified_A)
1145 {
1146 m_sortTopVertex = true;
1147 }
1148 else
1149 {
1150 m_sortTopVertex = false;
1151 }
1152
1153 const Array<OneD, const NekDouble> &z0 = m_stdExp->GetBasis(0)->GetZ();
1154 const Array<OneD, const NekDouble> &z1 = m_stdExp->GetBasis(1)->GetZ();
1155
1157 // set up geometric factor: 2/(1-z1)
1158 for (int i = 0; i < m_nquad0; ++i)
1159 {
1160 for (int j = 0; j < m_nquad1; ++j)
1161 {
1162 m_fac0[i + j * m_nquad0] = 2.0 / (1 - z1[j]);
1163 }
1164 }
1165
1167 // set up geometric factor: (1+z0)/(1-z1)
1168 for (int i = 0; i < m_nquad0; ++i)
1169 {
1170 for (int j = 0; j < m_nquad1; ++j)
1171 {
1172 m_fac1[i + j * m_nquad0] = (1 + z0[i]) / (1 - z1[j]);
1173 }
1174 }
1175 }
1176};
1177
1178/// Factory initialisation for the IProductWRTDerivBase_SumFac_Tri operator
1179OperatorKey IProductWRTDerivBase_SumFac_Tri::m_type =
1182 IProductWRTDerivBase_SumFac_Tri::create,
1183 "IProductWRTDerivBase_IterPerExp_Tri");
1184
1185/**
1186 * @brief Inner product WRT deriv base operator using sum-factorisation (Hex)
1187 */
1188class IProductWRTDerivBase_SumFac_Hex final : virtual public Operator,
1190{
1191public:
1193
1195
1196 void operator()(const Array<OneD, const NekDouble> &entry0,
1197 Array<OneD, NekDouble> &entry1,
1198 Array<OneD, NekDouble> &entry2,
1199 Array<OneD, NekDouble> &entry3,
1200 Array<OneD, NekDouble> &wsp) final
1201 {
1202 unsigned int nPhys = m_stdExp->GetTotPoints();
1203 unsigned int ntot = m_numElmt * nPhys;
1204 unsigned int nmodes = m_stdExp->GetNcoeffs();
1205 unsigned int nmax = max(ntot, m_numElmt * nmodes);
1207 Array<OneD, NekDouble> output, wsp1;
1209
1210 in[0] = entry0;
1211 in[1] = entry1;
1212 in[2] = entry2;
1213
1214 output = entry3;
1215
1216 for (int i = 0; i < 3; ++i)
1217 {
1218 tmp[i] = wsp + i * nmax;
1219 }
1220
1221 if (m_isDeformed)
1222 {
1223 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
1224 for (int i = 0; i < 3; ++i)
1225 {
1226 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
1227 for (int j = 1; j < 3; ++j)
1228 {
1229 Vmath::Vvtvp(ntot, m_derivFac[i + 3 * j], 1, in[j], 1,
1230 tmp[i], 1, tmp[i], 1);
1231 }
1232 }
1233 }
1234 else
1235 {
1237 for (int e = 0; e < m_numElmt; ++e)
1238 {
1239 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
1240 for (int i = 0; i < 3; ++i)
1241 {
1242 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
1243 t = tmp[i] + e * m_nqe, 1);
1244 for (int j = 1; j < 3; ++j)
1245 {
1246 Vmath::Svtvp(m_nqe, m_derivFac[i + 3 * j][e],
1247 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
1248 1, t = tmp[i] + e * m_nqe, 1);
1249 }
1250 }
1251 }
1252 }
1253
1254 wsp1 = wsp + 3 * nmax;
1255
1256 // calculate Iproduct WRT Std Deriv
1259 m_derbase0, m_base1, m_base2, m_jacWStdW, tmp[0], output,
1260 wsp1);
1261
1264 m_base0, m_derbase1, m_base2, m_jacWStdW, tmp[1], tmp[0],
1265 wsp1);
1266 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1267
1270 m_base0, m_base1, m_derbase2, m_jacWStdW, tmp[2], tmp[0],
1271 wsp1);
1272 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1273 }
1274
1275 void operator()([[maybe_unused]] int dir,
1276 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
1277 [[maybe_unused]] Array<OneD, NekDouble> &output,
1278 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
1279 {
1280 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
1281 }
1282
1283protected:
1284 const int m_nquad0;
1285 const int m_nquad1;
1286 const int m_nquad2;
1287 const int m_nmodes0;
1288 const int m_nmodes1;
1289 const int m_nmodes2;
1290 const bool m_colldir0;
1291 const bool m_colldir1;
1292 const bool m_colldir2;
1301
1302private:
1304 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
1306 : Operator(pCollExp, pGeomData, factors), IProductWRTDerivBase_Helper(),
1307 m_nquad0(m_stdExp->GetNumPoints(0)),
1308 m_nquad1(m_stdExp->GetNumPoints(1)),
1309 m_nquad2(m_stdExp->GetNumPoints(2)),
1310 m_nmodes0(m_stdExp->GetBasisNumModes(0)),
1311 m_nmodes1(m_stdExp->GetBasisNumModes(1)),
1312 m_nmodes2(m_stdExp->GetBasisNumModes(2)),
1313 m_colldir0(m_stdExp->GetBasis(0)->Collocation()),
1314 m_colldir1(m_stdExp->GetBasis(1)->Collocation()),
1315 m_colldir2(m_stdExp->GetBasis(2)->Collocation()),
1316 m_base0(m_stdExp->GetBasis(0)->GetBdata()),
1317 m_base1(m_stdExp->GetBasis(1)->GetBdata()),
1318 m_base2(m_stdExp->GetBasis(2)->GetBdata()),
1319 m_derbase0(m_stdExp->GetBasis(0)->GetDbdata()),
1320 m_derbase1(m_stdExp->GetBasis(1)->GetDbdata()),
1321 m_derbase2(m_stdExp->GetBasis(2)->GetDbdata())
1322
1323 {
1324 m_jacWStdW = pGeomData->GetJacWithStdWeights(pCollExp);
1325 m_wspSize = 6 * m_numElmt *
1326 (max(m_nquad0 * m_nquad1 * m_nquad2,
1328 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
1329 }
1330};
1331
1332/// Factory initialisation for the IProductWRTDerivBase_SumFac_Hex operator
1333OperatorKey IProductWRTDerivBase_SumFac_Hex::m_type =
1336 IProductWRTDerivBase_SumFac_Hex::create,
1337 "IProductWRTDerivBase_SumFac_Hex");
1338
1339/**
1340 * @brief Inner product WRT deriv base operator using sum-factorisation (Tet)
1341 */
1344{
1345public:
1347
1348 /**
1349 * This method calculates:
1350 *
1351 * \f[ (d\phi/dx,in[0]) + (d\phi/dy,in[1]) + (d\phi/dz,in[2]) \f]
1352 *
1353 * which can be represented in terms of local cartesian
1354 * derivaties as:
1355 *
1356 * \f[ ((d\phi/d\xi_0\, d\xi_0/dx +
1357 * d\phi/d\xi_1\, d\xi_1/dx +
1358 * d\phi/d\xi_2\, d\xi_2/dx),in[0]) + \f]
1359 *
1360 * \f[ ((d\phi/d\xi_0\, d\xi_0/dy +
1361 * d\phi/d\xi_1\, d\xi_1/dy +
1362 * d\phi/d\xi_2\, d\xi_2/dy),in[1]) + \f]
1363 *
1364 * \f[ ((d\phi/d\xi_0\, d\xi_0/dz +
1365 * d\phi/d\xi_1\, d\xi_1/dz +
1366 * d\phi/d\xi_2\, d\xi_2/dz),in[2]) \, \f]
1367 *
1368 * where we note that
1369 *
1370 * \f[ d\phi/d\xi_0 = d\phi/d\eta_0 4/((1-\eta_1)(1-\eta_2)) \f]
1371 *
1372 * \f[ d\phi/d\xi_1 = d\phi/d\eta_0 2(1+\eta_0)/((1-\eta_1)(1-\eta_2))
1373 * + d\phi/d\eta_1 2/(1-\eta_2) \f]
1374 *
1375 * \f[ d\phi/d\xi_2 = d\phi/d\eta_0 2(1+\eta_0)/((1-\eta_1)(1-\eta_2))
1376 * + d\phi/d\eta_1 (1+\eta_1)/(1-\eta_2) + d\phi/d\eta_2 \f]
1377 *
1378 * and so the full inner products are
1379 *
1380 * \f[ (d\phi/dx,in[0]) + (d\phi/dy,in[1]) + (d\phi/dz,in[2]) = \f]
1381 *
1382 * \f[ (d\phi/d\eta_0, fac0 (tmp0 + fac1(tmp1 + tmp2)))
1383 * + (d\phi/d\eta_1, fac2 (tmp1 + fac3 tmp2))
1384 * + (d\phi/d\eta_2, tmp2) \f]
1385 *
1386 * where
1387 *
1388 * \f[ \begin{array}{lcl}
1389 * tmp0 &=& (d\xi_0/dx in[0] + d\xi_0/dy in[1] + d\xi_0/dz in[2]) \\
1390 * tmp1 &=& (d\xi_1/dx in[0] + d\xi_1/dy in[1] + d\xi_1/dz in[2]) \\
1391 * tmp2 &=& (d\xi_2/dx in[0] + d\xi_2/dy in[1] + d\xi_2/dz in[2])
1392 * \end{array} \f]
1393 *
1394 * \f[ \begin{array}{lcl}
1395 * fac0 &= & 4/((1-\eta_1)(1-\eta_2)) \\
1396 * fac1 &= & (1+\eta_0)/2 \\
1397 * fac2 &= & 2/(1-\eta_2) \\
1398 * fac3 &= & (1+\eta_1)/2 \end{array} \f]
1399 *
1400 */
1401 void operator()(const Array<OneD, const NekDouble> &entry0,
1402 Array<OneD, NekDouble> &entry1,
1403 Array<OneD, NekDouble> &entry2,
1404 Array<OneD, NekDouble> &entry3,
1405 Array<OneD, NekDouble> &wsp) final
1406 {
1407 unsigned int nPhys = m_stdExp->GetTotPoints();
1408 unsigned int ntot = m_numElmt * nPhys;
1409 unsigned int nmodes = m_stdExp->GetNcoeffs();
1410 unsigned int nmax = max(ntot, m_numElmt * nmodes);
1412 Array<OneD, NekDouble> output, wsp1;
1414
1415 in[0] = entry0;
1416 in[1] = entry1;
1417 in[2] = entry2;
1418
1419 output = entry3;
1420
1421 for (int i = 0; i < 3; ++i)
1422 {
1423 tmp[i] = wsp + i * nmax;
1424 }
1425
1426 if (m_isDeformed)
1427 {
1428 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
1429 for (int i = 0; i < 3; ++i)
1430 {
1431 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
1432 for (int j = 1; j < 3; ++j)
1433 {
1434 Vmath::Vvtvp(ntot, m_derivFac[i + 3 * j], 1, in[j], 1,
1435 tmp[i], 1, tmp[i], 1);
1436 }
1437 }
1438 }
1439 else
1440 {
1442 for (int e = 0; e < m_numElmt; ++e)
1443 {
1444 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
1445 for (int i = 0; i < 3; ++i)
1446 {
1447 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
1448 t = tmp[i] + e * m_nqe, 1);
1449 for (int j = 1; j < 3; ++j)
1450 {
1451 Vmath::Svtvp(m_nqe, m_derivFac[i + 3 * j][e],
1452 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
1453 1, t = tmp[i] + e * m_nqe, 1);
1454 }
1455 }
1456 }
1457 }
1458
1459 wsp1 = wsp + 3 * nmax;
1460
1461 // Sort into eta factors
1462 for (int i = 0; i < m_numElmt; ++i)
1463 {
1464 // add tmp[1] + tmp[2]
1465 Vmath::Vadd(nPhys, tmp[1].get() + i * nPhys, 1,
1466 tmp[2].get() + i * nPhys, 1, wsp1.get(), 1);
1467
1468 // scale wsp1 by fac1 and add to tmp0
1469 Vmath::Vvtvp(nPhys, &m_fac1[0], 1, wsp1.get(), 1,
1470 tmp[0].get() + i * nPhys, 1, tmp[0].get() + i * nPhys,
1471 1);
1472
1473 // scale tmp[0] by fac0
1474 Vmath::Vmul(nPhys, &m_fac0[0], 1, tmp[0].get() + i * nPhys, 1,
1475 tmp[0].get() + i * nPhys, 1);
1476
1477 // scale tmp[2] by fac3 and add to tmp1
1478 Vmath::Vvtvp(nPhys, &m_fac3[0], 1, tmp[2].get() + i * nPhys, 1,
1479 tmp[1].get() + i * nPhys, 1, tmp[1].get() + i * nPhys,
1480 1);
1481
1482 // scale tmp[1] by fac2
1483 Vmath::Vmul(nPhys, &m_fac2[0], 1, tmp[1].get() + i * nPhys, 1,
1484 tmp[1].get() + i * nPhys, 1);
1485 }
1486
1487 // calculate Iproduct WRT Std Deriv
1490 m_base2, m_jacWStdW, tmp[0], output, wsp1);
1491
1494 m_base2, m_jacWStdW, tmp[1], tmp[0], wsp1);
1495 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1496
1499 m_derbase2, m_jacWStdW, tmp[2], tmp[0], wsp1);
1500 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1501 }
1502
1503 void operator()([[maybe_unused]] int dir,
1504 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
1505 [[maybe_unused]] Array<OneD, NekDouble> &output,
1506 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
1507 {
1508 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
1509 }
1510
1511protected:
1512 const int m_nquad0;
1513 const int m_nquad1;
1514 const int m_nquad2;
1515 const int m_nmodes0;
1516 const int m_nmodes1;
1517 const int m_nmodes2;
1531
1532private:
1534 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
1536 : Operator(pCollExp, pGeomData, factors), IProductWRTDerivBase_Helper(),
1537 m_nquad0(m_stdExp->GetNumPoints(0)),
1538 m_nquad1(m_stdExp->GetNumPoints(1)),
1539 m_nquad2(m_stdExp->GetNumPoints(2)),
1540 m_nmodes0(m_stdExp->GetBasisNumModes(0)),
1541 m_nmodes1(m_stdExp->GetBasisNumModes(1)),
1542 m_nmodes2(m_stdExp->GetBasisNumModes(2)),
1543 m_base0(m_stdExp->GetBasis(0)->GetBdata()),
1544 m_base1(m_stdExp->GetBasis(1)->GetBdata()),
1545 m_base2(m_stdExp->GetBasis(2)->GetBdata()),
1546 m_derbase0(m_stdExp->GetBasis(0)->GetDbdata()),
1547 m_derbase1(m_stdExp->GetBasis(1)->GetDbdata()),
1548 m_derbase2(m_stdExp->GetBasis(2)->GetDbdata())
1549
1550 {
1551 m_jacWStdW = pGeomData->GetJacWithStdWeights(pCollExp);
1552 m_wspSize = 6 * m_numElmt *
1553 (max(m_nquad0 * m_nquad1 * m_nquad2,
1555 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
1556
1557 const Array<OneD, const NekDouble> &z0 = m_stdExp->GetBasis(0)->GetZ();
1558 const Array<OneD, const NekDouble> &z1 = m_stdExp->GetBasis(1)->GetZ();
1559 const Array<OneD, const NekDouble> &z2 = m_stdExp->GetBasis(2)->GetZ();
1560
1565 // calculate 2.0/((1-eta_1)(1-eta_2))
1566 for (int i = 0; i < m_nquad0; ++i)
1567 {
1568 for (int j = 0; j < m_nquad1; ++j)
1569 {
1570 for (int k = 0; k < m_nquad2; ++k)
1571 {
1572 m_fac0[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
1573 4.0 / ((1 - z1[j]) * (1 - z2[k]));
1574 m_fac1[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
1575 (1 + z0[i]) * 0.5;
1576 m_fac2[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
1577 2.0 / (1 - z2[k]);
1578 m_fac3[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
1579 (1 + z1[j]) * 0.5;
1580 }
1581 }
1582 }
1583
1584 if (m_stdExp->GetBasis(0)->GetBasisType() == LibUtilities::eModified_A)
1585 {
1586 m_sortTopEdge = true;
1587 }
1588 else
1589 {
1590 m_sortTopEdge = false;
1591 }
1592 }
1593};
1594
1595/// Factory initialisation for the IProductWRTDerivBase_SumFac_Tet operator
1596OperatorKey IProductWRTDerivBase_SumFac_Tet::m_type =
1599 IProductWRTDerivBase_SumFac_Tet::create,
1600 "IProductWRTDerivBase_SumFac_Tet");
1601
1602/**
1603 * @brief Inner product WRT deriv base operator using sum-factorisation (Prism)
1604 */
1605class IProductWRTDerivBase_SumFac_Prism final : virtual public Operator,
1607{
1608public:
1610
1612
1613 /**
1614 * This method calculates:
1615 *
1616 * \f[ (d\phi/dx,in[0]) + (d\phi/dy,in[1]) + (d\phi/dz,in[2]) \f]
1617 *
1618 * which can be represented in terms of local cartesian
1619 * derivaties as:
1620 *
1621 * \f[ ((d\phi/d\xi_0\, d\xi_0/dx +
1622 * d\phi/d\xi_1\, d\xi_1/dx +
1623 * d\phi/d\xi_2\, d\xi_2/dx),in[0]) + \f]
1624 *
1625 * \f[ ((d\phi/d\xi_0\, d\xi_0/dy +
1626 * d\phi/d\xi_1\, d\xi_1/dy +
1627 * d\phi/d\xi_2\, d\xi_2/dy),in[1]) + \f]
1628 *
1629 * \f[ ((d\phi/d\xi_0\, d\xi_0/dz +
1630 * d\phi/d\xi_1\, d\xi_1/dz +
1631 * d\phi/d\xi_2\, d\xi_2/dz),in[2]) \, \f]
1632 *
1633 * where we note that
1634 *
1635 * \f[ d\phi/d\xi_0 =
1636 * d\phi/d\eta_0 d\eta_0/d\xi_0 = d\phi/d\eta_0 2/(1-\eta_2) \f]
1637 *
1638 * \f[ d\phi/d\xi_2 =
1639 * d\phi/d\eta_0 d\eta_0/d\xi_2 + d\phi/d\eta_2 d\eta_2/d\xi_2 =
1640 * d\phi/d\eta_0 (1+\eta_0)/(1-\eta_2) + d\phi/d\eta_2 \f]
1641 *
1642 *
1643 * and so the full inner products are
1644 *
1645 * \f[ (d\phi/dx,in[0]) + (d\phi/dy,in[1]) + (d\phi/dz,in[2]) = \f]
1646 *
1647 * \f[ (d\phi/d\eta_0, ((2/(1-\eta_2) (d\xi_0/dx in[0] + d\xi_0/dy in[1]
1648 * + d\xi_0/dz in[2])
1649 * + (1-\eta_0)/(1-\eta_2) (d\xi_2/dx in[0] + d\xi_2/dy in[1]
1650 * + d\xi_2/dz in[2] )) + \f]
1651 *
1652 * \f[ (d\phi/d\eta_1, (d\xi_1/dx in[0] + d\xi_1/dy in[1]
1653 * + d\xi_1/dz in[2])) + \f]
1654 *
1655 * \f[ (d\phi/d\eta_2, (d\xi_2/dx in[0] + d\xi_2/dy in[1]
1656 * + d\xi_2/dz in[2])) \f]
1657 *
1658 */
1659 void operator()(const Array<OneD, const NekDouble> &entry0,
1660 Array<OneD, NekDouble> &entry1,
1661 Array<OneD, NekDouble> &entry2,
1662 Array<OneD, NekDouble> &entry3,
1663 Array<OneD, NekDouble> &wsp) final
1664 {
1665 unsigned int nPhys = m_stdExp->GetTotPoints();
1666 unsigned int ntot = m_numElmt * nPhys;
1667 unsigned int nmodes = m_stdExp->GetNcoeffs();
1668 unsigned int nmax = max(ntot, m_numElmt * nmodes);
1670 Array<OneD, NekDouble> output, wsp1;
1672
1673 in[0] = entry0;
1674 in[1] = entry1;
1675 in[2] = entry2;
1676
1677 output = entry3;
1678
1679 for (int i = 0; i < 3; ++i)
1680 {
1681 tmp[i] = wsp + i * nmax;
1682 }
1683
1684 if (m_isDeformed)
1685 {
1686 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
1687 for (int i = 0; i < 3; ++i)
1688 {
1689 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
1690 for (int j = 1; j < 3; ++j)
1691 {
1692 Vmath::Vvtvp(ntot, m_derivFac[i + 3 * j], 1, in[j], 1,
1693 tmp[i], 1, tmp[i], 1);
1694 }
1695 }
1696 }
1697 else
1698 {
1700 for (int e = 0; e < m_numElmt; ++e)
1701 {
1702 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
1703 for (int i = 0; i < 3; ++i)
1704 {
1705 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
1706 t = tmp[i] + e * m_nqe, 1);
1707 for (int j = 1; j < 3; ++j)
1708 {
1709 Vmath::Svtvp(m_nqe, m_derivFac[i + 3 * j][e],
1710 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
1711 1, t = tmp[i] + e * m_nqe, 1);
1712 }
1713 }
1714 }
1715 }
1716
1717 wsp1 = wsp + 3 * nmax;
1718
1719 // Sort into eta factors
1720 for (int i = 0; i < m_numElmt; ++i)
1721 {
1722 // scale tmp[0] by fac0
1723 Vmath::Vmul(nPhys, &m_fac0[0], 1, tmp[0].get() + i * nPhys, 1,
1724 tmp[0].get() + i * nPhys, 1);
1725
1726 // scale tmp[2] by fac1 and add to tmp0
1727 Vmath::Vvtvp(nPhys, &m_fac1[0], 1, tmp[2].get() + i * nPhys, 1,
1728 tmp[0].get() + i * nPhys, 1, tmp[0].get() + i * nPhys,
1729 1);
1730 }
1731
1732 // calculate Iproduct WRT Std Deriv
1735 m_base2, m_jacWStdW, tmp[0], output, wsp1);
1736
1739 m_base2, m_jacWStdW, tmp[1], tmp[0], wsp1);
1740 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1741
1744 m_derbase2, m_jacWStdW, tmp[2], tmp[0], wsp1);
1745 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1746 }
1747
1748 void operator()([[maybe_unused]] int dir,
1749 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
1750 [[maybe_unused]] Array<OneD, NekDouble> &output,
1751 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
1752 {
1753 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
1754 }
1755
1756protected:
1757 const int m_nquad0;
1758 const int m_nquad1;
1759 const int m_nquad2;
1760 const int m_nmodes0;
1761 const int m_nmodes1;
1762 const int m_nmodes2;
1774
1775private:
1777 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
1779 : Operator(pCollExp, pGeomData, factors), IProductWRTDerivBase_Helper(),
1780 m_nquad0(m_stdExp->GetNumPoints(0)),
1781 m_nquad1(m_stdExp->GetNumPoints(1)),
1782 m_nquad2(m_stdExp->GetNumPoints(2)),
1783 m_nmodes0(m_stdExp->GetBasisNumModes(0)),
1784 m_nmodes1(m_stdExp->GetBasisNumModes(1)),
1785 m_nmodes2(m_stdExp->GetBasisNumModes(2)),
1786 m_base0(m_stdExp->GetBasis(0)->GetBdata()),
1787 m_base1(m_stdExp->GetBasis(1)->GetBdata()),
1788 m_base2(m_stdExp->GetBasis(2)->GetBdata()),
1789 m_derbase0(m_stdExp->GetBasis(0)->GetDbdata()),
1790 m_derbase1(m_stdExp->GetBasis(1)->GetDbdata()),
1791 m_derbase2(m_stdExp->GetBasis(2)->GetDbdata())
1792
1793 {
1794 m_jacWStdW = pGeomData->GetJacWithStdWeights(pCollExp);
1795 m_wspSize = 6 * m_numElmt *
1796 (max(m_nquad0 * m_nquad1 * m_nquad2,
1798 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
1799
1800 if (m_stdExp->GetBasis(0)->GetBasisType() == LibUtilities::eModified_A)
1801 {
1802 m_sortTopVertex = true;
1803 }
1804 else
1805 {
1806 m_sortTopVertex = false;
1807 }
1808
1809 const Array<OneD, const NekDouble> &z0 = m_stdExp->GetBasis(0)->GetZ();
1810 const Array<OneD, const NekDouble> &z2 = m_stdExp->GetBasis(2)->GetZ();
1811
1814
1815 for (int i = 0; i < m_nquad0; ++i)
1816 {
1817 for (int j = 0; j < m_nquad1; ++j)
1818 {
1819 for (int k = 0; k < m_nquad2; ++k)
1820 {
1821 // set up geometric factor: 2/(1-z1)
1822 m_fac0[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
1823 2.0 / (1 - z2[k]);
1824 // set up geometric factor: (1+z0)/(1-z1)
1825 m_fac1[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
1826 (1 + z0[i]) / (1 - z2[k]);
1827 }
1828 }
1829 }
1830 }
1831};
1832
1833/// Factory initialisation for the IProductWRTDerivBase_SumFac_Prism operator
1834OperatorKey IProductWRTDerivBase_SumFac_Prism::m_type =
1837 IProductWRTDerivBase_SumFac_Prism::create,
1838 "IProductWRTDerivBase_SumFac_Prism");
1839
1840/**
1841 * @brief Inner product WRT deriv base operator using sum-factorisation (Pyr)
1842 */
1843class IProductWRTDerivBase_SumFac_Pyr final : virtual public Operator,
1845{
1846public:
1848
1850
1851 /**
1852 * This method calculates:
1853 *
1854 * \f[ (d\phi/dx,in[0]) + (d\phi/dy,in[1]) + (d\phi/dz,in[2]) \f]
1855 *
1856 * which can be represented in terms of local cartesian
1857 * derivaties as:
1858 *
1859 * \f[ ((d\phi/d\xi_0\, d\xi_0/dx +
1860 * d\phi/d\xi_1\, d\xi_1/dx +
1861 * d\phi/d\xi_2\, d\xi_2/dx),in[0]) + \f]
1862 *
1863 * \f[ ((d\phi/d\xi_0\, d\xi_0/dy +
1864 * d\phi/d\xi_1\, d\xi_1/dy +
1865 * d\phi/d\xi_2\, d\xi_2/dy),in[1]) + \f]
1866 *
1867 * \f[ ((d\phi/d\xi_0\, d\xi_0/dz +
1868 * d\phi/d\xi_1\, d\xi_1/dz +
1869 * d\phi/d\xi_2\, d\xi_2/dz),in[2]) \, \f]
1870 *
1871 * where we note that
1872 *
1873 * \f[ d\phi/d\xi_0 =
1874 * d\phi/d\eta_0\, d\eta_0/d\xi_0 =
1875 * d\phi/d\eta_0\, 2/(1-\eta_2). \f]
1876 *
1877 * \f[ d\phi/d\xi_1 =
1878 * d\phi/d\eta_1\, d\eta_1/d\xi_1 =
1879 * d\phi/d\eta_1\, 2/(1-\eta_2) \f]
1880 *
1881 * \f[ d\phi/d\xi_2 =
1882 * d\phi/d\eta_0\, d\eta_0/d\xi_2 +
1883 * d\phi/d\eta_1\, d\eta_1/d\xi_2 +
1884 * d\phi/d\eta_2\, d\eta_2/d\xi_2 =
1885 * d\phi/d\eta_0 (1+\eta_0)/(1-\eta_2) +
1886 * d\phi/d\eta_1 (1+\eta_1)/(1-\eta_2) + d\phi/d\eta_2 \f]
1887 *
1888 * and so the full inner products are
1889 *
1890 * \f[ (d\phi/dx,in[0]) + (d\phi/dy,in[1]) + (d\phi/dz,in[2]) = \f]
1891 *
1892 * \f[ (d\phi/d\eta_0, ((2/(1-\eta_2) (d\xi_0/dx in[0] +
1893 * d\xi_0/dy in[1] +
1894 * (1-\eta_0)/(1-\eta_2) (d\xi_2/dx in[0] + d\xi_2/dy in[1]
1895 * + d\xi_2/dz in[2] )) + \f]
1896 * \f[ (d\phi/d\eta_1, ((2/(1-\eta_2) (d\xi_1/dx in[0] +
1897 * d\xi_0/dy in[1] + d\xi_0/dz in[2]) +
1898 * (1-\eta_1)/(1-\eta_2) (d\xi_2/dx in[0] + d\xi_2/dy in[1] +
1899 * d\xi_2/dz in[2] )) \f]
1900 *
1901 * \f[ (d\phi/d\eta_2, (d\xi_2/dx in[0] + d\xi_2/dy in[1] +
1902 * d\xi_2/dz in[2])) \f]
1903 */
1904 void operator()(const Array<OneD, const NekDouble> &entry0,
1905 Array<OneD, NekDouble> &entry1,
1906 Array<OneD, NekDouble> &entry2,
1907 Array<OneD, NekDouble> &entry3,
1908 Array<OneD, NekDouble> &wsp) final
1909 {
1910 unsigned int nPhys = m_stdExp->GetTotPoints();
1911 unsigned int ntot = m_numElmt * nPhys;
1912 unsigned int nmodes = m_stdExp->GetNcoeffs();
1913 unsigned int nmax = max(ntot, m_numElmt * nmodes);
1915 Array<OneD, NekDouble> output, wsp1;
1917
1918 in[0] = entry0;
1919 in[1] = entry1;
1920 in[2] = entry2;
1921
1922 output = entry3;
1923
1924 for (int i = 0; i < 3; ++i)
1925 {
1926 tmp[i] = wsp + i * nmax;
1927 }
1928
1929 if (m_isDeformed)
1930 {
1931 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
1932 for (int i = 0; i < 3; ++i)
1933 {
1934 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
1935 for (int j = 1; j < 3; ++j)
1936 {
1937 Vmath::Vvtvp(ntot, m_derivFac[i + 3 * j], 1, in[j], 1,
1938 tmp[i], 1, tmp[i], 1);
1939 }
1940 }
1941 }
1942 else
1943 {
1945 for (int e = 0; e < m_numElmt; ++e)
1946 {
1947 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
1948 for (int i = 0; i < 3; ++i)
1949 {
1950 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
1951 t = tmp[i] + e * m_nqe, 1);
1952 for (int j = 1; j < 3; ++j)
1953 {
1954 Vmath::Svtvp(m_nqe, m_derivFac[i + 3 * j][e],
1955 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
1956 1, t = tmp[i] + e * m_nqe, 1);
1957 }
1958 }
1959 }
1960 }
1961
1962 wsp1 = wsp + 3 * nmax;
1963
1964 // Sort into eta factors
1965 for (int i = 0; i < m_numElmt; ++i)
1966 {
1967 // scale tmp[0] by fac0
1968 Vmath::Vmul(nPhys, &m_fac0[0], 1, tmp[0].get() + i * nPhys, 1,
1969 tmp[0].get() + i * nPhys, 1);
1970
1971 // scale tmp[2] by fac1 and add to tmp0
1972 Vmath::Vvtvp(nPhys, &m_fac1[0], 1, tmp[2].get() + i * nPhys, 1,
1973 tmp[0].get() + i * nPhys, 1, tmp[0].get() + i * nPhys,
1974 1);
1975
1976 // scale tmp[1] by fac0
1977 Vmath::Vmul(nPhys, &m_fac0[0], 1, tmp[1].get() + i * nPhys, 1,
1978 tmp[1].get() + i * nPhys, 1);
1979
1980 // scale tmp[2] by fac2 and add to tmp1
1981 Vmath::Vvtvp(nPhys, &m_fac2[0], 1, tmp[2].get() + i * nPhys, 1,
1982 tmp[1].get() + i * nPhys, 1, tmp[1].get() + i * nPhys,
1983 1);
1984 }
1985
1986 // calculate Iproduct WRT Std Deriv
1989 m_base2, m_jacWStdW, tmp[0], output, wsp1);
1990
1993 m_base2, m_jacWStdW, tmp[1], tmp[0], wsp1);
1994 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1995
1998 m_derbase2, m_jacWStdW, tmp[2], tmp[0], wsp1);
1999 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
2000 }
2001
2002 void operator()([[maybe_unused]] int dir,
2003 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
2004 [[maybe_unused]] Array<OneD, NekDouble> &output,
2005 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
2006 {
2007 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
2008 }
2009
2010protected:
2011 const int m_nquad0;
2012 const int m_nquad1;
2013 const int m_nquad2;
2014 const int m_nmodes0;
2015 const int m_nmodes1;
2016 const int m_nmodes2;
2029
2030private:
2032 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
2034 : Operator(pCollExp, pGeomData, factors), IProductWRTDerivBase_Helper(),
2035 m_nquad0(m_stdExp->GetNumPoints(0)),
2036 m_nquad1(m_stdExp->GetNumPoints(1)),
2037 m_nquad2(m_stdExp->GetNumPoints(2)),
2038 m_nmodes0(m_stdExp->GetBasisNumModes(0)),
2039 m_nmodes1(m_stdExp->GetBasisNumModes(1)),
2040 m_nmodes2(m_stdExp->GetBasisNumModes(2)),
2041 m_base0(m_stdExp->GetBasis(0)->GetBdata()),
2042 m_base1(m_stdExp->GetBasis(1)->GetBdata()),
2043 m_base2(m_stdExp->GetBasis(2)->GetBdata()),
2044 m_derbase0(m_stdExp->GetBasis(0)->GetDbdata()),
2045 m_derbase1(m_stdExp->GetBasis(1)->GetDbdata()),
2046 m_derbase2(m_stdExp->GetBasis(2)->GetDbdata())
2047
2048 {
2049 m_jacWStdW = pGeomData->GetJacWithStdWeights(pCollExp);
2050 m_wspSize = 6 * m_numElmt *
2051 (max(m_nquad0 * m_nquad1 * m_nquad2,
2053 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
2054
2055 if (m_stdExp->GetBasis(0)->GetBasisType() == LibUtilities::eModified_A)
2056 {
2057 m_sortTopVertex = true;
2058 }
2059 else
2060 {
2061 m_sortTopVertex = false;
2062 }
2063
2064 const Array<OneD, const NekDouble> &z0 = m_stdExp->GetBasis(0)->GetZ();
2065 const Array<OneD, const NekDouble> &z1 = m_stdExp->GetBasis(1)->GetZ();
2066 const Array<OneD, const NekDouble> &z2 = m_stdExp->GetBasis(2)->GetZ();
2067
2071
2072 for (int i = 0; i < m_nquad0; ++i)
2073 {
2074 for (int j = 0; j < m_nquad1; ++j)
2075 {
2076 for (int k = 0; k < m_nquad2; ++k)
2077 {
2078 // set up geometric factor: 2/(1-z2)
2079 m_fac0[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
2080 2.0 / (1 - z2[k]);
2081 // set up geometric factor: (1+z0)/(1-z2)
2082 m_fac1[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
2083 (1 + z0[i]) / (1 - z2[k]);
2084 // set up geometric factor: (1+z1)/(1-z2)
2085 m_fac2[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
2086 (1 + z1[j]) / (1 - z2[k]);
2087 }
2088 }
2089 }
2090 }
2091};
2092
2093/// Factory initialisation for the IProductWRTDerivBase_SumFac_Pyr operator
2094OperatorKey IProductWRTDerivBase_SumFac_Pyr::m_type =
2097 IProductWRTDerivBase_SumFac_Pyr::create,
2098 "IProductWRTDerivBase_SumFac_Pyr");
2099
2100} // namespace Nektar::Collections
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:208
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:202
#define OPERATOR_CREATE(cname)
Definition: Operator.h:43
Inner product deriv base help class to calculate the size of the collection that is given as an input...
Inner product WRT deriv base operator using element-wise operation.
IProductWRTDerivBase_IterPerExp(vector< StdRegions::StdExpansionSharedPtr > pCollExp, CoalescedGeomDataSharedPtr pGeomData, StdRegions::FactorMap factors)
void operator()(int dir, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp) final
Inner product operator using operator using matrix free operators.
IProductWRTDerivBase_MatrixFree(vector< StdRegions::StdExpansionSharedPtr > pCollExp, CoalescedGeomDataSharedPtr pGeomData, StdRegions::FactorMap factors)
std::shared_ptr< MatrixFree::IProductWRTDerivBase > m_oper
void operator()(int dir, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp) final
Inner product WRT deriv base operator using LocalRegions implementation.
vector< StdRegions::StdExpansionSharedPtr > m_expList
void operator()(int dir, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp) final
IProductWRTDerivBase_NoCollection(vector< StdRegions::StdExpansionSharedPtr > pCollExp, CoalescedGeomDataSharedPtr pGeomData, StdRegions::FactorMap factors)
Inner product WRT deriv base operator using standard matrix approach.
void operator()(int dir, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp) final
IProductWRTDerivBase_StdMat(vector< StdRegions::StdExpansionSharedPtr > pCollExp, CoalescedGeomDataSharedPtr pGeomData, StdRegions::FactorMap factors)
Inner product WRT deriv base operator using sum-factorisation (Hex)
void operator()(int dir, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp) final
IProductWRTDerivBase_SumFac_Hex(vector< StdRegions::StdExpansionSharedPtr > pCollExp, CoalescedGeomDataSharedPtr pGeomData, StdRegions::FactorMap factors)
Inner product WRT deriv base operator using sum-factorisation (Prism)
IProductWRTDerivBase_SumFac_Prism(vector< StdRegions::StdExpansionSharedPtr > pCollExp, CoalescedGeomDataSharedPtr pGeomData, StdRegions::FactorMap factors)
void operator()(int dir, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp) final
Inner product WRT deriv base operator using sum-factorisation (Pyr)
void operator()(int dir, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp) final
IProductWRTDerivBase_SumFac_Pyr(vector< StdRegions::StdExpansionSharedPtr > pCollExp, CoalescedGeomDataSharedPtr pGeomData, StdRegions::FactorMap factors)
Inner product WRT deriv base operator using sum-factorisation (Quad)
void operator()(int dir, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp) final
IProductWRTDerivBase_SumFac_Quad(vector< StdRegions::StdExpansionSharedPtr > pCollExp, CoalescedGeomDataSharedPtr pGeomData, StdRegions::FactorMap factors)
Inner product WRT deriv base operator using sum-factorisation (Segment)
void operator()(int dir, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp) final
IProductWRTDerivBase_SumFac_Seg(vector< StdRegions::StdExpansionSharedPtr > pCollExp, CoalescedGeomDataSharedPtr pGeomData, StdRegions::FactorMap factors)
Inner product WRT deriv base operator using sum-factorisation (Tet)
void operator()(int dir, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp) final
IProductWRTDerivBase_SumFac_Tet(vector< StdRegions::StdExpansionSharedPtr > pCollExp, CoalescedGeomDataSharedPtr pGeomData, StdRegions::FactorMap factors)
Inner product WRT deriv base operator using sum-factorisation (Tri)
void operator()(int dir, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp) final
IProductWRTDerivBase_SumFac_Tri(vector< StdRegions::StdExpansionSharedPtr > pCollExp, CoalescedGeomDataSharedPtr pGeomData, StdRegions::FactorMap factors)
unsigned int m_nElmtPad
size after padding
unsigned short m_coordim
coordinates dimension
Array< OneD, Array< OneD, NekDouble > > m_input
padded input/output vectors
Base class for operators on a collection of elements.
Definition: Operator.h:138
StdRegions::StdExpansionSharedPtr m_stdExp
Definition: Operator.h:217
unsigned int m_numElmt
number of elements that the operator is applied on
Definition: Operator.h:219
unsigned int m_outputSize
number of modes or quadrature points that are taken as output from an operator
Definition: Operator.h:227
unsigned int m_inputSize
number of modes or quadrature points that are passed as input to an operator
Definition: Operator.h:224
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
static void Dgemm(const char &transa, const char &transb, const int &m, const int &n, const int &k, const double &alpha, const double *a, const int &lda, const double *b, const int &ldb, const double &beta, double *c, const int &ldc)
BLAS level 3: Matrix-matrix multiply C = A x B where op(A)[m x k], op(B)[k x n], C[m x n] DGEMM perfo...
Definition: Blas.hpp:383
void TetIProduct(bool sortTopEdge, int numElmt, int nquad0, int nquad1, int nquad2, int nmodes0, int nmodes1, int nmodes2, const Array< OneD, const NekDouble > &base0, const Array< OneD, const NekDouble > &base1, const Array< OneD, const NekDouble > &base2, const Array< OneD, const NekDouble > &jac, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp)
Definition: IProduct.cpp:496
void PyrIProduct(bool sortTopVert, int numElmt, int nquad0, int nquad1, int nquad2, int nmodes0, int nmodes1, int nmodes2, const Array< OneD, const NekDouble > &base0, const Array< OneD, const NekDouble > &base1, const Array< OneD, const NekDouble > &base2, const Array< OneD, const NekDouble > &jac, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp)
Definition: IProduct.cpp:405
void TriIProduct(bool sortTopVertex, int numElmt, int nquad0, int nquad1, int nmodes0, int nmodes1, const Array< OneD, const NekDouble > &base0, const Array< OneD, const NekDouble > &base1, const Array< OneD, const NekDouble > &jac, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp)
Definition: IProduct.cpp:128
std::tuple< LibUtilities::ShapeType, OperatorType, ImplementationType, ExpansionIsNodal > OperatorKey
Key for describing an Operator.
Definition: Operator.h:120
void QuadIProduct(bool colldir0, bool colldir1, int numElmt, int nquad0, int nquad1, int nmodes0, int nmodes1, const Array< OneD, const NekDouble > &base0, const Array< OneD, const NekDouble > &base1, const Array< OneD, const NekDouble > &jac, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp)
Definition: IProduct.cpp:46
std::shared_ptr< CoalescedGeomData > CoalescedGeomDataSharedPtr
OperatorFactory & GetOperatorFactory()
Returns the singleton Operator factory object.
Definition: Operator.cpp:44
void PrismIProduct(bool sortTopVert, int numElmt, int nquad0, int nquad1, int nquad2, int nmodes0, int nmodes1, int nmodes2, const Array< OneD, const NekDouble > &base0, const Array< OneD, const NekDouble > &base1, const Array< OneD, const NekDouble > &base2, const Array< OneD, const NekDouble > &jac, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp)
Definition: IProduct.cpp:338
void HexIProduct(bool colldir0, bool colldir1, bool colldir2, int numElmt, int nquad0, int nquad1, int nquad2, int nmodes0, int nmodes1, int nmodes2, const Array< OneD, const NekDouble > &base0, const Array< OneD, const NekDouble > &base1, const Array< OneD, const NekDouble > &base2, const Array< OneD, const NekDouble > &jac, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp)
Definition: IProduct.cpp:170
@ eModified_A
Principle Modified Functions .
Definition: BasisType.h:48
ConstFactorMap FactorMap
Definition: StdRegions.hpp:434
StdRegions::ConstFactorMap factors
double NekDouble
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 Svtvp(int n, const T alpha, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Svtvp (scalar times vector plus vector): z = alpha*x + y.
Definition: Vmath.hpp:396
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 Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.hpp:273
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.hpp:825
STL namespace.