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
35#include <boost/core/ignore_unused.hpp>
36
37#include <MatrixFreeOps/Operator.hpp>
38
43
44using namespace std;
45
46namespace Nektar
47{
48namespace Collections
49{
50
58
59/**
60 * @brief Inner product WRT deriv base operator using standard matrix approach
61 */
63{
64public:
66
68 {
69 }
70
75 Array<OneD, NekDouble> &wsp) override final
76 {
77
78 int nPhys = m_stdExp->GetTotPoints();
79 int ntot = m_numElmt * nPhys;
80 int nmodes = m_stdExp->GetNcoeffs();
84
85 in[0] = entry0;
86 in[1] = entry1;
87 in[2] = entry2;
88
89 output = (m_coordim == 3) ? entry3 : (m_coordim == 2) ? entry2 : entry1;
90
91 for (int i = 0; i < m_dim; ++i)
92 {
93 tmp[i] = wsp + i * ntot;
94 }
95
96 // calculate Iproduct WRT Std Deriv
97
98 // First component
99 if (m_isDeformed)
100 {
101 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
102 for (int i = 0; i < m_dim; ++i)
103 {
104 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
105 for (int j = 1; j < m_coordim; ++j)
106 {
107 Vmath::Vvtvp(ntot, m_derivFac[i + j * m_dim], 1, in[j], 1,
108 tmp[i], 1, tmp[i], 1);
109 }
110 }
111
112 Vmath::Vmul(ntot, m_jac, 1, tmp[0], 1, tmp[0], 1);
113 }
114 else
115 {
117 for (int e = 0; e < m_numElmt; ++e)
118 {
119 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
120 for (int i = 0; i < m_dim; ++i)
121 {
122 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
123 t = tmp[i] + e * m_nqe, 1);
124 for (int j = 1; j < m_coordim; ++j)
125 {
126 Vmath::Svtvp(m_nqe, m_derivFac[i + j * m_dim][e],
127 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
128 1, t = tmp[i] + e * m_nqe, 1);
129 }
130 }
131
132 Vmath::Smul(m_nqe, m_jac[e], tmp[0] + e * m_nqe, 1,
133 t = tmp[0] + e * m_nqe, 1);
134 }
135 }
136
137 Blas::Dgemm('N', 'N', m_iProdWRTStdDBase[0]->GetRows(), m_numElmt,
138 m_iProdWRTStdDBase[0]->GetColumns(), 1.0,
139 m_iProdWRTStdDBase[0]->GetRawPtr(),
140 m_iProdWRTStdDBase[0]->GetRows(), tmp[0].get(), nPhys, 0.0,
141 output.get(), nmodes);
142
143 // Other components
144 for (int i = 1; i < m_dim; ++i)
145 {
146 if (m_isDeformed)
147 {
148 Vmath::Vmul(ntot, m_jac, 1, tmp[i], 1, tmp[i], 1);
149 }
150 else
151 {
153 for (int e = 0; e < m_numElmt; ++e)
154 {
155 Vmath::Smul(m_nqe, m_jac[e], tmp[i] + e * m_nqe, 1,
156 t = tmp[i] + e * m_nqe, 1);
157 }
158 }
159 Blas::Dgemm('N', 'N', m_iProdWRTStdDBase[i]->GetRows(), m_numElmt,
160 m_iProdWRTStdDBase[i]->GetColumns(), 1.0,
161 m_iProdWRTStdDBase[i]->GetRawPtr(),
162 m_iProdWRTStdDBase[i]->GetRows(), tmp[i].get(), nPhys,
163 1.0, output.get(), nmodes);
164 }
165 }
166
167 void operator()(int dir, const Array<OneD, const NekDouble> &input,
169 Array<OneD, NekDouble> &wsp) override final
170 {
171 boost::ignore_unused(dir, input, output, wsp);
172 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
173 }
174
176 int coll_phys_offset) override
177 {
178 boost::ignore_unused(factors, coll_phys_offset);
179 ASSERTL0(false, "Not valid for this operator.");
180 }
181
182protected:
186 int m_dim;
188
189private:
191 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
193 : Operator(pCollExp, pGeomData, factors)
194 {
195 LibUtilities::PointsKeyVector PtsKey = m_stdExp->GetPointsKeys();
196 m_dim = PtsKey.size();
197 m_coordim = pCollExp[0]->GetCoordim();
198
199 m_nqe = m_stdExp->GetTotPoints();
200 int nmodes = m_stdExp->GetNcoeffs();
201
202 // set up a IProductWRTDerivBase StdMat.
204 for (int i = 0; i < m_dim; ++i)
205 {
206 Array<OneD, NekDouble> tmp(m_nqe), tmp1(nmodes);
209 for (int j = 0; j < m_nqe; ++j)
210 {
211 Vmath::Zero(m_nqe, tmp, 1);
212 tmp[j] = 1.0;
213 m_stdExp->IProductWRTDerivBase(i, tmp, tmp1);
214 Vmath::Vcopy(nmodes, &tmp1[0], 1,
215 &(m_iProdWRTStdDBase[i]->GetPtr())[0] + j * nmodes,
216 1);
217 }
218 }
219 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
220 m_jac = pGeomData->GetJac(pCollExp);
222 }
223};
224
225/// Factory initialisation for the IProductWRTDerivBase_StdMat operators
226OperatorKey IProductWRTDerivBase_StdMat::m_typeArr[] = {
229 IProductWRTDerivBase_StdMat::create, "IProductWRTDerivBase_StdMat_Seg"),
232 IProductWRTDerivBase_StdMat::create, "IProductWRTDerivBase_StdMat_Tri"),
235 IProductWRTDerivBase_StdMat::create,
236 "IProductWRTDerivBase_StdMat_NodalTri"),
239 IProductWRTDerivBase_StdMat::create,
240 "IProductWRTDerivBase_StdMat_Quad"),
243 IProductWRTDerivBase_StdMat::create, "IProductWRTDerivBase_StdMat_Tet"),
246 IProductWRTDerivBase_StdMat::create,
247 "IProductWRTDerivBase_StdMat_NodalTet"),
250 IProductWRTDerivBase_StdMat::create, "IProductWRTDerivBase_StdMat_Pyr"),
253 IProductWRTDerivBase_StdMat::create,
254 "IProductWRTDerivBase_StdMat_Prism"),
257 IProductWRTDerivBase_StdMat::create,
258 "IProductWRTDerivBase_StdMat_NodalPrism"),
261 IProductWRTDerivBase_StdMat::create, "IProductWRTDerivBase_StdMat_Hex"),
264 IProductWRTDerivBase_StdMat::create,
265 "IProductWRTDerivBase_SumFac_Pyr")};
266
267/**
268 * @brief Inner product operator using operator using matrix free operators.
269 */
272{
273public:
275
277 {
278 }
279
284 Array<OneD, NekDouble> &wsp) override final
285 {
286 boost::ignore_unused(wsp);
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()(int dir, const Array<OneD, const NekDouble> &input,
353 Array<OneD, NekDouble> &wsp) override final
354 {
355 boost::ignore_unused(dir, input, output, wsp);
356 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
357 }
358
360 int coll_phys_offset) override
361 {
362 boost::ignore_unused(factors, coll_phys_offset);
363 ASSERTL0(false, "Not valid for this operator.");
364 }
365
366private:
367 std::shared_ptr<MatrixFree::IProductWRTDerivBase> m_oper;
368
370 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
372 : Operator(pCollExp, pGeomData, factors),
373 MatrixFreeMultiInOneOut(pCollExp[0]->GetCoordim(),
374 pCollExp[0]->GetStdExp()->GetTotPoints(),
375 pCollExp[0]->GetStdExp()->GetNcoeffs(),
376 pCollExp.size())
377 {
378 // Check if deformed
379 const auto dim = pCollExp[0]->GetStdExp()->GetShapeDimension();
380
381 // Basis vector
382 std::vector<LibUtilities::BasisSharedPtr> basis(dim);
383 for (unsigned int i = 0; i < dim; ++i)
384 {
385 basis[i] = pCollExp[0]->GetBasis(i);
386 }
387
388 // Get shape type
389 auto shapeType = pCollExp[0]->GetStdExp()->DetShapeType();
390
391 // Generate operator string and create operator.
392 std::string op_string = "IProductWRTDerivBase";
393 op_string += MatrixFree::GetOpstring(shapeType, m_isDeformed);
395 op_string, basis, m_nElmtPad);
396
397 // Set Jacobian
398 oper->SetJac(pGeomData->GetJacInterLeave(pCollExp, m_nElmtPad));
399
400 // Set derivative factors
401 oper->SetDF(pGeomData->GetDerivFactorsInterLeave(pCollExp, m_nElmtPad));
402
403 m_oper =
404 std::dynamic_pointer_cast<MatrixFree::IProductWRTDerivBase>(oper);
405 ASSERTL0(m_oper, "Failed to cast pointer.");
406 }
407};
408
409/// Factory initialisation for the IProductWRTDerivBase_MatrixFree operators
410OperatorKey IProductWRTDerivBase_MatrixFree::m_typeArr[] = {
413 IProductWRTDerivBase_MatrixFree::create,
414 "IProductWRTDerivBase_MatrixFree_Seg"),
417 IProductWRTDerivBase_MatrixFree::create,
418 "IProductWRTDerivBase_MatrixFree_Quad"),
421 IProductWRTDerivBase_MatrixFree::create,
422 "IProductWRTDerivBase_MatrixFree_Tri"),
425 IProductWRTDerivBase_MatrixFree::create,
426 "IProductWRTDerivBase_MatrixFree_Hex"),
429 IProductWRTDerivBase_MatrixFree::create,
430 "IProductWRTDerivBase_MatrixFree_Prism"),
433 IProductWRTDerivBase_MatrixFree::create,
434 "IProductWRTDerivBase_MatrixFree_Pyr"),
437 IProductWRTDerivBase_MatrixFree::create,
438 "IProductWRTDerivBase_MatrixFree_Tet")};
439
440/**
441 * @brief Inner product WRT deriv base operator using element-wise operation
442 */
444{
445public:
447
449 {
450 }
451
456 Array<OneD, NekDouble> &wsp) override final
457 {
458
459 unsigned int nPhys = m_stdExp->GetTotPoints();
460 unsigned int ntot = m_numElmt * nPhys;
461 unsigned int nmodes = m_stdExp->GetNcoeffs();
462 unsigned int nmax = max(ntot, m_numElmt * nmodes);
464 Array<OneD, NekDouble> output, tmp1;
466
467 in[0] = entry0;
468 in[1] = entry1;
469 in[2] = entry2;
470
471 output = (m_coordim == 3) ? entry3 : (m_coordim == 2) ? entry2 : entry1;
472
473 for (int i = 0; i < m_dim; ++i)
474 {
475 tmp[i] = wsp + i * nmax;
476 }
477
478 // calculate Iproduct WRT Std Deriv
479 // first component
480 if (m_isDeformed)
481 {
482 // calculate dx/dxi in[0] + dy/dxi in[2] + dz/dxi in[3]
483 for (int i = 0; i < m_dim; ++i)
484 {
485 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
486 for (int j = 1; j < m_coordim; ++j)
487 {
488 Vmath::Vvtvp(ntot, m_derivFac[i + j * m_dim], 1, in[j], 1,
489 tmp[i], 1, tmp[i], 1);
490 }
491 }
492
493 Vmath::Vmul(ntot, m_jac, 1, tmp[0], 1, tmp[0], 1);
494 }
495 else
496 {
498 for (int e = 0; e < m_numElmt; ++e)
499 {
500 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
501 for (int i = 0; i < m_dim; ++i)
502 {
503 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
504 t = tmp[i] + e * m_nqe, 1);
505 for (int j = 1; j < m_coordim; ++j)
506 {
507 Vmath::Svtvp(m_nqe, m_derivFac[i + j * m_dim][e],
508 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
509 1, t = tmp[i] + e * m_nqe, 1);
510 }
511 }
512
513 Vmath::Smul(m_nqe, m_jac[e], tmp[0] + e * m_nqe, 1,
514 t = tmp[0] + e * m_nqe, 1);
515 }
516 }
517
518 for (int n = 0; n < m_numElmt; ++n)
519 {
520 m_stdExp->IProductWRTDerivBase(0, tmp[0] + n * nPhys,
521 tmp1 = output + n * nmodes);
522 }
523
524 // other components
525 for (int i = 1; i < m_dim; ++i)
526 {
527 // multiply by Jacobian
528 if (m_isDeformed)
529 {
530 Vmath::Vmul(ntot, m_jac, 1, tmp[i], 1, tmp[i], 1);
531 }
532 else
533 {
535 for (int e = 0; e < m_numElmt; ++e)
536 {
537 Vmath::Smul(m_nqe, m_jac[e], tmp[i] + e * m_nqe, 1,
538 t = tmp[i] + e * m_nqe, 1);
539 }
540 }
541
542 for (int n = 0; n < m_numElmt; ++n)
543 {
544 m_stdExp->IProductWRTDerivBase(i, tmp[i] + n * nPhys, tmp[0]);
545 Vmath::Vadd(nmodes, tmp[0], 1, output + n * nmodes, 1,
546 tmp1 = output + n * nmodes, 1);
547 }
548 }
549 }
550
551 void operator()(int dir, const Array<OneD, const NekDouble> &input,
553 Array<OneD, NekDouble> &wsp) override final
554 {
555 boost::ignore_unused(dir, input, output, wsp);
556 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
557 }
558
560 int coll_phys_offset) override
561 {
562 boost::ignore_unused(factors, coll_phys_offset);
563 ASSERTL0(false, "Not valid for this operator.");
564 }
565
566protected:
569 int m_dim;
571
572private:
574 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
576 : Operator(pCollExp, pGeomData, factors)
577 {
578 LibUtilities::PointsKeyVector PtsKey = m_stdExp->GetPointsKeys();
579 m_dim = PtsKey.size();
580 m_coordim = pCollExp[0]->GetCoordim();
581
582 m_nqe = m_stdExp->GetTotPoints();
583
584 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
585 m_jac = pGeomData->GetJac(pCollExp);
587 }
588};
589
590/// Factory initialisation for the IProductWRTDerivBase_IterPerExp operators
591OperatorKey IProductWRTDerivBase_IterPerExp::m_typeArr[] = {
594 IProductWRTDerivBase_IterPerExp::create,
595 "IProductWRTDerivBase_IterPerExp_Seg"),
598 IProductWRTDerivBase_IterPerExp::create,
599 "IProductWRTDerivBase_IterPerExp_Tri"),
602 IProductWRTDerivBase_IterPerExp::create,
603 "IProductWRTDerivBase_IterPerExp_NodalTri"),
606 IProductWRTDerivBase_IterPerExp::create,
607 "IProductWRTDerivBase_IterPerExp_Quad"),
610 IProductWRTDerivBase_IterPerExp::create,
611 "IProductWRTDerivBase_IterPerExp_Tet"),
614 IProductWRTDerivBase_IterPerExp::create,
615 "IProductWRTDerivBase_IterPerExp_NodalTet"),
618 IProductWRTDerivBase_IterPerExp::create,
619 "IProductWRTDerivBase_IterPerExp_Pyr"),
622 IProductWRTDerivBase_IterPerExp::create,
623 "IProductWRTDerivBase_IterPerExp_Prism"),
626 IProductWRTDerivBase_IterPerExp::create,
627 "IProductWRTDerivBase_IterPerExp_NodalPrism"),
630 IProductWRTDerivBase_IterPerExp::create,
631 "IProductWRTDerivBase_IterPerExp_Hex")};
632
633/**
634 * @brief Inner product WRT deriv base operator using LocalRegions
635 * implementation.
636 */
638{
639public:
641
643 {
644 }
645
650 Array<OneD, NekDouble> &wsp) override final
651 {
652 boost::ignore_unused(wsp);
653
654 unsigned int nmodes = m_expList[0]->GetNcoeffs();
655 unsigned int nPhys = m_expList[0]->GetTotPoints();
656 Array<OneD, NekDouble> tmp(nmodes), tmp1;
657
660 in[0] = entry0;
661 in[1] = entry1;
662 in[2] = entry2;
663
664 output = (m_coordim == 3) ? entry3 : (m_coordim == 2) ? entry2 : entry1;
665
666 for (int n = 0; n < m_numElmt; ++n)
667 {
668 m_expList[n]->IProductWRTDerivBase(0, in[0] + n * nPhys,
669 tmp1 = output + n * nmodes);
670 }
671
672 for (int i = 1; i < m_dim; ++i)
673 {
674 for (int n = 0; n < m_numElmt; ++n)
675 {
676 m_expList[n]->IProductWRTDerivBase(i, in[i] + n * nPhys, tmp);
677
678 Vmath::Vadd(nmodes, tmp, 1, output + n * nmodes, 1,
679 tmp1 = output + n * nmodes, 1);
680 }
681 }
682 }
683
684 void operator()(int dir, const Array<OneD, const NekDouble> &input,
686 Array<OneD, NekDouble> &wsp) override final
687 {
688 boost::ignore_unused(dir, input, output, wsp);
689 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
690 }
691
693 int coll_phys_offset) override
694 {
695 boost::ignore_unused(factors, coll_phys_offset);
696 ASSERTL0(false, "Not valid for this operator.");
697 }
698
699protected:
700 int m_dim;
702 vector<StdRegions::StdExpansionSharedPtr> m_expList;
703
704private:
706 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
708 : Operator(pCollExp, pGeomData, factors)
709 {
710 m_expList = pCollExp;
711 m_dim = pCollExp[0]->GetNumBases();
712 m_coordim = pCollExp[0]->GetCoordim();
713 }
714};
715
716/// Factory initialisation for the IProductWRTDerivBase_NoCollection operators
717OperatorKey IProductWRTDerivBase_NoCollection::m_typeArr[] = {
720 IProductWRTDerivBase_NoCollection::create,
721 "IProductWRTDerivBase_NoCollection_Seg"),
724 IProductWRTDerivBase_NoCollection::create,
725 "IProductWRTDerivBase_NoCollection_Tri"),
728 IProductWRTDerivBase_NoCollection::create,
729 "IProductWRTDerivBase_NoCollection_NodalTri"),
732 false),
733 IProductWRTDerivBase_NoCollection::create,
734 "IProductWRTDerivBase_NoCollection_Quad"),
737 IProductWRTDerivBase_NoCollection::create,
738 "IProductWRTDerivBase_NoCollection_Tet"),
741 IProductWRTDerivBase_NoCollection::create,
742 "IProductWRTDerivBase_NoCollection_NodalTet"),
745 IProductWRTDerivBase_NoCollection::create,
746 "IProductWRTDerivBase_NoCollection_Pyr"),
749 IProductWRTDerivBase_NoCollection::create,
750 "IProductWRTDerivBase_NoCollection_Prism"),
753 IProductWRTDerivBase_NoCollection::create,
754 "IProductWRTDerivBase_NoCollection_NodalPrism"),
757 IProductWRTDerivBase_NoCollection::create,
758 "IProductWRTDerivBase_NoCollection_Hex")};
759
760/**
761 * @brief Inner product WRT deriv base operator using sum-factorisation
762 * (Segment)
763 */
765{
766public:
768
770 {
771 }
772
777 Array<OneD, NekDouble> &wsp) override final
778 {
781
782 output = (m_coordim == 3) ? entry3 : (m_coordim == 2) ? entry2 : entry1;
783
784 in[0] = entry0;
785 in[1] = entry1;
786 in[2] = entry2;
787
788 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
789 if (m_isDeformed)
790 {
791 Vmath::Vmul(m_wspSize, m_derivFac[0], 1, in[0], 1, wsp, 1);
792 for (int i = 1; i < m_coordim; ++i)
793 {
794 Vmath::Vvtvp(m_wspSize, m_derivFac[i], 1, in[i], 1, wsp, 1, wsp,
795 1);
796 }
797 }
798 else
799 {
801 for (int e = 0; e < m_numElmt; ++e)
802 {
803 Vmath::Smul(m_nquad0, m_derivFac[0][e], in[0] + e * m_nquad0, 1,
804 t = wsp + e * m_nquad0, 1);
805 }
806
807 for (int i = 1; i < m_coordim; ++i)
808 {
809 for (int e = 0; e < m_numElmt; ++e)
810 {
812 in[i] + e * m_nquad0, 1, wsp + e * m_nquad0, 1,
813 t = wsp + e * m_nquad0, 1);
814 }
815 }
816 }
817
818 Vmath::Vmul(m_wspSize, m_jacWStdW, 1, wsp, 1, wsp, 1);
819
820 // out = B0*in;
821 Blas::Dgemm('T', 'N', m_nmodes0, m_numElmt, m_nquad0, 1.0,
822 m_derbase0.get(), m_nquad0, &wsp[0], m_nquad0, 0.0,
823 &output[0], m_nmodes0);
824 }
825
826 void operator()(int dir, const Array<OneD, const NekDouble> &input,
828 Array<OneD, NekDouble> &wsp) override final
829 {
830 boost::ignore_unused(dir, input, output, wsp);
831 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
832 }
833
835 int coll_phys_offset) override
836 {
837 boost::ignore_unused(factors, coll_phys_offset);
838 ASSERTL0(false, "Not valid for this operator.");
839 }
840
841protected:
842 const int m_nquad0;
843 const int m_nmodes0;
848
849private:
851 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
853 : Operator(pCollExp, pGeomData, factors),
854 m_nquad0(m_stdExp->GetNumPoints(0)),
855 m_nmodes0(m_stdExp->GetBasisNumModes(0)),
856 m_derbase0(m_stdExp->GetBasis(0)->GetDbdata())
857 {
858 m_coordim = pCollExp[0]->GetCoordim();
860 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
861 m_jacWStdW = pGeomData->GetJacWithStdWeights(pCollExp);
862 }
863};
864
865/// Factory initialisation for the IProductWRTDerivBase_SumFac_Seg operator
866OperatorKey IProductWRTDerivBase_SumFac_Seg::m_type =
869 IProductWRTDerivBase_SumFac_Seg::create,
870 "IProductWRTDerivBase_SumFac_Seg");
871
872/**
873 * @brief Inner product WRT deriv base operator using sum-factorisation (Quad)
874 */
876{
877public:
879
881 {
882 }
883
888 Array<OneD, NekDouble> &wsp) override final
889 {
890
891 unsigned int nPhys = m_stdExp->GetTotPoints();
892 unsigned int ntot = m_numElmt * nPhys;
893 unsigned int nmodes = m_stdExp->GetNcoeffs();
894 unsigned int nmax = max(ntot, m_numElmt * nmodes);
896 Array<OneD, NekDouble> output, wsp1;
898
899 in[0] = entry0;
900 in[1] = entry1;
901 in[2] = entry2;
902
903 output = (m_coordim == 2) ? entry2 : entry3;
904
905 tmp[0] = wsp;
906 tmp[1] = wsp + nmax;
907 wsp1 = wsp + 2 * nmax;
908
909 if (m_isDeformed)
910 {
911 // calculate dx/dxi in[0] + dy/dxi in[1]
912 for (int i = 0; i < 2; ++i)
913 {
914 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
915 for (int j = 1; j < m_coordim; ++j)
916 {
917 Vmath::Vvtvp(ntot, m_derivFac[i + 2 * j], 1, in[j], 1,
918 tmp[i], 1, tmp[i], 1);
919 }
920 }
921 }
922 else
923 {
925 for (int e = 0; e < m_numElmt; ++e)
926 {
927 // calculate dx/dxi in[0] + dy/dxi in[1]
928 for (int i = 0; i < 2; ++i)
929 {
930 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
931 t = tmp[i] + e * m_nqe, 1);
932 for (int j = 1; j < m_coordim; ++j)
933 {
934 Vmath::Svtvp(m_nqe, m_derivFac[i + 2 * j][e],
935 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
936 1, t = tmp[i] + e * m_nqe, 1);
937 }
938 }
939 }
940 }
941 // Iproduct wrt derivative of base 1
944 tmp[0], output, wsp1);
945
946 // Iproduct wrt derivative of base 1
949 tmp[1], tmp[0], wsp1);
950
951 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
952 }
953
954 void operator()(int dir, const Array<OneD, const NekDouble> &input,
956 Array<OneD, NekDouble> &wsp) override final
957 {
958 boost::ignore_unused(dir, input, output, wsp);
959 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
960 }
961
963 int coll_phys_offset) override
964 {
965 boost::ignore_unused(factors, coll_phys_offset);
966 ASSERTL0(false, "Not valid for this operator.");
967 }
968
969protected:
970 const int m_nquad0;
971 const int m_nquad1;
972 const int m_nmodes0;
973 const int m_nmodes1;
974 const bool m_colldir0;
975 const bool m_colldir1;
983
984private:
986 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
988 : Operator(pCollExp, pGeomData, factors),
989 m_nquad0(m_stdExp->GetNumPoints(0)),
990 m_nquad1(m_stdExp->GetNumPoints(1)),
991 m_nmodes0(m_stdExp->GetBasisNumModes(0)),
992 m_nmodes1(m_stdExp->GetBasisNumModes(1)),
993 m_colldir0(m_stdExp->GetBasis(0)->Collocation()),
994 m_colldir1(m_stdExp->GetBasis(1)->Collocation()),
995 m_base0(m_stdExp->GetBasis(0)->GetBdata()),
996 m_base1(m_stdExp->GetBasis(1)->GetBdata()),
997 m_derbase0(m_stdExp->GetBasis(0)->GetDbdata()),
998 m_derbase1(m_stdExp->GetBasis(1)->GetDbdata())
999 {
1000 LibUtilities::PointsKeyVector PtsKey = m_stdExp->GetPointsKeys();
1001 m_coordim = pCollExp[0]->GetCoordim();
1002
1003 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
1004 m_jacWStdW = pGeomData->GetJacWithStdWeights(pCollExp);
1005 m_wspSize =
1006 4 * m_numElmt * (max(m_nquad0 * m_nquad1, m_nmodes0 * m_nmodes1));
1007 }
1008};
1009
1010/// Factory initialisation for the IProductWRTDerivBase_SumFac_Quad operator
1011OperatorKey IProductWRTDerivBase_SumFac_Quad::m_type =
1014 IProductWRTDerivBase_SumFac_Quad::create,
1015 "IProductWRTDerivBase_IterPerExp_Quad");
1016
1017/**
1018 * @brief Inner product WRT deriv base operator using sum-factorisation (Tri)
1019 */
1021{
1022public:
1024
1026 {
1027 }
1028
1029 /**
1030 * This method calculates:
1031 *
1032 * \f[ (d\phi/dx,in[0]) + (d\phi/dy,in[1]) \f]
1033 *
1034 * which can be represented in terms of local cartesian
1035 * derivaties as:
1036 *
1037 * \f[ ((d\phi/d\xi_0\, d\xi_0/dx +
1038 * d\phi/d\xi_1\, d\xi_1/dx),in[0]) + \f]
1039 *
1040 * \f[ ((d\phi/d\xi_0\, d\xi_0/dy +
1041 * d\phi/d\xi_1\, d\xi_1/dy),in[1]) + \f]
1042 *
1043 * where we note that
1044 *
1045 * \f[ d\phi/d\xi_0 = d\phi/d\eta_0\, d\eta_0/d\xi_0 =
1046 * d\phi/d\eta_0 2/(1-\eta_1) \f]
1047 *
1048 * \f[ d\phi/d\xi_1 = d\phi/d\eta_1\, d\eta_1/d\xi_1 +
1049 * d\phi/d\eta_1\, d\eta_1/d\xi_1 = d\phi/d\eta_0 (1+\eta_0)/(1-\eta_1)
1050 * + d\phi/d\eta_1 \f]
1051 *
1052 * and so the full inner products are
1053 *
1054 * \f[ (d\phi/dx,in[0]) + (dphi/dy,in[1]) =
1055 * (d\phi/d\eta_0, ((2/(1-\eta_1) (d\xi_0/dx in[0] + d\xi_0/dy in[1])
1056 * + (1-\eta_0)/(1-\eta_1) (d\xi_1/dx in[0]+d\xi_1/dy in[1]))
1057 * + (d\phi/d\eta_1, (d\xi_1/dx in[0] + d\xi_1/dy in[1])) \f]
1058 *
1059 */
1061 Array<OneD, NekDouble> &entry1,
1062 Array<OneD, NekDouble> &entry2,
1063 Array<OneD, NekDouble> &entry3,
1064 Array<OneD, NekDouble> &wsp) override final
1065 {
1066
1067 unsigned int nPhys = m_stdExp->GetTotPoints();
1068 unsigned int ntot = m_numElmt * nPhys;
1069 unsigned int nmodes = m_stdExp->GetNcoeffs();
1070 unsigned int nmax = max(ntot, m_numElmt * nmodes);
1072 Array<OneD, NekDouble> output, wsp1;
1074
1075 in[0] = entry0;
1076 in[1] = entry1;
1077 in[2] = entry2;
1078
1079 output = (m_coordim == 2) ? entry2 : entry3;
1080
1081 tmp[0] = wsp;
1082 tmp[1] = wsp + nmax;
1083 wsp1 = wsp + 2 * nmax;
1084
1085 if (m_isDeformed)
1086 {
1087 for (int i = 0; i < 2; ++i)
1088 {
1089 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
1090 for (int j = 1; j < m_coordim; ++j)
1091 {
1092 Vmath::Vvtvp(ntot, m_derivFac[i + 2 * j], 1, in[j], 1,
1093 tmp[i], 1, tmp[i], 1);
1094 }
1095 }
1096 }
1097 else
1098 {
1100 for (int e = 0; e < m_numElmt; ++e)
1101 {
1102 // calculate dx/dxi in[0] + dy/dxi in[1]
1103 for (int i = 0; i < 2; ++i)
1104 {
1105 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
1106 t = tmp[i] + e * m_nqe, 1);
1107 for (int j = 1; j < m_coordim; ++j)
1108 {
1109 Vmath::Svtvp(m_nqe, m_derivFac[i + 2 * j][e],
1110 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
1111 1, t = tmp[i] + e * m_nqe, 1);
1112 }
1113 }
1114 }
1115 }
1116
1117 // Multiply by factor: 2/(1-z1)
1118 for (int i = 0; i < m_numElmt; ++i)
1119 {
1120 // scale tmp[0] by geometric factor: 2/(1-z1)
1121 Vmath::Vmul(nPhys, &m_fac0[0], 1, tmp[0].get() + i * nPhys, 1,
1122 tmp[0].get() + i * nPhys, 1);
1123
1124 // scale tmp[1] by geometric factor (1+z0)/(1-z1)
1125 Vmath::Vvtvp(nPhys, &m_fac1[0], 1, tmp[1].get() + i * nPhys, 1,
1126 tmp[0].get() + i * nPhys, 1, tmp[0].get() + i * nPhys,
1127 1);
1128 }
1129
1130 // Iproduct wrt derivative of base 0
1132 m_nmodes1, m_derbase0, m_base1, m_jacWStdW, tmp[0], output,
1133 wsp1);
1134
1135 // Iproduct wrt derivative of base 1
1137 m_nmodes1, m_base0, m_derbase1, m_jacWStdW, tmp[1], tmp[0],
1138 wsp1);
1139
1140 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1141 }
1142
1143 void operator()(int dir, const Array<OneD, const NekDouble> &input,
1144 Array<OneD, NekDouble> &output,
1145 Array<OneD, NekDouble> &wsp) override final
1146 {
1147 boost::ignore_unused(dir, input, output, wsp);
1148 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
1149 }
1150
1152 int coll_phys_offset) override
1153 {
1154 boost::ignore_unused(factors, coll_phys_offset);
1155 ASSERTL0(false, "Not valid for this operator.");
1156 }
1157
1158protected:
1159 const int m_nquad0;
1160 const int m_nquad1;
1161 const int m_nmodes0;
1162 const int m_nmodes1;
1163 const bool m_colldir0;
1164 const bool m_colldir1;
1175
1176private:
1178 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
1180 : Operator(pCollExp, pGeomData, factors),
1181 m_nquad0(m_stdExp->GetNumPoints(0)),
1182 m_nquad1(m_stdExp->GetNumPoints(1)),
1183 m_nmodes0(m_stdExp->GetBasisNumModes(0)),
1184 m_nmodes1(m_stdExp->GetBasisNumModes(1)),
1185 m_colldir0(m_stdExp->GetBasis(0)->Collocation()),
1186 m_colldir1(m_stdExp->GetBasis(1)->Collocation()),
1187 m_base0(m_stdExp->GetBasis(0)->GetBdata()),
1188 m_base1(m_stdExp->GetBasis(1)->GetBdata()),
1189 m_derbase0(m_stdExp->GetBasis(0)->GetDbdata()),
1190 m_derbase1(m_stdExp->GetBasis(1)->GetDbdata())
1191 {
1192 LibUtilities::PointsKeyVector PtsKey = m_stdExp->GetPointsKeys();
1193 m_coordim = pCollExp[0]->GetCoordim();
1194
1195 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
1196 m_jacWStdW = pGeomData->GetJacWithStdWeights(pCollExp);
1197 m_wspSize =
1198 4 * m_numElmt * (max(m_nquad0 * m_nquad1, m_nmodes0 * m_nmodes1));
1199
1200 if (m_stdExp->GetBasis(0)->GetBasisType() == LibUtilities::eModified_A)
1201 {
1202 m_sortTopVertex = true;
1203 }
1204 else
1205 {
1206 m_sortTopVertex = false;
1207 }
1208
1209 const Array<OneD, const NekDouble> &z0 = m_stdExp->GetBasis(0)->GetZ();
1210 const Array<OneD, const NekDouble> &z1 = m_stdExp->GetBasis(1)->GetZ();
1211
1213 // set up geometric factor: 2/(1-z1)
1214 for (int i = 0; i < m_nquad0; ++i)
1215 {
1216 for (int j = 0; j < m_nquad1; ++j)
1217 {
1218 m_fac0[i + j * m_nquad0] = 2.0 / (1 - z1[j]);
1219 }
1220 }
1221
1223 // set up geometric factor: (1+z0)/(1-z1)
1224 for (int i = 0; i < m_nquad0; ++i)
1225 {
1226 for (int j = 0; j < m_nquad1; ++j)
1227 {
1228 m_fac1[i + j * m_nquad0] = (1 + z0[i]) / (1 - z1[j]);
1229 }
1230 }
1231 }
1232};
1233
1234/// Factory initialisation for the IProductWRTDerivBase_SumFac_Tri operator
1235OperatorKey IProductWRTDerivBase_SumFac_Tri::m_type =
1238 IProductWRTDerivBase_SumFac_Tri::create,
1239 "IProductWRTDerivBase_IterPerExp_Tri");
1240
1241/**
1242 * @brief Inner product WRT deriv base operator using sum-factorisation (Hex)
1243 */
1245{
1246public:
1248
1250 {
1251 }
1252
1254 Array<OneD, NekDouble> &entry1,
1255 Array<OneD, NekDouble> &entry2,
1256 Array<OneD, NekDouble> &entry3,
1257 Array<OneD, NekDouble> &wsp) override final
1258 {
1259
1260 unsigned int nPhys = m_stdExp->GetTotPoints();
1261 unsigned int ntot = m_numElmt * nPhys;
1262 unsigned int nmodes = m_stdExp->GetNcoeffs();
1263 unsigned int nmax = max(ntot, m_numElmt * nmodes);
1265 Array<OneD, NekDouble> output, wsp1;
1267
1268 in[0] = entry0;
1269 in[1] = entry1;
1270 in[2] = entry2;
1271
1272 output = entry3;
1273
1274 for (int i = 0; i < 3; ++i)
1275 {
1276 tmp[i] = wsp + i * nmax;
1277 }
1278
1279 if (m_isDeformed)
1280 {
1281 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
1282 for (int i = 0; i < 3; ++i)
1283 {
1284 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
1285 for (int j = 1; j < 3; ++j)
1286 {
1287 Vmath::Vvtvp(ntot, m_derivFac[i + 3 * j], 1, in[j], 1,
1288 tmp[i], 1, tmp[i], 1);
1289 }
1290 }
1291 }
1292 else
1293 {
1295 for (int e = 0; e < m_numElmt; ++e)
1296 {
1297 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
1298 for (int i = 0; i < 3; ++i)
1299 {
1300 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
1301 t = tmp[i] + e * m_nqe, 1);
1302 for (int j = 1; j < 3; ++j)
1303 {
1304 Vmath::Svtvp(m_nqe, m_derivFac[i + 3 * j][e],
1305 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
1306 1, t = tmp[i] + e * m_nqe, 1);
1307 }
1308 }
1309 }
1310 }
1311
1312 wsp1 = wsp + 3 * nmax;
1313
1314 // calculate Iproduct WRT Std Deriv
1317 m_derbase0, m_base1, m_base2, m_jacWStdW, tmp[0], output,
1318 wsp1);
1319
1322 m_base0, m_derbase1, m_base2, m_jacWStdW, tmp[1], tmp[0],
1323 wsp1);
1324 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1325
1328 m_base0, m_base1, m_derbase2, m_jacWStdW, tmp[2], tmp[0],
1329 wsp1);
1330 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1331 }
1332
1333 void operator()(int dir, const Array<OneD, const NekDouble> &input,
1334 Array<OneD, NekDouble> &output,
1335 Array<OneD, NekDouble> &wsp) override final
1336 {
1337 boost::ignore_unused(dir, input, output, wsp);
1338 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
1339 }
1340
1342 int coll_phys_offset) override
1343 {
1344 boost::ignore_unused(factors, coll_phys_offset);
1345 ASSERTL0(false, "Not valid for this operator.");
1346 }
1347
1348protected:
1349 const int m_nquad0;
1350 const int m_nquad1;
1351 const int m_nquad2;
1352 const int m_nmodes0;
1353 const int m_nmodes1;
1354 const int m_nmodes2;
1355 const bool m_colldir0;
1356 const bool m_colldir1;
1357 const bool m_colldir2;
1366
1367private:
1369 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
1371 : Operator(pCollExp, pGeomData, factors),
1372 m_nquad0(m_stdExp->GetNumPoints(0)),
1373 m_nquad1(m_stdExp->GetNumPoints(1)),
1374 m_nquad2(m_stdExp->GetNumPoints(2)),
1375 m_nmodes0(m_stdExp->GetBasisNumModes(0)),
1376 m_nmodes1(m_stdExp->GetBasisNumModes(1)),
1377 m_nmodes2(m_stdExp->GetBasisNumModes(2)),
1378 m_colldir0(m_stdExp->GetBasis(0)->Collocation()),
1379 m_colldir1(m_stdExp->GetBasis(1)->Collocation()),
1380 m_colldir2(m_stdExp->GetBasis(2)->Collocation()),
1381 m_base0(m_stdExp->GetBasis(0)->GetBdata()),
1382 m_base1(m_stdExp->GetBasis(1)->GetBdata()),
1383 m_base2(m_stdExp->GetBasis(2)->GetBdata()),
1384 m_derbase0(m_stdExp->GetBasis(0)->GetDbdata()),
1385 m_derbase1(m_stdExp->GetBasis(1)->GetDbdata()),
1386 m_derbase2(m_stdExp->GetBasis(2)->GetDbdata())
1387
1388 {
1389 m_jacWStdW = pGeomData->GetJacWithStdWeights(pCollExp);
1390 m_wspSize = 6 * m_numElmt *
1391 (max(m_nquad0 * m_nquad1 * m_nquad2,
1393 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
1394 }
1395};
1396
1397/// Factory initialisation for the IProductWRTDerivBase_SumFac_Hex operator
1398OperatorKey IProductWRTDerivBase_SumFac_Hex::m_type =
1401 IProductWRTDerivBase_SumFac_Hex::create,
1402 "IProductWRTDerivBase_SumFac_Hex");
1403
1404/**
1405 * @brief Inner product WRT deriv base operator using sum-factorisation (Tet)
1406 */
1408{
1409public:
1411
1412 /**
1413 * This method calculates:
1414 *
1415 * \f[ (d\phi/dx,in[0]) + (d\phi/dy,in[1]) + (d\phi/dz,in[2]) \f]
1416 *
1417 * which can be represented in terms of local cartesian
1418 * derivaties as:
1419 *
1420 * \f[ ((d\phi/d\xi_0\, d\xi_0/dx +
1421 * d\phi/d\xi_1\, d\xi_1/dx +
1422 * d\phi/d\xi_2\, d\xi_2/dx),in[0]) + \f]
1423 *
1424 * \f[ ((d\phi/d\xi_0\, d\xi_0/dy +
1425 * d\phi/d\xi_1\, d\xi_1/dy +
1426 * d\phi/d\xi_2\, d\xi_2/dy),in[1]) + \f]
1427 *
1428 * \f[ ((d\phi/d\xi_0\, d\xi_0/dz +
1429 * d\phi/d\xi_1\, d\xi_1/dz +
1430 * d\phi/d\xi_2\, d\xi_2/dz),in[2]) \, \f]
1431 *
1432 * where we note that
1433 *
1434 * \f[ d\phi/d\xi_0 = d\phi/d\eta_0 4/((1-\eta_1)(1-\eta_2)) \f]
1435 *
1436 * \f[ d\phi/d\xi_1 = d\phi/d\eta_0 2(1+\eta_0)/((1-\eta_1)(1-\eta_2))
1437 * + d\phi/d\eta_1 2/(1-\eta_2) \f]
1438 *
1439 * \f[ d\phi/d\xi_2 = d\phi/d\eta_0 2(1+\eta_0)/((1-\eta_1)(1-\eta_2))
1440 * + d\phi/d\eta_1 (1+\eta_1)/(1-\eta_2) + d\phi/d\eta_2 \f]
1441 *
1442 * and so the full inner products are
1443 *
1444 * \f[ (d\phi/dx,in[0]) + (d\phi/dy,in[1]) + (d\phi/dz,in[2]) = \f]
1445 *
1446 * \f[ (d\phi/d\eta_0, fac0 (tmp0 + fac1(tmp1 + tmp2)))
1447 * + (d\phi/d\eta_1, fac2 (tmp1 + fac3 tmp2))
1448 * + (d\phi/d\eta_2, tmp2) \f]
1449 *
1450 * where
1451 *
1452 * \f[ \begin{array}{lcl}
1453 * tmp0 &=& (d\xi_0/dx in[0] + d\xi_0/dy in[1] + d\xi_0/dz in[2]) \\
1454 * tmp1 &=& (d\xi_1/dx in[0] + d\xi_1/dy in[1] + d\xi_1/dz in[2]) \\
1455 * tmp2 &=& (d\xi_2/dx in[0] + d\xi_2/dy in[1] + d\xi_2/dz in[2])
1456 * \end{array} \f]
1457 *
1458 * \f[ \begin{array}{lcl}
1459 * fac0 &= & 4/((1-\eta_1)(1-\eta_2)) \\
1460 * fac1 &= & (1+\eta_0)/2 \\
1461 * fac2 &= & 2/(1-\eta_2) \\
1462 * fac3 &= & (1+\eta_1)/2 \end{array} \f]
1463 *
1464 */
1465 void operator()(const Array<OneD, const NekDouble> &entry0,
1466 Array<OneD, NekDouble> &entry1,
1467 Array<OneD, NekDouble> &entry2,
1468 Array<OneD, NekDouble> &entry3,
1469 Array<OneD, NekDouble> &wsp) override final
1470 {
1471
1472 unsigned int nPhys = m_stdExp->GetTotPoints();
1473 unsigned int ntot = m_numElmt * nPhys;
1474 unsigned int nmodes = m_stdExp->GetNcoeffs();
1475 unsigned int nmax = max(ntot, m_numElmt * nmodes);
1477 Array<OneD, NekDouble> output, wsp1;
1479
1480 in[0] = entry0;
1481 in[1] = entry1;
1482 in[2] = entry2;
1483
1484 output = entry3;
1485
1486 for (int i = 0; i < 3; ++i)
1487 {
1488 tmp[i] = wsp + i * nmax;
1489 }
1490
1491 if (m_isDeformed)
1492 {
1493 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
1494 for (int i = 0; i < 3; ++i)
1495 {
1496 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
1497 for (int j = 1; j < 3; ++j)
1498 {
1499 Vmath::Vvtvp(ntot, m_derivFac[i + 3 * j], 1, in[j], 1,
1500 tmp[i], 1, tmp[i], 1);
1501 }
1502 }
1503 }
1504 else
1505 {
1507 for (int e = 0; e < m_numElmt; ++e)
1508 {
1509 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
1510 for (int i = 0; i < 3; ++i)
1511 {
1512 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
1513 t = tmp[i] + e * m_nqe, 1);
1514 for (int j = 1; j < 3; ++j)
1515 {
1516 Vmath::Svtvp(m_nqe, m_derivFac[i + 3 * j][e],
1517 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
1518 1, t = tmp[i] + e * m_nqe, 1);
1519 }
1520 }
1521 }
1522 }
1523
1524 wsp1 = wsp + 3 * nmax;
1525
1526 // Sort into eta factors
1527 for (int i = 0; i < m_numElmt; ++i)
1528 {
1529 // add tmp[1] + tmp[2]
1530 Vmath::Vadd(nPhys, tmp[1].get() + i * nPhys, 1,
1531 tmp[2].get() + i * nPhys, 1, wsp1.get(), 1);
1532
1533 // scale wsp1 by fac1 and add to tmp0
1534 Vmath::Vvtvp(nPhys, &m_fac1[0], 1, wsp1.get(), 1,
1535 tmp[0].get() + i * nPhys, 1, tmp[0].get() + i * nPhys,
1536 1);
1537
1538 // scale tmp[0] by fac0
1539 Vmath::Vmul(nPhys, &m_fac0[0], 1, tmp[0].get() + i * nPhys, 1,
1540 tmp[0].get() + i * nPhys, 1);
1541
1542 // scale tmp[2] by fac3 and add to tmp1
1543 Vmath::Vvtvp(nPhys, &m_fac3[0], 1, tmp[2].get() + i * nPhys, 1,
1544 tmp[1].get() + i * nPhys, 1, tmp[1].get() + i * nPhys,
1545 1);
1546
1547 // scale tmp[1] by fac2
1548 Vmath::Vmul(nPhys, &m_fac2[0], 1, tmp[1].get() + i * nPhys, 1,
1549 tmp[1].get() + i * nPhys, 1);
1550 }
1551
1552 // calculate Iproduct WRT Std Deriv
1555 m_base2, m_jacWStdW, tmp[0], output, wsp1);
1556
1559 m_base2, m_jacWStdW, tmp[1], tmp[0], wsp1);
1560 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1561
1564 m_derbase2, m_jacWStdW, tmp[2], tmp[0], wsp1);
1565 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1566 }
1567
1568 void operator()(int dir, const Array<OneD, const NekDouble> &input,
1569 Array<OneD, NekDouble> &output,
1570 Array<OneD, NekDouble> &wsp) override final
1571 {
1572 boost::ignore_unused(dir, input, output, wsp);
1573 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
1574 }
1575
1577 int coll_phys_offset) override
1578 {
1579 boost::ignore_unused(factors, coll_phys_offset);
1580 ASSERTL0(false, "Not valid for this operator.");
1581 }
1582
1583protected:
1584 const int m_nquad0;
1585 const int m_nquad1;
1586 const int m_nquad2;
1587 const int m_nmodes0;
1588 const int m_nmodes1;
1589 const int m_nmodes2;
1603
1604private:
1606 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
1608 : Operator(pCollExp, pGeomData, factors),
1609 m_nquad0(m_stdExp->GetNumPoints(0)),
1610 m_nquad1(m_stdExp->GetNumPoints(1)),
1611 m_nquad2(m_stdExp->GetNumPoints(2)),
1612 m_nmodes0(m_stdExp->GetBasisNumModes(0)),
1613 m_nmodes1(m_stdExp->GetBasisNumModes(1)),
1614 m_nmodes2(m_stdExp->GetBasisNumModes(2)),
1615 m_base0(m_stdExp->GetBasis(0)->GetBdata()),
1616 m_base1(m_stdExp->GetBasis(1)->GetBdata()),
1617 m_base2(m_stdExp->GetBasis(2)->GetBdata()),
1618 m_derbase0(m_stdExp->GetBasis(0)->GetDbdata()),
1619 m_derbase1(m_stdExp->GetBasis(1)->GetDbdata()),
1620 m_derbase2(m_stdExp->GetBasis(2)->GetDbdata())
1621
1622 {
1623 m_jacWStdW = pGeomData->GetJacWithStdWeights(pCollExp);
1624 m_wspSize = 6 * m_numElmt *
1625 (max(m_nquad0 * m_nquad1 * m_nquad2,
1627 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
1628
1629 const Array<OneD, const NekDouble> &z0 = m_stdExp->GetBasis(0)->GetZ();
1630 const Array<OneD, const NekDouble> &z1 = m_stdExp->GetBasis(1)->GetZ();
1631 const Array<OneD, const NekDouble> &z2 = m_stdExp->GetBasis(2)->GetZ();
1632
1637 // calculate 2.0/((1-eta_1)(1-eta_2))
1638 for (int i = 0; i < m_nquad0; ++i)
1639 {
1640 for (int j = 0; j < m_nquad1; ++j)
1641 {
1642 for (int k = 0; k < m_nquad2; ++k)
1643 {
1644
1645 m_fac0[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
1646 4.0 / ((1 - z1[j]) * (1 - z2[k]));
1647 m_fac1[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
1648 (1 + z0[i]) * 0.5;
1649 m_fac2[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
1650 2.0 / (1 - z2[k]);
1651 m_fac3[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
1652 (1 + z1[j]) * 0.5;
1653 }
1654 }
1655 }
1656
1657 if (m_stdExp->GetBasis(0)->GetBasisType() == LibUtilities::eModified_A)
1658 {
1659 m_sortTopEdge = true;
1660 }
1661 else
1662 {
1663 m_sortTopEdge = false;
1664 }
1665 }
1666};
1667
1668/// Factory initialisation for the IProductWRTDerivBase_SumFac_Tet operator
1669OperatorKey IProductWRTDerivBase_SumFac_Tet::m_type =
1672 IProductWRTDerivBase_SumFac_Tet::create,
1673 "IProductWRTDerivBase_SumFac_Tet");
1674
1675/**
1676 * @brief Inner product WRT deriv base operator using sum-factorisation (Prism)
1677 */
1679{
1680public:
1682
1684 {
1685 }
1686
1687 /**
1688 * This method calculates:
1689 *
1690 * \f[ (d\phi/dx,in[0]) + (d\phi/dy,in[1]) + (d\phi/dz,in[2]) \f]
1691 *
1692 * which can be represented in terms of local cartesian
1693 * derivaties as:
1694 *
1695 * \f[ ((d\phi/d\xi_0\, d\xi_0/dx +
1696 * d\phi/d\xi_1\, d\xi_1/dx +
1697 * d\phi/d\xi_2\, d\xi_2/dx),in[0]) + \f]
1698 *
1699 * \f[ ((d\phi/d\xi_0\, d\xi_0/dy +
1700 * d\phi/d\xi_1\, d\xi_1/dy +
1701 * d\phi/d\xi_2\, d\xi_2/dy),in[1]) + \f]
1702 *
1703 * \f[ ((d\phi/d\xi_0\, d\xi_0/dz +
1704 * d\phi/d\xi_1\, d\xi_1/dz +
1705 * d\phi/d\xi_2\, d\xi_2/dz),in[2]) \, \f]
1706 *
1707 * where we note that
1708 *
1709 * \f[ d\phi/d\xi_0 =
1710 * d\phi/d\eta_0 d\eta_0/d\xi_0 = d\phi/d\eta_0 2/(1-\eta_2) \f]
1711 *
1712 * \f[ d\phi/d\xi_2 =
1713 * d\phi/d\eta_0 d\eta_0/d\xi_2 + d\phi/d\eta_2 d\eta_2/d\xi_2 =
1714 * d\phi/d\eta_0 (1+\eta_0)/(1-\eta_2) + d\phi/d\eta_2 \f]
1715 *
1716 *
1717 * and so the full inner products are
1718 *
1719 * \f[ (d\phi/dx,in[0]) + (d\phi/dy,in[1]) + (d\phi/dz,in[2]) = \f]
1720 *
1721 * \f[ (d\phi/d\eta_0, ((2/(1-\eta_2) (d\xi_0/dx in[0] + d\xi_0/dy in[1]
1722 * + d\xi_0/dz in[2])
1723 * + (1-\eta_0)/(1-\eta_2) (d\xi_2/dx in[0] + d\xi_2/dy in[1]
1724 * + d\xi_2/dz in[2] )) + \f]
1725 *
1726 * \f[ (d\phi/d\eta_1, (d\xi_1/dx in[0] + d\xi_1/dy in[1]
1727 * + d\xi_1/dz in[2])) + \f]
1728 *
1729 * \f[ (d\phi/d\eta_2, (d\xi_2/dx in[0] + d\xi_2/dy in[1]
1730 * + d\xi_2/dz in[2])) \f]
1731 *
1732 */
1734 Array<OneD, NekDouble> &entry1,
1735 Array<OneD, NekDouble> &entry2,
1736 Array<OneD, NekDouble> &entry3,
1737 Array<OneD, NekDouble> &wsp) override final
1738 {
1739
1740 unsigned int nPhys = m_stdExp->GetTotPoints();
1741 unsigned int ntot = m_numElmt * nPhys;
1742 unsigned int nmodes = m_stdExp->GetNcoeffs();
1743 unsigned int nmax = max(ntot, m_numElmt * nmodes);
1745 Array<OneD, NekDouble> output, wsp1;
1747
1748 in[0] = entry0;
1749 in[1] = entry1;
1750 in[2] = entry2;
1751
1752 output = entry3;
1753
1754 for (int i = 0; i < 3; ++i)
1755 {
1756 tmp[i] = wsp + i * nmax;
1757 }
1758
1759 if (m_isDeformed)
1760 {
1761 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
1762 for (int i = 0; i < 3; ++i)
1763 {
1764 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
1765 for (int j = 1; j < 3; ++j)
1766 {
1767 Vmath::Vvtvp(ntot, m_derivFac[i + 3 * j], 1, in[j], 1,
1768 tmp[i], 1, tmp[i], 1);
1769 }
1770 }
1771 }
1772 else
1773 {
1775 for (int e = 0; e < m_numElmt; ++e)
1776 {
1777 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
1778 for (int i = 0; i < 3; ++i)
1779 {
1780 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
1781 t = tmp[i] + e * m_nqe, 1);
1782 for (int j = 1; j < 3; ++j)
1783 {
1784 Vmath::Svtvp(m_nqe, m_derivFac[i + 3 * j][e],
1785 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
1786 1, t = tmp[i] + e * m_nqe, 1);
1787 }
1788 }
1789 }
1790 }
1791
1792 wsp1 = wsp + 3 * nmax;
1793
1794 // Sort into eta factors
1795 for (int i = 0; i < m_numElmt; ++i)
1796 {
1797 // scale tmp[0] by fac0
1798 Vmath::Vmul(nPhys, &m_fac0[0], 1, tmp[0].get() + i * nPhys, 1,
1799 tmp[0].get() + i * nPhys, 1);
1800
1801 // scale tmp[2] by fac1 and add to tmp0
1802 Vmath::Vvtvp(nPhys, &m_fac1[0], 1, tmp[2].get() + i * nPhys, 1,
1803 tmp[0].get() + i * nPhys, 1, tmp[0].get() + i * nPhys,
1804 1);
1805 }
1806
1807 // calculate Iproduct WRT Std Deriv
1810 m_base2, m_jacWStdW, tmp[0], output, wsp1);
1811
1814 m_base2, m_jacWStdW, tmp[1], tmp[0], wsp1);
1815 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1816
1819 m_derbase2, m_jacWStdW, tmp[2], tmp[0], wsp1);
1820 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1821 }
1822
1823 void operator()(int dir, const Array<OneD, const NekDouble> &input,
1824 Array<OneD, NekDouble> &output,
1825 Array<OneD, NekDouble> &wsp) override final
1826 {
1827 boost::ignore_unused(dir, input, output, wsp);
1828 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
1829 }
1830
1832 int coll_phys_offset) override
1833 {
1834 boost::ignore_unused(factors, coll_phys_offset);
1835 ASSERTL0(false, "Not valid for this operator.");
1836 }
1837
1838protected:
1839 const int m_nquad0;
1840 const int m_nquad1;
1841 const int m_nquad2;
1842 const int m_nmodes0;
1843 const int m_nmodes1;
1844 const int m_nmodes2;
1856
1857private:
1859 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
1861 : Operator(pCollExp, pGeomData, factors),
1862 m_nquad0(m_stdExp->GetNumPoints(0)),
1863 m_nquad1(m_stdExp->GetNumPoints(1)),
1864 m_nquad2(m_stdExp->GetNumPoints(2)),
1865 m_nmodes0(m_stdExp->GetBasisNumModes(0)),
1866 m_nmodes1(m_stdExp->GetBasisNumModes(1)),
1867 m_nmodes2(m_stdExp->GetBasisNumModes(2)),
1868 m_base0(m_stdExp->GetBasis(0)->GetBdata()),
1869 m_base1(m_stdExp->GetBasis(1)->GetBdata()),
1870 m_base2(m_stdExp->GetBasis(2)->GetBdata()),
1871 m_derbase0(m_stdExp->GetBasis(0)->GetDbdata()),
1872 m_derbase1(m_stdExp->GetBasis(1)->GetDbdata()),
1873 m_derbase2(m_stdExp->GetBasis(2)->GetDbdata())
1874
1875 {
1876 m_jacWStdW = pGeomData->GetJacWithStdWeights(pCollExp);
1877 m_wspSize = 6 * m_numElmt *
1878 (max(m_nquad0 * m_nquad1 * m_nquad2,
1880 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
1881
1882 if (m_stdExp->GetBasis(0)->GetBasisType() == LibUtilities::eModified_A)
1883 {
1884 m_sortTopVertex = true;
1885 }
1886 else
1887 {
1888 m_sortTopVertex = false;
1889 }
1890
1891 const Array<OneD, const NekDouble> &z0 = m_stdExp->GetBasis(0)->GetZ();
1892 const Array<OneD, const NekDouble> &z2 = m_stdExp->GetBasis(2)->GetZ();
1893
1896
1897 for (int i = 0; i < m_nquad0; ++i)
1898 {
1899 for (int j = 0; j < m_nquad1; ++j)
1900 {
1901 for (int k = 0; k < m_nquad2; ++k)
1902 {
1903 // set up geometric factor: 2/(1-z1)
1904 m_fac0[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
1905 2.0 / (1 - z2[k]);
1906 // set up geometric factor: (1+z0)/(1-z1)
1907 m_fac1[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
1908 (1 + z0[i]) / (1 - z2[k]);
1909 }
1910 }
1911 }
1912 }
1913};
1914
1915/// Factory initialisation for the IProductWRTDerivBase_SumFac_Prism operator
1916OperatorKey IProductWRTDerivBase_SumFac_Prism::m_type =
1919 IProductWRTDerivBase_SumFac_Prism::create,
1920 "IProductWRTDerivBase_SumFac_Prism");
1921
1922/**
1923 * @brief Inner product WRT deriv base operator using sum-factorisation (Pyr)
1924 */
1926{
1927public:
1929
1931 {
1932 }
1933
1934 /**
1935 * This method calculates:
1936 *
1937 * \f[ (d\phi/dx,in[0]) + (d\phi/dy,in[1]) + (d\phi/dz,in[2]) \f]
1938 *
1939 * which can be represented in terms of local cartesian
1940 * derivaties as:
1941 *
1942 * \f[ ((d\phi/d\xi_0\, d\xi_0/dx +
1943 * d\phi/d\xi_1\, d\xi_1/dx +
1944 * d\phi/d\xi_2\, d\xi_2/dx),in[0]) + \f]
1945 *
1946 * \f[ ((d\phi/d\xi_0\, d\xi_0/dy +
1947 * d\phi/d\xi_1\, d\xi_1/dy +
1948 * d\phi/d\xi_2\, d\xi_2/dy),in[1]) + \f]
1949 *
1950 * \f[ ((d\phi/d\xi_0\, d\xi_0/dz +
1951 * d\phi/d\xi_1\, d\xi_1/dz +
1952 * d\phi/d\xi_2\, d\xi_2/dz),in[2]) \, \f]
1953 *
1954 * where we note that
1955 *
1956 * \f[ d\phi/d\xi_0 =
1957 * d\phi/d\eta_0\, d\eta_0/d\xi_0 =
1958 * d\phi/d\eta_0\, 2/(1-\eta_2). \f]
1959 *
1960 * \f[ d\phi/d\xi_1 =
1961 * d\phi/d\eta_1\, d\eta_1/d\xi_1 =
1962 * d\phi/d\eta_1\, 2/(1-\eta_2) \f]
1963 *
1964 * \f[ d\phi/d\xi_2 =
1965 * d\phi/d\eta_0\, d\eta_0/d\xi_2 +
1966 * d\phi/d\eta_1\, d\eta_1/d\xi_2 +
1967 * d\phi/d\eta_2\, d\eta_2/d\xi_2 =
1968 * d\phi/d\eta_0 (1+\eta_0)/(1-\eta_2) +
1969 * d\phi/d\eta_1 (1+\eta_1)/(1-\eta_2) + d\phi/d\eta_2 \f]
1970 *
1971 * and so the full inner products are
1972 *
1973 * \f[ (d\phi/dx,in[0]) + (d\phi/dy,in[1]) + (d\phi/dz,in[2]) = \f]
1974 *
1975 * \f[ (d\phi/d\eta_0, ((2/(1-\eta_2) (d\xi_0/dx in[0] +
1976 * d\xi_0/dy in[1] +
1977 * (1-\eta_0)/(1-\eta_2) (d\xi_2/dx in[0] + d\xi_2/dy in[1]
1978 * + d\xi_2/dz in[2] )) + \f]
1979 * \f[ (d\phi/d\eta_1, ((2/(1-\eta_2) (d\xi_1/dx in[0] +
1980 * d\xi_0/dy in[1] + d\xi_0/dz in[2]) +
1981 * (1-\eta_1)/(1-\eta_2) (d\xi_2/dx in[0] + d\xi_2/dy in[1] +
1982 * d\xi_2/dz in[2] )) \f]
1983 *
1984 * \f[ (d\phi/d\eta_2, (d\xi_2/dx in[0] + d\xi_2/dy in[1] +
1985 * d\xi_2/dz in[2])) \f]
1986 */
1988 Array<OneD, NekDouble> &entry1,
1989 Array<OneD, NekDouble> &entry2,
1990 Array<OneD, NekDouble> &entry3,
1991 Array<OneD, NekDouble> &wsp) override final
1992 {
1993 unsigned int nPhys = m_stdExp->GetTotPoints();
1994 unsigned int ntot = m_numElmt * nPhys;
1995 unsigned int nmodes = m_stdExp->GetNcoeffs();
1996 unsigned int nmax = max(ntot, m_numElmt * nmodes);
1998 Array<OneD, NekDouble> output, wsp1;
2000
2001 in[0] = entry0;
2002 in[1] = entry1;
2003 in[2] = entry2;
2004
2005 output = entry3;
2006
2007 for (int i = 0; i < 3; ++i)
2008 {
2009 tmp[i] = wsp + i * nmax;
2010 }
2011
2012 if (m_isDeformed)
2013 {
2014 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
2015 for (int i = 0; i < 3; ++i)
2016 {
2017 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
2018 for (int j = 1; j < 3; ++j)
2019 {
2020 Vmath::Vvtvp(ntot, m_derivFac[i + 3 * j], 1, in[j], 1,
2021 tmp[i], 1, tmp[i], 1);
2022 }
2023 }
2024 }
2025 else
2026 {
2028 for (int e = 0; e < m_numElmt; ++e)
2029 {
2030 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
2031 for (int i = 0; i < 3; ++i)
2032 {
2033 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
2034 t = tmp[i] + e * m_nqe, 1);
2035 for (int j = 1; j < 3; ++j)
2036 {
2037 Vmath::Svtvp(m_nqe, m_derivFac[i + 3 * j][e],
2038 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
2039 1, t = tmp[i] + e * m_nqe, 1);
2040 }
2041 }
2042 }
2043 }
2044
2045 wsp1 = wsp + 3 * nmax;
2046
2047 // Sort into eta factors
2048 for (int i = 0; i < m_numElmt; ++i)
2049 {
2050 // scale tmp[0] by fac0
2051 Vmath::Vmul(nPhys, &m_fac0[0], 1, tmp[0].get() + i * nPhys, 1,
2052 tmp[0].get() + i * nPhys, 1);
2053
2054 // scale tmp[2] by fac1 and add to tmp0
2055 Vmath::Vvtvp(nPhys, &m_fac1[0], 1, tmp[2].get() + i * nPhys, 1,
2056 tmp[0].get() + i * nPhys, 1, tmp[0].get() + i * nPhys,
2057 1);
2058
2059 // scale tmp[1] by fac0
2060 Vmath::Vmul(nPhys, &m_fac0[0], 1, tmp[1].get() + i * nPhys, 1,
2061 tmp[1].get() + i * nPhys, 1);
2062
2063 // scale tmp[2] by fac2 and add to tmp1
2064 Vmath::Vvtvp(nPhys, &m_fac2[0], 1, tmp[2].get() + i * nPhys, 1,
2065 tmp[1].get() + i * nPhys, 1, tmp[1].get() + i * nPhys,
2066 1);
2067 }
2068
2069 // calculate Iproduct WRT Std Deriv
2072 m_base2, m_jacWStdW, tmp[0], output, wsp1);
2073
2076 m_base2, m_jacWStdW, tmp[1], tmp[0], wsp1);
2077 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
2078
2081 m_derbase2, m_jacWStdW, tmp[2], tmp[0], wsp1);
2082 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
2083 }
2084
2085 void operator()(int dir, const Array<OneD, const NekDouble> &input,
2086 Array<OneD, NekDouble> &output,
2087 Array<OneD, NekDouble> &wsp) override final
2088 {
2089 boost::ignore_unused(dir, input, output, wsp);
2090 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
2091 }
2092
2094 int coll_phys_offset) override
2095 {
2096 boost::ignore_unused(factors, coll_phys_offset);
2097 ASSERTL0(false, "Not valid for this operator.");
2098 }
2099
2100protected:
2101 const int m_nquad0;
2102 const int m_nquad1;
2103 const int m_nquad2;
2104 const int m_nmodes0;
2105 const int m_nmodes1;
2106 const int m_nmodes2;
2119
2120private:
2122 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
2124 : Operator(pCollExp, pGeomData, factors),
2125 m_nquad0(m_stdExp->GetNumPoints(0)),
2126 m_nquad1(m_stdExp->GetNumPoints(1)),
2127 m_nquad2(m_stdExp->GetNumPoints(2)),
2128 m_nmodes0(m_stdExp->GetBasisNumModes(0)),
2129 m_nmodes1(m_stdExp->GetBasisNumModes(1)),
2130 m_nmodes2(m_stdExp->GetBasisNumModes(2)),
2131 m_base0(m_stdExp->GetBasis(0)->GetBdata()),
2132 m_base1(m_stdExp->GetBasis(1)->GetBdata()),
2133 m_base2(m_stdExp->GetBasis(2)->GetBdata()),
2134 m_derbase0(m_stdExp->GetBasis(0)->GetDbdata()),
2135 m_derbase1(m_stdExp->GetBasis(1)->GetDbdata()),
2136 m_derbase2(m_stdExp->GetBasis(2)->GetDbdata())
2137
2138 {
2139 m_jacWStdW = pGeomData->GetJacWithStdWeights(pCollExp);
2140 m_wspSize = 6 * m_numElmt *
2141 (max(m_nquad0 * m_nquad1 * m_nquad2,
2143 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
2144
2145 if (m_stdExp->GetBasis(0)->GetBasisType() == LibUtilities::eModified_A)
2146 {
2147 m_sortTopVertex = true;
2148 }
2149 else
2150 {
2151 m_sortTopVertex = false;
2152 }
2153
2154 const Array<OneD, const NekDouble> &z0 = m_stdExp->GetBasis(0)->GetZ();
2155 const Array<OneD, const NekDouble> &z1 = m_stdExp->GetBasis(1)->GetZ();
2156 const Array<OneD, const NekDouble> &z2 = m_stdExp->GetBasis(2)->GetZ();
2157
2161
2162 for (int i = 0; i < m_nquad0; ++i)
2163 {
2164 for (int j = 0; j < m_nquad1; ++j)
2165 {
2166 for (int k = 0; k < m_nquad2; ++k)
2167 {
2168 // set up geometric factor: 2/(1-z2)
2169 m_fac0[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
2170 2.0 / (1 - z2[k]);
2171 // set up geometric factor: (1+z0)/(1-z2)
2172 m_fac1[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
2173 (1 + z0[i]) / (1 - z2[k]);
2174 // set up geometric factor: (1+z1)/(1-z2)
2175 m_fac2[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
2176 (1 + z1[j]) / (1 - z2[k]);
2177 }
2178 }
2179 }
2180 }
2181};
2182
2183/// Factory initialisation for the IProductWRTDerivBase_SumFac_Pyr operator
2184OperatorKey IProductWRTDerivBase_SumFac_Pyr::m_type =
2187 IProductWRTDerivBase_SumFac_Pyr::create,
2188 "IProductWRTDerivBase_SumFac_Pyr");
2189
2190} // namespace Collections
2191} // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:209
#define OPERATOR_CREATE(cname)
Definition: Operator.h:45
Inner product WRT deriv base operator using element-wise operation.
void operator()(int dir, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp) override final
IProductWRTDerivBase_IterPerExp(vector< StdRegions::StdExpansionSharedPtr > pCollExp, CoalescedGeomDataSharedPtr pGeomData, StdRegions::FactorMap factors)
virtual void CheckFactors(StdRegions::FactorMap factors, int coll_phys_offset) override
Check the validity of the supplied factor map.
void operator()(const Array< OneD, const NekDouble > &entry0, Array< OneD, NekDouble > &entry1, Array< OneD, NekDouble > &entry2, Array< OneD, NekDouble > &entry3, Array< OneD, NekDouble > &wsp) override final
Perform operation.
Inner product operator using operator using matrix free operators.
IProductWRTDerivBase_MatrixFree(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) override final
void operator()(const Array< OneD, const NekDouble > &entry0, Array< OneD, NekDouble > &entry1, Array< OneD, NekDouble > &entry2, Array< OneD, NekDouble > &entry3, Array< OneD, NekDouble > &wsp) override final
Perform operation.
std::shared_ptr< MatrixFree::IProductWRTDerivBase > m_oper
virtual void CheckFactors(StdRegions::FactorMap factors, int coll_phys_offset) override
Check the validity of the supplied factor map.
Inner product WRT deriv base operator using LocalRegions implementation.
vector< StdRegions::StdExpansionSharedPtr > m_expList
IProductWRTDerivBase_NoCollection(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) override final
virtual void CheckFactors(StdRegions::FactorMap factors, int coll_phys_offset) override
Check the validity of the supplied factor map.
void operator()(const Array< OneD, const NekDouble > &entry0, Array< OneD, NekDouble > &entry1, Array< OneD, NekDouble > &entry2, Array< OneD, NekDouble > &entry3, Array< OneD, NekDouble > &wsp) override final
Perform operation.
Inner product WRT deriv base operator using standard matrix approach.
void operator()(const Array< OneD, const NekDouble > &entry0, Array< OneD, NekDouble > &entry1, Array< OneD, NekDouble > &entry2, Array< OneD, NekDouble > &entry3, Array< OneD, NekDouble > &wsp) override final
Perform operation.
void operator()(int dir, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp) override final
virtual void CheckFactors(StdRegions::FactorMap factors, int coll_phys_offset) override
Check the validity of the supplied factor map.
IProductWRTDerivBase_StdMat(vector< StdRegions::StdExpansionSharedPtr > pCollExp, CoalescedGeomDataSharedPtr pGeomData, StdRegions::FactorMap factors)
Inner product WRT deriv base operator using sum-factorisation (Hex)
virtual void CheckFactors(StdRegions::FactorMap factors, int coll_phys_offset) override
Check the validity of the supplied factor map.
IProductWRTDerivBase_SumFac_Hex(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) override final
void operator()(const Array< OneD, const NekDouble > &entry0, Array< OneD, NekDouble > &entry1, Array< OneD, NekDouble > &entry2, Array< OneD, NekDouble > &entry3, Array< OneD, NekDouble > &wsp) override final
Perform operation.
Inner product WRT deriv base operator using sum-factorisation (Prism)
virtual void CheckFactors(StdRegions::FactorMap factors, int coll_phys_offset) override
Check the validity of the supplied factor map.
void operator()(int dir, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp) override final
void operator()(const Array< OneD, const NekDouble > &entry0, Array< OneD, NekDouble > &entry1, Array< OneD, NekDouble > &entry2, Array< OneD, NekDouble > &entry3, Array< OneD, NekDouble > &wsp) override final
IProductWRTDerivBase_SumFac_Prism(vector< StdRegions::StdExpansionSharedPtr > pCollExp, CoalescedGeomDataSharedPtr pGeomData, StdRegions::FactorMap factors)
Inner product WRT deriv base operator using sum-factorisation (Pyr)
void operator()(const Array< OneD, const NekDouble > &entry0, Array< OneD, NekDouble > &entry1, Array< OneD, NekDouble > &entry2, Array< OneD, NekDouble > &entry3, Array< OneD, NekDouble > &wsp) override final
virtual void CheckFactors(StdRegions::FactorMap factors, int coll_phys_offset) override
Check the validity of the supplied factor map.
void operator()(int dir, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp) override 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) override final
virtual void CheckFactors(StdRegions::FactorMap factors, int coll_phys_offset) override
Check the validity of the supplied factor map.
void operator()(const Array< OneD, const NekDouble > &entry0, Array< OneD, NekDouble > &entry1, Array< OneD, NekDouble > &entry2, Array< OneD, NekDouble > &entry3, Array< OneD, NekDouble > &wsp) override final
Perform operation.
IProductWRTDerivBase_SumFac_Quad(vector< StdRegions::StdExpansionSharedPtr > pCollExp, CoalescedGeomDataSharedPtr pGeomData, StdRegions::FactorMap factors)
Inner product WRT deriv base operator using sum-factorisation (Segment)
void operator()(const Array< OneD, const NekDouble > &entry0, Array< OneD, NekDouble > &entry1, Array< OneD, NekDouble > &entry2, Array< OneD, NekDouble > &entry3, Array< OneD, NekDouble > &wsp) override final
Perform operation.
void operator()(int dir, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp) override final
virtual void CheckFactors(StdRegions::FactorMap factors, int coll_phys_offset) override
Check the validity of the supplied factor map.
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) override final
virtual void CheckFactors(StdRegions::FactorMap factors, int coll_phys_offset) override
Check the validity of the supplied factor map.
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) override final
void operator()(const Array< OneD, const NekDouble > &entry0, Array< OneD, NekDouble > &entry1, Array< OneD, NekDouble > &entry2, Array< OneD, NekDouble > &entry3, Array< OneD, NekDouble > &wsp) override final
virtual void CheckFactors(StdRegions::FactorMap factors, int coll_phys_offset) override
Check the validity of the supplied factor map.
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:119
StdRegions::StdExpansionSharedPtr m_stdExp
Definition: Operator.h:165
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:198
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
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:385
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:500
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:409
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:131
std::tuple< LibUtilities::ShapeType, OperatorType, ImplementationType, ExpansionIsNodal > OperatorKey
Key for describing an Operator.
Definition: Operator.h:177
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:48
std::shared_ptr< CoalescedGeomData > CoalescedGeomDataSharedPtr
OperatorFactory & GetOperatorFactory()
Returns the singleton Operator factory object.
Definition: Operator.cpp:117
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:342
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:173
std::vector< PointsKey > PointsKeyVector
Definition: Points.h:236
@ eModified_A
Principle Modified Functions .
Definition: BasisType.h:50
ConstFactorMap FactorMap
Definition: StdRegions.hpp:412
StdRegions::ConstFactorMap factors
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
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.cpp:207
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.cpp:617
void Vvtvp(int n, const T *w, const int incw, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
vvtvp (vector times vector plus vector): z = w*x + y
Definition: Vmath.cpp:569
void Vadd(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Add vector z = x+y.
Definition: Vmath.cpp:354
void Smul(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha*x.
Definition: Vmath.cpp:245
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:487
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1191