Nektar++
Loading...
Searching...
No Matches
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
56
57/**
58 * @brief Inner product deriv base help class to calculate the size of the
59 * collection that is given as an input and as an output to the
60 * IProductWRTDerivBase Operator. The size evaluation takes into account the
61 * conversion from the physical space to the coefficient space.
62 */
64{
65protected:
67 {
68 // expect input to be number of elements by the number of quad points
69 m_inputSize = m_numElmt * m_stdExp->GetTotPoints();
70 // expect input to be number of elements by the number of coefficients
71 m_outputSize = m_numElmt * m_stdExp->GetNcoeffs();
72 }
73};
74
75/**
76 * @brief Inner product WRT deriv base operator using standard matrix approach
77 */
78class IProductWRTDerivBase_StdMat final : virtual public Operator,
80{
81public:
83
85
86 void operator()(const Array<OneD, const NekDouble> &entry0,
87 Array<OneD, NekDouble> &entry1,
88 Array<OneD, NekDouble> &entry2,
89 Array<OneD, NekDouble> &entry3,
90 Array<OneD, NekDouble> &wsp) final
91 {
92 int nPhys = m_stdExp->GetTotPoints();
93 int ntot = m_numElmt * nPhys;
94 int nmodes = m_stdExp->GetNcoeffs();
98
99 in[0] = entry0;
100 in[1] = entry1;
101 in[2] = entry2;
102
103 output = (m_coordim == 3) ? entry3 : (m_coordim == 2) ? entry2 : entry1;
104
105 for (int i = 0; i < m_dim; ++i)
106 {
107 tmp[i] = wsp + i * ntot;
108 }
109
110 // calculate Iproduct WRT Std Deriv
111
112 // First component
113 if (m_isDeformed)
114 {
115 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
116 for (int i = 0; i < m_dim; ++i)
117 {
118 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
119 for (int j = 1; j < m_coordim; ++j)
120 {
121 Vmath::Vvtvp(ntot, m_derivFac[i + j * m_dim], 1, in[j], 1,
122 tmp[i], 1, tmp[i], 1);
123 }
124 }
125
126 Vmath::Vmul(ntot, m_jac, 1, tmp[0], 1, tmp[0], 1);
127 }
128 else
129 {
131 for (int e = 0; e < m_numElmt; ++e)
132 {
133 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
134 for (int i = 0; i < m_dim; ++i)
135 {
136 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
137 t = tmp[i] + e * m_nqe, 1);
138 for (int j = 1; j < m_coordim; ++j)
139 {
140 Vmath::Svtvp(m_nqe, m_derivFac[i + j * m_dim][e],
141 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
142 1, t = tmp[i] + e * m_nqe, 1);
143 }
144 }
145
146 Vmath::Smul(m_nqe, m_jac[e], tmp[0] + e * m_nqe, 1,
147 t = tmp[0] + e * m_nqe, 1);
148 }
149 }
150
151 Blas::Dgemm('N', 'N', m_iProdWRTStdDBase[0]->GetRows(), m_numElmt,
152 m_iProdWRTStdDBase[0]->GetColumns(), 1.0,
153 m_iProdWRTStdDBase[0]->GetRawPtr(),
154 m_iProdWRTStdDBase[0]->GetRows(), tmp[0].data(), nPhys, 0.0,
155 output.data(), nmodes);
156
157 // Other components
158 for (int i = 1; i < m_dim; ++i)
159 {
160 if (m_isDeformed)
161 {
162 Vmath::Vmul(ntot, m_jac, 1, tmp[i], 1, tmp[i], 1);
163 }
164 else
165 {
167 for (int e = 0; e < m_numElmt; ++e)
168 {
169 Vmath::Smul(m_nqe, m_jac[e], tmp[i] + e * m_nqe, 1,
170 t = tmp[i] + e * m_nqe, 1);
171 }
172 }
173 Blas::Dgemm('N', 'N', m_iProdWRTStdDBase[i]->GetRows(), m_numElmt,
174 m_iProdWRTStdDBase[i]->GetColumns(), 1.0,
175 m_iProdWRTStdDBase[i]->GetRawPtr(),
176 m_iProdWRTStdDBase[i]->GetRows(), tmp[i].data(), nPhys,
177 1.0, output.data(), nmodes);
178 }
179 }
180
181 void operator()([[maybe_unused]] int dir,
182 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
183 [[maybe_unused]] Array<OneD, NekDouble> &output,
184 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
185 {
186 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
187 }
188
189protected:
193 int m_dim;
195
196private:
198 vector<LocalRegions::ExpansionSharedPtr> pCollExp,
200 : Operator(pCollExp, pGeomData, factors), IProductWRTDerivBase_Helper()
201 {
202 m_dim = pCollExp[0]->GetShapeDimension();
203 m_coordim = pCollExp[0]->GetCoordim();
204
205 m_nqe = m_stdExp->GetTotPoints();
206 int nmodes = m_stdExp->GetNcoeffs();
207
208 // set up a IProductWRTDerivBase StdMat.
210 for (int i = 0; i < m_dim; ++i)
211 {
212 Array<OneD, NekDouble> tmp(m_nqe), tmp1(nmodes);
215 for (int j = 0; j < m_nqe; ++j)
216 {
217 Vmath::Zero(m_nqe, tmp, 1);
218 tmp[j] = 1.0;
219 m_stdExp->IProductWRTDerivBase(i, tmp, tmp1);
220 Vmath::Vcopy(nmodes, &tmp1[0], 1,
221 &(m_iProdWRTStdDBase[i]->GetPtr())[0] + j * nmodes,
222 1);
223 }
224 }
225 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
226 m_jac = pGeomData->GetJac(pCollExp);
228 }
229};
230
231/// Factory initialisation for the IProductWRTDerivBase_StdMat operators
232OperatorKey IProductWRTDerivBase_StdMat::m_typeArr[] = {
234 OperatorKey(eSegment, eIProductWRTDerivBase, eStdMat, false),
235 IProductWRTDerivBase_StdMat::create, "IProductWRTDerivBase_StdMat_Seg"),
237 OperatorKey(eTriangle, eIProductWRTDerivBase, eStdMat, false),
238 IProductWRTDerivBase_StdMat::create, "IProductWRTDerivBase_StdMat_Tri"),
240 OperatorKey(eNodalTri, eIProductWRTDerivBase, eStdMat, true),
241 IProductWRTDerivBase_StdMat::create,
242 "IProductWRTDerivBase_StdMat_NodalTri"),
244 OperatorKey(eQuadrilateral, eIProductWRTDerivBase, eStdMat, false),
245 IProductWRTDerivBase_StdMat::create,
246 "IProductWRTDerivBase_StdMat_Quad"),
248 OperatorKey(eTetrahedron, eIProductWRTDerivBase, eStdMat, false),
249 IProductWRTDerivBase_StdMat::create, "IProductWRTDerivBase_StdMat_Tet"),
251 OperatorKey(eNodalTet, eIProductWRTDerivBase, eStdMat, true),
252 IProductWRTDerivBase_StdMat::create,
253 "IProductWRTDerivBase_StdMat_NodalTet"),
255 OperatorKey(ePyramid, eIProductWRTDerivBase, eStdMat, false),
256 IProductWRTDerivBase_StdMat::create, "IProductWRTDerivBase_StdMat_Pyr"),
259 IProductWRTDerivBase_StdMat::create,
260 "IProductWRTDerivBase_StdMat_Prism"),
262 OperatorKey(eNodalPrism, eIProductWRTDerivBase, eStdMat, true),
263 IProductWRTDerivBase_StdMat::create,
264 "IProductWRTDerivBase_StdMat_NodalPrism"),
266 OperatorKey(eHexahedron, eIProductWRTDerivBase, eStdMat, false),
267 IProductWRTDerivBase_StdMat::create, "IProductWRTDerivBase_StdMat_Hex"),
269 OperatorKey(ePyramid, eIProductWRTDerivBase, eSumFac, false),
270 IProductWRTDerivBase_StdMat::create,
271 "IProductWRTDerivBase_SumFac_Pyr")};
272
273/**
274 * @brief Inner product operator using operator using matrix free operators.
275 */
276class IProductWRTDerivBase_MatrixFree final : virtual public Operator,
279{
280public:
282
284
285 void operator()(const Array<OneD, const NekDouble> &entry0,
286 Array<OneD, NekDouble> &entry1,
287 Array<OneD, NekDouble> &entry2,
288 Array<OneD, NekDouble> &entry3,
289 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
290 {
293
294 // copy into padded vector
295 switch (m_coordim)
296 {
297 case 1:
298 input[0] = entry0;
299 output = entry1;
300 break;
301 case 2:
302 input[0] = entry0;
303 input[1] = entry1;
304 output = entry2;
305 break;
306 case 3:
307 input[0] = entry0;
308 input[1] = entry1;
309 input[2] = entry2;
310 output = entry3;
311 break;
312 default:
313 NEKERROR(ErrorUtil::efatal, "coordim not valid");
314 break;
315 }
316
317 (*m_oper)(input, output);
318 }
319
320 void operator()([[maybe_unused]] int dir,
321 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
322 [[maybe_unused]] Array<OneD, NekDouble> &output,
323 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
324 {
325 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
326 }
327
328private:
329 std::shared_ptr<MatrixFree::IProductWRTDerivBase> m_oper;
331
333 vector<LocalRegions::ExpansionSharedPtr> pCollExp,
335 : Operator(pCollExp, pGeomData, factors),
336 MatrixFreeBase(pCollExp[0]->GetTotPoints(), pCollExp[0]->GetNcoeffs(),
337 pCollExp.size()),
339 {
340 const auto dim = pCollExp[0]->GetShapeDimension();
341 m_coordim = pCollExp[0]->GetCoordim();
342
343 // Basis vector
344 std::vector<LibUtilities::BasisSharedPtr> basis(dim);
345 for (unsigned int i = 0; i < dim; ++i)
346 {
347 basis[i] = pCollExp[0]->GetBasis(i);
348 }
349
350 // Get shape type
351 auto shapeType = pCollExp[0]->DetShapeType();
352
353 // Generate operator string and create operator.
354 std::string op_string = "IProductWRTDerivBase";
355 op_string += MatrixFree::GetOpstring(shapeType, m_isDeformed);
356 auto oper = MatrixFree::GetOperatorFactory().CreateInstance(
357 op_string, basis, pCollExp.size());
358
359 // set up required copies for operations
360 oper->SetUpBdata(basis);
361 oper->SetUpDBdata(basis);
362 oper->SetUpZW(basis);
363
364 // Set Jacobian
365 oper->SetJac(pGeomData->GetJacInterLeave(pCollExp, m_nElmtPad));
366
367 // Set derivative factors
368 oper->SetDF(pGeomData->GetDerivFactorsInterLeave(pCollExp, m_nElmtPad));
369
370 m_oper =
371 std::dynamic_pointer_cast<MatrixFree::IProductWRTDerivBase>(oper);
372 ASSERTL0(m_oper, "Failed to cast pointer.");
373 }
374};
375
376/// Factory initialisation for the IProductWRTDerivBase_MatrixFree operators
377OperatorKey IProductWRTDerivBase_MatrixFree::m_typeArr[] = {
380 IProductWRTDerivBase_MatrixFree::create,
381 "IProductWRTDerivBase_MatrixFree_Seg"),
383 OperatorKey(eQuadrilateral, eIProductWRTDerivBase, eMatrixFree, false),
384 IProductWRTDerivBase_MatrixFree::create,
385 "IProductWRTDerivBase_MatrixFree_Quad"),
388 IProductWRTDerivBase_MatrixFree::create,
389 "IProductWRTDerivBase_MatrixFree_Tri"),
391 OperatorKey(eHexahedron, eIProductWRTDerivBase, eMatrixFree, false),
392 IProductWRTDerivBase_MatrixFree::create,
393 "IProductWRTDerivBase_MatrixFree_Hex"),
396 IProductWRTDerivBase_MatrixFree::create,
397 "IProductWRTDerivBase_MatrixFree_Prism"),
400 IProductWRTDerivBase_MatrixFree::create,
401 "IProductWRTDerivBase_MatrixFree_Pyr"),
403 OperatorKey(eTetrahedron, eIProductWRTDerivBase, eMatrixFree, false),
404 IProductWRTDerivBase_MatrixFree::create,
405 "IProductWRTDerivBase_MatrixFree_Tet")};
406
407/**
408 * @brief Inner product WRT deriv base operator using element-wise operation
409 */
410class IProductWRTDerivBase_IterPerExp final : virtual public Operator,
412{
413public:
415
417
418 void operator()(const Array<OneD, const NekDouble> &entry0,
419 Array<OneD, NekDouble> &entry1,
420 Array<OneD, NekDouble> &entry2,
421 Array<OneD, NekDouble> &entry3,
422 Array<OneD, NekDouble> &wsp) final
423 {
424 unsigned int nPhys = m_stdExp->GetTotPoints();
425 unsigned int ntot = m_numElmt * nPhys;
426 unsigned int nmodes = m_stdExp->GetNcoeffs();
427 unsigned int nmax = max(ntot, m_numElmt * nmodes);
429 Array<OneD, NekDouble> output, tmp1;
431
432 in[0] = entry0;
433 in[1] = entry1;
434 in[2] = entry2;
435
436 output = (m_coordim == 3) ? entry3 : (m_coordim == 2) ? entry2 : entry1;
437
438 for (int i = 0; i < m_dim; ++i)
439 {
440 tmp[i] = wsp + i * nmax;
441 }
442
443 // calculate Iproduct WRT Std Deriv
444 // first component
445 if (m_isDeformed)
446 {
447 // calculate dx/dxi in[0] + dy/dxi in[2] + dz/dxi in[3]
448 for (int i = 0; i < m_dim; ++i)
449 {
450 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
451 for (int j = 1; j < m_coordim; ++j)
452 {
453 Vmath::Vvtvp(ntot, m_derivFac[i + j * m_dim], 1, in[j], 1,
454 tmp[i], 1, tmp[i], 1);
455 }
456 }
457
458 Vmath::Vmul(ntot, m_jac, 1, tmp[0], 1, tmp[0], 1);
459 }
460 else
461 {
463 for (int e = 0; e < m_numElmt; ++e)
464 {
465 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
466 for (int i = 0; i < m_dim; ++i)
467 {
468 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
469 t = tmp[i] + e * m_nqe, 1);
470 for (int j = 1; j < m_coordim; ++j)
471 {
472 Vmath::Svtvp(m_nqe, m_derivFac[i + j * m_dim][e],
473 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
474 1, t = tmp[i] + e * m_nqe, 1);
475 }
476 }
477
478 Vmath::Smul(m_nqe, m_jac[e], tmp[0] + e * m_nqe, 1,
479 t = tmp[0] + e * m_nqe, 1);
480 }
481 }
482
483 for (int n = 0; n < m_numElmt; ++n)
484 {
485 m_stdExp->IProductWRTDerivBase(0, tmp[0] + n * nPhys,
486 tmp1 = output + n * nmodes);
487 }
488
489 // other components
490 for (int i = 1; i < m_dim; ++i)
491 {
492 // multiply by Jacobian
493 if (m_isDeformed)
494 {
495 Vmath::Vmul(ntot, m_jac, 1, tmp[i], 1, tmp[i], 1);
496 }
497 else
498 {
500 for (int e = 0; e < m_numElmt; ++e)
501 {
502 Vmath::Smul(m_nqe, m_jac[e], tmp[i] + e * m_nqe, 1,
503 t = tmp[i] + e * m_nqe, 1);
504 }
505 }
506
507 for (int n = 0; n < m_numElmt; ++n)
508 {
509 m_stdExp->IProductWRTDerivBase(i, tmp[i] + n * nPhys, tmp[0]);
510 Vmath::Vadd(nmodes, tmp[0], 1, output + n * nmodes, 1,
511 tmp1 = output + n * nmodes, 1);
512 }
513 }
514 }
515
516 void operator()([[maybe_unused]] int dir,
517 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
518 [[maybe_unused]] Array<OneD, NekDouble> &output,
519 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
520 {
521 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
522 }
523
524protected:
527 int m_dim;
529
530private:
532 vector<LocalRegions::ExpansionSharedPtr> pCollExp,
534 : Operator(pCollExp, pGeomData, factors), IProductWRTDerivBase_Helper()
535 {
536 m_dim = pCollExp[0]->GetShapeDimension();
537 m_coordim = pCollExp[0]->GetCoordim();
538
539 m_nqe = m_stdExp->GetTotPoints();
540
541 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
542 m_jac = pGeomData->GetJac(pCollExp);
544 }
545};
546
547/// Factory initialisation for the IProductWRTDerivBase_IterPerExp operators
548OperatorKey IProductWRTDerivBase_IterPerExp::m_typeArr[] = {
551 IProductWRTDerivBase_IterPerExp::create,
552 "IProductWRTDerivBase_IterPerExp_Seg"),
555 IProductWRTDerivBase_IterPerExp::create,
556 "IProductWRTDerivBase_IterPerExp_Tri"),
559 IProductWRTDerivBase_IterPerExp::create,
560 "IProductWRTDerivBase_IterPerExp_NodalTri"),
562 OperatorKey(eQuadrilateral, eIProductWRTDerivBase, eIterPerExp, false),
563 IProductWRTDerivBase_IterPerExp::create,
564 "IProductWRTDerivBase_IterPerExp_Quad"),
566 OperatorKey(eTetrahedron, eIProductWRTDerivBase, eIterPerExp, false),
567 IProductWRTDerivBase_IterPerExp::create,
568 "IProductWRTDerivBase_IterPerExp_Tet"),
571 IProductWRTDerivBase_IterPerExp::create,
572 "IProductWRTDerivBase_IterPerExp_NodalTet"),
575 IProductWRTDerivBase_IterPerExp::create,
576 "IProductWRTDerivBase_IterPerExp_Pyr"),
579 IProductWRTDerivBase_IterPerExp::create,
580 "IProductWRTDerivBase_IterPerExp_Prism"),
582 OperatorKey(eNodalPrism, eIProductWRTDerivBase, eIterPerExp, true),
583 IProductWRTDerivBase_IterPerExp::create,
584 "IProductWRTDerivBase_IterPerExp_NodalPrism"),
586 OperatorKey(eHexahedron, eIProductWRTDerivBase, eIterPerExp, false),
587 IProductWRTDerivBase_IterPerExp::create,
588 "IProductWRTDerivBase_IterPerExp_Hex")};
589
590/**
591 * @brief Inner product WRT deriv base operator using LocalRegions
592 * implementation.
593 */
594class IProductWRTDerivBase_NoCollection final : virtual public Operator,
596{
597public:
599
601
602 void operator()(const Array<OneD, const NekDouble> &entry0,
603 Array<OneD, NekDouble> &entry1,
604 Array<OneD, NekDouble> &entry2,
605 Array<OneD, NekDouble> &entry3,
606 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
607 {
608 unsigned int nmodes = m_expList[0]->GetNcoeffs();
609 unsigned int nPhys = m_expList[0]->GetTotPoints();
610 Array<OneD, NekDouble> tmp(nmodes), tmp1;
611
614 in[0] = entry0;
615 in[1] = entry1;
616 in[2] = entry2;
617
618 output = (m_coordim == 3) ? entry3 : (m_coordim == 2) ? entry2 : entry1;
619
620 for (int n = 0; n < m_numElmt; ++n)
621 {
622 m_expList[n]->IProductWRTDerivBase(0, in[0] + n * nPhys,
623 tmp1 = output + n * nmodes);
624 }
625
626 for (int i = 1; i < m_coordim; ++i)
627 {
628 for (int n = 0; n < m_numElmt; ++n)
629 {
630 m_expList[n]->IProductWRTDerivBase(i, in[i] + n * nPhys, tmp);
631
632 Vmath::Vadd(nmodes, tmp, 1, output + n * nmodes, 1,
633 tmp1 = output + n * nmodes, 1);
634 }
635 }
636 }
637
638 void operator()([[maybe_unused]] int dir,
639 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
640 [[maybe_unused]] Array<OneD, NekDouble> &output,
641 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
642 {
643 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
644 }
645
646protected:
647 int m_dim;
649 vector<LocalRegions::ExpansionSharedPtr> m_expList;
650
651private:
653 vector<LocalRegions::ExpansionSharedPtr> pCollExp,
655 : Operator(pCollExp, pGeomData, factors), IProductWRTDerivBase_Helper()
656 {
657 m_expList = pCollExp;
658 m_dim = pCollExp[0]->GetNumBases();
659 m_coordim = pCollExp[0]->GetCoordim();
660 }
661};
662
663/// Factory initialisation for the IProductWRTDerivBase_NoCollection operators
664OperatorKey IProductWRTDerivBase_NoCollection::m_typeArr[] = {
667 IProductWRTDerivBase_NoCollection::create,
668 "IProductWRTDerivBase_NoCollection_Seg"),
671 IProductWRTDerivBase_NoCollection::create,
672 "IProductWRTDerivBase_NoCollection_Tri"),
675 IProductWRTDerivBase_NoCollection::create,
676 "IProductWRTDerivBase_NoCollection_NodalTri"),
679 false),
680 IProductWRTDerivBase_NoCollection::create,
681 "IProductWRTDerivBase_NoCollection_Quad"),
683 OperatorKey(eTetrahedron, eIProductWRTDerivBase, eNoCollection, false),
684 IProductWRTDerivBase_NoCollection::create,
685 "IProductWRTDerivBase_NoCollection_Tet"),
688 IProductWRTDerivBase_NoCollection::create,
689 "IProductWRTDerivBase_NoCollection_NodalTet"),
692 IProductWRTDerivBase_NoCollection::create,
693 "IProductWRTDerivBase_NoCollection_Pyr"),
696 IProductWRTDerivBase_NoCollection::create,
697 "IProductWRTDerivBase_NoCollection_Prism"),
700 IProductWRTDerivBase_NoCollection::create,
701 "IProductWRTDerivBase_NoCollection_NodalPrism"),
703 OperatorKey(eHexahedron, eIProductWRTDerivBase, eNoCollection, false),
704 IProductWRTDerivBase_NoCollection::create,
705 "IProductWRTDerivBase_NoCollection_Hex")};
706
707/**
708 * @brief Inner product WRT deriv base operator using sum-factorisation
709 * (Segment)
710 */
711class IProductWRTDerivBase_SumFac_Seg final : virtual public Operator,
713{
714public:
716
718
719 void operator()(const Array<OneD, const NekDouble> &entry0,
720 Array<OneD, NekDouble> &entry1,
721 Array<OneD, NekDouble> &entry2,
722 Array<OneD, NekDouble> &entry3,
723 Array<OneD, NekDouble> &wsp) final
724 {
727
728 output = (m_coordim == 3) ? entry3 : (m_coordim == 2) ? entry2 : entry1;
729
730 in[0] = entry0;
731 in[1] = entry1;
732 in[2] = entry2;
733
734 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
735 if (m_isDeformed)
736 {
737 Vmath::Vmul(m_wspSize, m_derivFac[0], 1, in[0], 1, wsp, 1);
738 for (int i = 1; i < m_coordim; ++i)
739 {
740 Vmath::Vvtvp(m_wspSize, m_derivFac[i], 1, in[i], 1, wsp, 1, wsp,
741 1);
742 }
743 }
744 else
745 {
747 for (int e = 0; e < m_numElmt; ++e)
748 {
749 Vmath::Smul(m_nquad0, m_derivFac[0][e], in[0] + e * m_nquad0, 1,
750 t = wsp + e * m_nquad0, 1);
751 }
752
753 for (int i = 1; i < m_coordim; ++i)
754 {
755 for (int e = 0; e < m_numElmt; ++e)
756 {
758 in[i] + e * m_nquad0, 1, wsp + e * m_nquad0, 1,
759 t = wsp + e * m_nquad0, 1);
760 }
761 }
762 }
763
764 Vmath::Vmul(m_wspSize, m_jacWStdW, 1, wsp, 1, wsp, 1);
765
766 // out = B0*in;
767 Blas::Dgemm('T', 'N', m_nmodes0, m_numElmt, m_nquad0, 1.0,
768 m_derbase0.data(), m_nquad0, &wsp[0], m_nquad0, 0.0,
769 &output[0], m_nmodes0);
770 }
771
772 void operator()([[maybe_unused]] int dir,
773 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
774 [[maybe_unused]] Array<OneD, NekDouble> &output,
775 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
776 {
777 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
778 }
779
780protected:
781 const int m_nquad0;
782 const int m_nmodes0;
787
788private:
790 vector<LocalRegions::ExpansionSharedPtr> pCollExp,
792 : Operator(pCollExp, pGeomData, factors), IProductWRTDerivBase_Helper(),
793 m_nquad0(m_stdExp->GetNumPoints(0)),
794 m_nmodes0(m_stdExp->GetBasisNumModes(0)),
795 m_derbase0(m_stdExp->GetBasis(0)->GetDbdata())
796 {
797 m_coordim = pCollExp[0]->GetCoordim();
799 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
800 m_jacWStdW = pGeomData->GetJacWithStdWeights(pCollExp);
801 }
802};
803
804/// Factory initialisation for the IProductWRTDerivBase_SumFac_Seg operator
805OperatorKey IProductWRTDerivBase_SumFac_Seg::m_type =
807 OperatorKey(eSegment, eIProductWRTDerivBase, eSumFac, false),
808 IProductWRTDerivBase_SumFac_Seg::create,
809 "IProductWRTDerivBase_SumFac_Seg");
810
811/**
812 * @brief Inner product WRT deriv base operator using sum-factorisation (Quad)
813 */
814class IProductWRTDerivBase_SumFac_Quad final : virtual public Operator,
816{
817public:
819
821
822 void operator()(const Array<OneD, const NekDouble> &entry0,
823 Array<OneD, NekDouble> &entry1,
824 Array<OneD, NekDouble> &entry2,
825 Array<OneD, NekDouble> &entry3,
826 Array<OneD, NekDouble> &wsp) final
827 {
828 unsigned int nPhys = m_stdExp->GetTotPoints();
829 unsigned int ntot = m_numElmt * nPhys;
830 unsigned int nmodes = m_stdExp->GetNcoeffs();
831 unsigned int nmax = max(ntot, m_numElmt * nmodes);
833 Array<OneD, NekDouble> output, wsp1;
835
836 in[0] = entry0;
837 in[1] = entry1;
838 in[2] = entry2;
839
840 output = (m_coordim == 2) ? entry2 : entry3;
841
842 tmp[0] = wsp;
843 tmp[1] = wsp + nmax;
844 wsp1 = wsp + 2 * nmax;
845
846 if (m_isDeformed)
847 {
848 // calculate dx/dxi in[0] + dy/dxi in[1]
849 for (int i = 0; i < 2; ++i)
850 {
851 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
852 for (int j = 1; j < m_coordim; ++j)
853 {
854 Vmath::Vvtvp(ntot, m_derivFac[i + 2 * j], 1, in[j], 1,
855 tmp[i], 1, tmp[i], 1);
856 }
857 }
858 }
859 else
860 {
862 for (int e = 0; e < m_numElmt; ++e)
863 {
864 // calculate dx/dxi in[0] + dy/dxi in[1]
865 for (int i = 0; i < 2; ++i)
866 {
867 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
868 t = tmp[i] + e * m_nqe, 1);
869 for (int j = 1; j < m_coordim; ++j)
870 {
871 Vmath::Svtvp(m_nqe, m_derivFac[i + 2 * j][e],
872 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
873 1, t = tmp[i] + e * m_nqe, 1);
874 }
875 }
876 }
877 }
878 // Iproduct wrt derivative of base 1
881 tmp[0], output, wsp1);
882
883 // Iproduct wrt derivative of base 1
886 tmp[1], tmp[0], wsp1);
887
888 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
889 }
890
891 void operator()([[maybe_unused]] int dir,
892 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
893 [[maybe_unused]] Array<OneD, NekDouble> &output,
894 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
895 {
896 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
897 }
898
899protected:
900 const int m_nquad0;
901 const int m_nquad1;
902 const int m_nmodes0;
903 const int m_nmodes1;
904 const bool m_colldir0;
905 const bool m_colldir1;
913
914private:
916 vector<LocalRegions::ExpansionSharedPtr> pCollExp,
918 : Operator(pCollExp, pGeomData, factors), IProductWRTDerivBase_Helper(),
919 m_nquad0(m_stdExp->GetNumPoints(0)),
920 m_nquad1(m_stdExp->GetNumPoints(1)),
921 m_nmodes0(m_stdExp->GetBasisNumModes(0)),
922 m_nmodes1(m_stdExp->GetBasisNumModes(1)),
923 m_colldir0(m_stdExp->GetBasis(0)->Collocation()),
924 m_colldir1(m_stdExp->GetBasis(1)->Collocation()),
925 m_base0(m_stdExp->GetBasis(0)->GetBdata()),
926 m_base1(m_stdExp->GetBasis(1)->GetBdata()),
927 m_derbase0(m_stdExp->GetBasis(0)->GetDbdata()),
928 m_derbase1(m_stdExp->GetBasis(1)->GetDbdata())
929 {
930 m_coordim = pCollExp[0]->GetCoordim();
931 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
932 m_jacWStdW = pGeomData->GetJacWithStdWeights(pCollExp);
933 m_wspSize =
935 }
936};
937
938/// Factory initialisation for the IProductWRTDerivBase_SumFac_Quad operator
939OperatorKey IProductWRTDerivBase_SumFac_Quad::m_type =
941 OperatorKey(eQuadrilateral, eIProductWRTDerivBase, eSumFac, false),
942 IProductWRTDerivBase_SumFac_Quad::create,
943 "IProductWRTDerivBase_IterPerExp_Quad");
944
945/**
946 * @brief Inner product WRT deriv base operator using sum-factorisation (Tri)
947 */
948class IProductWRTDerivBase_SumFac_Tri final : virtual public Operator,
950{
951public:
953
955
956 /**
957 * This method calculates:
958 *
959 * \f[ (d\phi/dx,in[0]) + (d\phi/dy,in[1]) \f]
960 *
961 * which can be represented in terms of local cartesian
962 * derivaties as:
963 *
964 * \f[ ((d\phi/d\xi_0\, d\xi_0/dx +
965 * d\phi/d\xi_1\, d\xi_1/dx),in[0]) + \f]
966 *
967 * \f[ ((d\phi/d\xi_0\, d\xi_0/dy +
968 * d\phi/d\xi_1\, d\xi_1/dy),in[1]) + \f]
969 *
970 * where we note that
971 *
972 * \f[ d\phi/d\xi_0 = d\phi/d\eta_0\, d\eta_0/d\xi_0 =
973 * d\phi/d\eta_0 2/(1-\eta_1) \f]
974 *
975 * \f[ d\phi/d\xi_1 = d\phi/d\eta_1\, d\eta_1/d\xi_1 +
976 * d\phi/d\eta_1\, d\eta_1/d\xi_1 = d\phi/d\eta_0 (1+\eta_0)/(1-\eta_1)
977 * + d\phi/d\eta_1 \f]
978 *
979 * and so the full inner products are
980 *
981 * \f[ (d\phi/dx,in[0]) + (dphi/dy,in[1]) =
982 * (d\phi/d\eta_0, ((2/(1-\eta_1) (d\xi_0/dx in[0] + d\xi_0/dy in[1])
983 * + (1-\eta_0)/(1-\eta_1) (d\xi_1/dx in[0]+d\xi_1/dy in[1]))
984 * + (d\phi/d\eta_1, (d\xi_1/dx in[0] + d\xi_1/dy in[1])) \f]
985 *
986 */
987 void operator()(const Array<OneD, const NekDouble> &entry0,
988 Array<OneD, NekDouble> &entry1,
989 Array<OneD, NekDouble> &entry2,
990 Array<OneD, NekDouble> &entry3,
991 Array<OneD, NekDouble> &wsp) final
992 {
993 unsigned int nPhys = m_stdExp->GetTotPoints();
994 unsigned int ntot = m_numElmt * nPhys;
995 unsigned int nmodes = m_stdExp->GetNcoeffs();
996 unsigned int nmax = max(ntot, m_numElmt * nmodes);
998 Array<OneD, NekDouble> output, wsp1;
1000
1001 in[0] = entry0;
1002 in[1] = entry1;
1003 in[2] = entry2;
1004
1005 output = (m_coordim == 2) ? entry2 : entry3;
1006
1007 tmp[0] = wsp;
1008 tmp[1] = wsp + nmax;
1009 wsp1 = wsp + 2 * nmax;
1010
1011 if (m_isDeformed)
1012 {
1013 for (int i = 0; i < 2; ++i)
1014 {
1015 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
1016 for (int j = 1; j < m_coordim; ++j)
1017 {
1018 Vmath::Vvtvp(ntot, m_derivFac[i + 2 * j], 1, in[j], 1,
1019 tmp[i], 1, tmp[i], 1);
1020 }
1021 }
1022 }
1023 else
1024 {
1026 for (int e = 0; e < m_numElmt; ++e)
1027 {
1028 // calculate dx/dxi in[0] + dy/dxi in[1]
1029 for (int i = 0; i < 2; ++i)
1030 {
1031 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
1032 t = tmp[i] + e * m_nqe, 1);
1033 for (int j = 1; j < m_coordim; ++j)
1034 {
1035 Vmath::Svtvp(m_nqe, m_derivFac[i + 2 * j][e],
1036 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
1037 1, t = tmp[i] + e * m_nqe, 1);
1038 }
1039 }
1040 }
1041 }
1042
1043 // Multiply by factor: 2/(1-z1)
1044 for (int i = 0; i < m_numElmt; ++i)
1045 {
1046 // scale tmp[0] by geometric factor: 2/(1-z1)
1047 Vmath::Vmul(nPhys, &m_fac0[0], 1, tmp[0].data() + i * nPhys, 1,
1048 tmp[0].data() + i * nPhys, 1);
1049
1050 // scale tmp[1] by geometric factor (1+z0)/(1-z1)
1051 Vmath::Vvtvp(nPhys, &m_fac1[0], 1, tmp[1].data() + i * nPhys, 1,
1052 tmp[0].data() + i * nPhys, 1,
1053 tmp[0].data() + i * nPhys, 1);
1054 }
1055
1056 // Iproduct wrt derivative of base 0
1058 m_nmodes1, m_derbase0, m_base1, m_jacWStdW, tmp[0], output,
1059 wsp1);
1060
1061 // Iproduct wrt derivative of base 1
1063 m_nmodes1, m_base0, m_derbase1, m_jacWStdW, tmp[1], tmp[0],
1064 wsp1);
1065
1066 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1067 }
1068
1069 void operator()([[maybe_unused]] int dir,
1070 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
1071 [[maybe_unused]] Array<OneD, NekDouble> &output,
1072 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
1073 {
1074 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
1075 }
1076
1077protected:
1078 const int m_nquad0;
1079 const int m_nquad1;
1080 const int m_nmodes0;
1081 const int m_nmodes1;
1082 const bool m_colldir0;
1083 const bool m_colldir1;
1094
1095private:
1097 vector<LocalRegions::ExpansionSharedPtr> pCollExp,
1099 : Operator(pCollExp, pGeomData, factors), IProductWRTDerivBase_Helper(),
1100 m_nquad0(m_stdExp->GetNumPoints(0)),
1101 m_nquad1(m_stdExp->GetNumPoints(1)),
1102 m_nmodes0(m_stdExp->GetBasisNumModes(0)),
1103 m_nmodes1(m_stdExp->GetBasisNumModes(1)),
1104 m_colldir0(m_stdExp->GetBasis(0)->Collocation()),
1105 m_colldir1(m_stdExp->GetBasis(1)->Collocation()),
1106 m_base0(m_stdExp->GetBasis(0)->GetBdata()),
1107 m_base1(m_stdExp->GetBasis(1)->GetBdata()),
1108 m_derbase0(m_stdExp->GetBasis(0)->GetDbdata()),
1109 m_derbase1(m_stdExp->GetBasis(1)->GetDbdata())
1110 {
1111 m_coordim = pCollExp[0]->GetCoordim();
1112 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
1113 m_jacWStdW = pGeomData->GetJacWithStdWeights(pCollExp);
1114 m_wspSize =
1116
1117 if (m_stdExp->GetBasis(0)->GetBasisType() == LibUtilities::eModified_A)
1118 {
1119 m_sortTopVertex = true;
1120 }
1121 else
1122 {
1123 m_sortTopVertex = false;
1124 }
1125
1126 const Array<OneD, const NekDouble> &z0 = m_stdExp->GetBasis(0)->GetZ();
1127 const Array<OneD, const NekDouble> &z1 = m_stdExp->GetBasis(1)->GetZ();
1128
1130 // set up geometric factor: 2/(1-z1)
1131 for (int i = 0; i < m_nquad0; ++i)
1132 {
1133 for (int j = 0; j < m_nquad1; ++j)
1134 {
1135 m_fac0[i + j * m_nquad0] = 2.0 / (1 - z1[j]);
1136 }
1137 }
1138
1140 // set up geometric factor: (1+z0)/(1-z1)
1141 for (int i = 0; i < m_nquad0; ++i)
1142 {
1143 for (int j = 0; j < m_nquad1; ++j)
1144 {
1145 m_fac1[i + j * m_nquad0] = (1 + z0[i]) / (1 - z1[j]);
1146 }
1147 }
1148 }
1149};
1150
1151/// Factory initialisation for the IProductWRTDerivBase_SumFac_Tri operator
1152OperatorKey IProductWRTDerivBase_SumFac_Tri::m_type =
1154 OperatorKey(eTriangle, eIProductWRTDerivBase, eSumFac, false),
1155 IProductWRTDerivBase_SumFac_Tri::create,
1156 "IProductWRTDerivBase_IterPerExp_Tri");
1157
1158/**
1159 * @brief Inner product WRT deriv base operator using sum-factorisation (Hex)
1160 */
1161class IProductWRTDerivBase_SumFac_Hex final : virtual public Operator,
1163{
1164public:
1166
1168
1169 void operator()(const Array<OneD, const NekDouble> &entry0,
1170 Array<OneD, NekDouble> &entry1,
1171 Array<OneD, NekDouble> &entry2,
1172 Array<OneD, NekDouble> &entry3,
1173 Array<OneD, NekDouble> &wsp) final
1174 {
1175 unsigned int nPhys = m_stdExp->GetTotPoints();
1176 unsigned int ntot = m_numElmt * nPhys;
1177 unsigned int nmodes = m_stdExp->GetNcoeffs();
1178 unsigned int nmax = max(ntot, m_numElmt * nmodes);
1180 Array<OneD, NekDouble> output, wsp1;
1182
1183 in[0] = entry0;
1184 in[1] = entry1;
1185 in[2] = entry2;
1186
1187 output = entry3;
1188
1189 for (int i = 0; i < 3; ++i)
1190 {
1191 tmp[i] = wsp + i * nmax;
1192 }
1193
1194 if (m_isDeformed)
1195 {
1196 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
1197 for (int i = 0; i < 3; ++i)
1198 {
1199 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
1200 for (int j = 1; j < 3; ++j)
1201 {
1202 Vmath::Vvtvp(ntot, m_derivFac[i + 3 * j], 1, in[j], 1,
1203 tmp[i], 1, tmp[i], 1);
1204 }
1205 }
1206 }
1207 else
1208 {
1210 for (int e = 0; e < m_numElmt; ++e)
1211 {
1212 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
1213 for (int i = 0; i < 3; ++i)
1214 {
1215 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
1216 t = tmp[i] + e * m_nqe, 1);
1217 for (int j = 1; j < 3; ++j)
1218 {
1219 Vmath::Svtvp(m_nqe, m_derivFac[i + 3 * j][e],
1220 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
1221 1, t = tmp[i] + e * m_nqe, 1);
1222 }
1223 }
1224 }
1225 }
1226
1227 wsp1 = wsp + 3 * nmax;
1228
1229 // calculate Iproduct WRT Std Deriv
1232 m_derbase0, m_base1, m_base2, m_jacWStdW, tmp[0], output,
1233 wsp1);
1234
1237 m_base0, m_derbase1, m_base2, m_jacWStdW, tmp[1], tmp[0],
1238 wsp1);
1239 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1240
1243 m_base0, m_base1, m_derbase2, m_jacWStdW, tmp[2], tmp[0],
1244 wsp1);
1245 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1246 }
1247
1248 void operator()([[maybe_unused]] int dir,
1249 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
1250 [[maybe_unused]] Array<OneD, NekDouble> &output,
1251 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
1252 {
1253 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
1254 }
1255
1256protected:
1257 const int m_nquad0;
1258 const int m_nquad1;
1259 const int m_nquad2;
1260 const int m_nmodes0;
1261 const int m_nmodes1;
1262 const int m_nmodes2;
1263 const bool m_colldir0;
1264 const bool m_colldir1;
1265 const bool m_colldir2;
1274
1275private:
1277 vector<LocalRegions::ExpansionSharedPtr> pCollExp,
1279 : Operator(pCollExp, pGeomData, factors), IProductWRTDerivBase_Helper(),
1280 m_nquad0(m_stdExp->GetNumPoints(0)),
1281 m_nquad1(m_stdExp->GetNumPoints(1)),
1282 m_nquad2(m_stdExp->GetNumPoints(2)),
1283 m_nmodes0(m_stdExp->GetBasisNumModes(0)),
1284 m_nmodes1(m_stdExp->GetBasisNumModes(1)),
1285 m_nmodes2(m_stdExp->GetBasisNumModes(2)),
1286 m_colldir0(m_stdExp->GetBasis(0)->Collocation()),
1287 m_colldir1(m_stdExp->GetBasis(1)->Collocation()),
1288 m_colldir2(m_stdExp->GetBasis(2)->Collocation()),
1289 m_base0(m_stdExp->GetBasis(0)->GetBdata()),
1290 m_base1(m_stdExp->GetBasis(1)->GetBdata()),
1291 m_base2(m_stdExp->GetBasis(2)->GetBdata()),
1292 m_derbase0(m_stdExp->GetBasis(0)->GetDbdata()),
1293 m_derbase1(m_stdExp->GetBasis(1)->GetDbdata()),
1294 m_derbase2(m_stdExp->GetBasis(2)->GetDbdata())
1295
1296 {
1297 m_jacWStdW = pGeomData->GetJacWithStdWeights(pCollExp);
1298 m_wspSize = 6 * m_numElmt *
1301 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
1302 }
1303};
1304
1305/// Factory initialisation for the IProductWRTDerivBase_SumFac_Hex operator
1306OperatorKey IProductWRTDerivBase_SumFac_Hex::m_type =
1308 OperatorKey(eHexahedron, eIProductWRTDerivBase, eSumFac, false),
1309 IProductWRTDerivBase_SumFac_Hex::create,
1310 "IProductWRTDerivBase_SumFac_Hex");
1311
1312/**
1313 * @brief Inner product WRT deriv base operator using sum-factorisation (Tet)
1314 */
1317{
1318public:
1320
1321 /**
1322 * This method calculates:
1323 *
1324 * \f[ (d\phi/dx,in[0]) + (d\phi/dy,in[1]) + (d\phi/dz,in[2]) \f]
1325 *
1326 * which can be represented in terms of local cartesian
1327 * derivaties as:
1328 *
1329 * \f[ ((d\phi/d\xi_0\, d\xi_0/dx +
1330 * d\phi/d\xi_1\, d\xi_1/dx +
1331 * d\phi/d\xi_2\, d\xi_2/dx),in[0]) + \f]
1332 *
1333 * \f[ ((d\phi/d\xi_0\, d\xi_0/dy +
1334 * d\phi/d\xi_1\, d\xi_1/dy +
1335 * d\phi/d\xi_2\, d\xi_2/dy),in[1]) + \f]
1336 *
1337 * \f[ ((d\phi/d\xi_0\, d\xi_0/dz +
1338 * d\phi/d\xi_1\, d\xi_1/dz +
1339 * d\phi/d\xi_2\, d\xi_2/dz),in[2]) \, \f]
1340 *
1341 * where we note that
1342 *
1343 * \f[ d\phi/d\xi_0 = d\phi/d\eta_0 4/((1-\eta_1)(1-\eta_2)) \f]
1344 *
1345 * \f[ d\phi/d\xi_1 = d\phi/d\eta_0 2(1+\eta_0)/((1-\eta_1)(1-\eta_2))
1346 * + d\phi/d\eta_1 2/(1-\eta_2) \f]
1347 *
1348 * \f[ d\phi/d\xi_2 = d\phi/d\eta_0 2(1+\eta_0)/((1-\eta_1)(1-\eta_2))
1349 * + d\phi/d\eta_1 (1+\eta_1)/(1-\eta_2) + d\phi/d\eta_2 \f]
1350 *
1351 * and so the full inner products are
1352 *
1353 * \f[ (d\phi/dx,in[0]) + (d\phi/dy,in[1]) + (d\phi/dz,in[2]) = \f]
1354 *
1355 * \f[ (d\phi/d\eta_0, fac0 (tmp0 + fac1(tmp1 + tmp2)))
1356 * + (d\phi/d\eta_1, fac2 (tmp1 + fac3 tmp2))
1357 * + (d\phi/d\eta_2, tmp2) \f]
1358 *
1359 * where
1360 *
1361 * \f[ \begin{array}{lcl}
1362 * tmp0 &=& (d\xi_0/dx in[0] + d\xi_0/dy in[1] + d\xi_0/dz in[2]) \\
1363 * tmp1 &=& (d\xi_1/dx in[0] + d\xi_1/dy in[1] + d\xi_1/dz in[2]) \\
1364 * tmp2 &=& (d\xi_2/dx in[0] + d\xi_2/dy in[1] + d\xi_2/dz in[2])
1365 * \end{array} \f]
1366 *
1367 * \f[ \begin{array}{lcl}
1368 * fac0 &= & 4/((1-\eta_1)(1-\eta_2)) \\
1369 * fac1 &= & (1+\eta_0)/2 \\
1370 * fac2 &= & 2/(1-\eta_2) \\
1371 * fac3 &= & (1+\eta_1)/2 \end{array} \f]
1372 *
1373 */
1374 void operator()(const Array<OneD, const NekDouble> &entry0,
1375 Array<OneD, NekDouble> &entry1,
1376 Array<OneD, NekDouble> &entry2,
1377 Array<OneD, NekDouble> &entry3,
1378 Array<OneD, NekDouble> &wsp) final
1379 {
1380 unsigned int nPhys = m_stdExp->GetTotPoints();
1381 unsigned int ntot = m_numElmt * nPhys;
1382 unsigned int nmodes = m_stdExp->GetNcoeffs();
1383 unsigned int nmax = max(ntot, m_numElmt * nmodes);
1385 Array<OneD, NekDouble> output, wsp1;
1387
1388 in[0] = entry0;
1389 in[1] = entry1;
1390 in[2] = entry2;
1391
1392 output = entry3;
1393
1394 for (int i = 0; i < 3; ++i)
1395 {
1396 tmp[i] = wsp + i * nmax;
1397 }
1398
1399 if (m_isDeformed)
1400 {
1401 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
1402 for (int i = 0; i < 3; ++i)
1403 {
1404 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
1405 for (int j = 1; j < 3; ++j)
1406 {
1407 Vmath::Vvtvp(ntot, m_derivFac[i + 3 * j], 1, in[j], 1,
1408 tmp[i], 1, tmp[i], 1);
1409 }
1410 }
1411 }
1412 else
1413 {
1415 for (int e = 0; e < m_numElmt; ++e)
1416 {
1417 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
1418 for (int i = 0; i < 3; ++i)
1419 {
1420 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
1421 t = tmp[i] + e * m_nqe, 1);
1422 for (int j = 1; j < 3; ++j)
1423 {
1424 Vmath::Svtvp(m_nqe, m_derivFac[i + 3 * j][e],
1425 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
1426 1, t = tmp[i] + e * m_nqe, 1);
1427 }
1428 }
1429 }
1430 }
1431
1432 wsp1 = wsp + 3 * nmax;
1433
1434 // Sort into eta factors
1435 for (int i = 0; i < m_numElmt; ++i)
1436 {
1437 // add tmp[1] + tmp[2]
1438 Vmath::Vadd(nPhys, tmp[1].data() + i * nPhys, 1,
1439 tmp[2].data() + i * nPhys, 1, wsp1.data(), 1);
1440
1441 // scale wsp1 by fac1 and add to tmp0
1442 Vmath::Vvtvp(nPhys, &m_fac1[0], 1, wsp1.data(), 1,
1443 tmp[0].data() + i * nPhys, 1,
1444 tmp[0].data() + i * nPhys, 1);
1445
1446 // scale tmp[0] by fac0
1447 Vmath::Vmul(nPhys, &m_fac0[0], 1, tmp[0].data() + i * nPhys, 1,
1448 tmp[0].data() + i * nPhys, 1);
1449
1450 // scale tmp[2] by fac3 and add to tmp1
1451 Vmath::Vvtvp(nPhys, &m_fac3[0], 1, tmp[2].data() + i * nPhys, 1,
1452 tmp[1].data() + i * nPhys, 1,
1453 tmp[1].data() + i * nPhys, 1);
1454
1455 // scale tmp[1] by fac2
1456 Vmath::Vmul(nPhys, &m_fac2[0], 1, tmp[1].data() + i * nPhys, 1,
1457 tmp[1].data() + i * nPhys, 1);
1458 }
1459
1460 // calculate Iproduct WRT Std Deriv
1463 m_base2, m_jacWStdW, tmp[0], output, wsp1);
1464
1467 m_base2, m_jacWStdW, tmp[1], tmp[0], wsp1);
1468 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1469
1472 m_derbase2, m_jacWStdW, tmp[2], tmp[0], wsp1);
1473 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1474 }
1475
1476 void operator()([[maybe_unused]] int dir,
1477 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
1478 [[maybe_unused]] Array<OneD, NekDouble> &output,
1479 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
1480 {
1481 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
1482 }
1483
1484protected:
1485 const int m_nquad0;
1486 const int m_nquad1;
1487 const int m_nquad2;
1488 const int m_nmodes0;
1489 const int m_nmodes1;
1490 const int m_nmodes2;
1504
1505private:
1507 vector<LocalRegions::ExpansionSharedPtr> pCollExp,
1509 : Operator(pCollExp, pGeomData, factors), IProductWRTDerivBase_Helper(),
1510 m_nquad0(m_stdExp->GetNumPoints(0)),
1511 m_nquad1(m_stdExp->GetNumPoints(1)),
1512 m_nquad2(m_stdExp->GetNumPoints(2)),
1513 m_nmodes0(m_stdExp->GetBasisNumModes(0)),
1514 m_nmodes1(m_stdExp->GetBasisNumModes(1)),
1515 m_nmodes2(m_stdExp->GetBasisNumModes(2)),
1516 m_base0(m_stdExp->GetBasis(0)->GetBdata()),
1517 m_base1(m_stdExp->GetBasis(1)->GetBdata()),
1518 m_base2(m_stdExp->GetBasis(2)->GetBdata()),
1519 m_derbase0(m_stdExp->GetBasis(0)->GetDbdata()),
1520 m_derbase1(m_stdExp->GetBasis(1)->GetDbdata()),
1521 m_derbase2(m_stdExp->GetBasis(2)->GetDbdata())
1522
1523 {
1524 m_jacWStdW = pGeomData->GetJacWithStdWeights(pCollExp);
1525 m_wspSize = 6 * m_numElmt *
1528 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
1529
1530 const Array<OneD, const NekDouble> &z0 = m_stdExp->GetBasis(0)->GetZ();
1531 const Array<OneD, const NekDouble> &z1 = m_stdExp->GetBasis(1)->GetZ();
1532 const Array<OneD, const NekDouble> &z2 = m_stdExp->GetBasis(2)->GetZ();
1533
1538 // calculate 2.0/((1-eta_1)(1-eta_2))
1539 for (int i = 0; i < m_nquad0; ++i)
1540 {
1541 for (int j = 0; j < m_nquad1; ++j)
1542 {
1543 for (int k = 0; k < m_nquad2; ++k)
1544 {
1545 m_fac0[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
1546 4.0 / ((1 - z1[j]) * (1 - z2[k]));
1547 m_fac1[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
1548 (1 + z0[i]) * 0.5;
1549 m_fac2[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
1550 2.0 / (1 - z2[k]);
1551 m_fac3[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
1552 (1 + z1[j]) * 0.5;
1553 }
1554 }
1555 }
1556
1557 if (m_stdExp->GetBasis(0)->GetBasisType() == LibUtilities::eModified_A)
1558 {
1559 m_sortTopEdge = true;
1560 }
1561 else
1562 {
1563 m_sortTopEdge = false;
1564 }
1565 }
1566};
1567
1568/// Factory initialisation for the IProductWRTDerivBase_SumFac_Tet operator
1569OperatorKey IProductWRTDerivBase_SumFac_Tet::m_type =
1571 OperatorKey(eTetrahedron, eIProductWRTDerivBase, eSumFac, false),
1572 IProductWRTDerivBase_SumFac_Tet::create,
1573 "IProductWRTDerivBase_SumFac_Tet");
1574
1575/**
1576 * @brief Inner product WRT deriv base operator using sum-factorisation (Prism)
1577 */
1578class IProductWRTDerivBase_SumFac_Prism final : virtual public Operator,
1580{
1581public:
1583
1585
1586 /**
1587 * This method calculates:
1588 *
1589 * \f[ (d\phi/dx,in[0]) + (d\phi/dy,in[1]) + (d\phi/dz,in[2]) \f]
1590 *
1591 * which can be represented in terms of local cartesian
1592 * derivaties as:
1593 *
1594 * \f[ ((d\phi/d\xi_0\, d\xi_0/dx +
1595 * d\phi/d\xi_1\, d\xi_1/dx +
1596 * d\phi/d\xi_2\, d\xi_2/dx),in[0]) + \f]
1597 *
1598 * \f[ ((d\phi/d\xi_0\, d\xi_0/dy +
1599 * d\phi/d\xi_1\, d\xi_1/dy +
1600 * d\phi/d\xi_2\, d\xi_2/dy),in[1]) + \f]
1601 *
1602 * \f[ ((d\phi/d\xi_0\, d\xi_0/dz +
1603 * d\phi/d\xi_1\, d\xi_1/dz +
1604 * d\phi/d\xi_2\, d\xi_2/dz),in[2]) \, \f]
1605 *
1606 * where we note that
1607 *
1608 * \f[ d\phi/d\xi_0 =
1609 * d\phi/d\eta_0 d\eta_0/d\xi_0 = d\phi/d\eta_0 2/(1-\eta_2) \f]
1610 *
1611 * \f[ d\phi/d\xi_2 =
1612 * d\phi/d\eta_0 d\eta_0/d\xi_2 + d\phi/d\eta_2 d\eta_2/d\xi_2 =
1613 * d\phi/d\eta_0 (1+\eta_0)/(1-\eta_2) + d\phi/d\eta_2 \f]
1614 *
1615 *
1616 * and so the full inner products are
1617 *
1618 * \f[ (d\phi/dx,in[0]) + (d\phi/dy,in[1]) + (d\phi/dz,in[2]) = \f]
1619 *
1620 * \f[ (d\phi/d\eta_0, ((2/(1-\eta_2) (d\xi_0/dx in[0] + d\xi_0/dy in[1]
1621 * + d\xi_0/dz in[2])
1622 * + (1-\eta_0)/(1-\eta_2) (d\xi_2/dx in[0] + d\xi_2/dy in[1]
1623 * + d\xi_2/dz in[2] )) + \f]
1624 *
1625 * \f[ (d\phi/d\eta_1, (d\xi_1/dx in[0] + d\xi_1/dy in[1]
1626 * + d\xi_1/dz in[2])) + \f]
1627 *
1628 * \f[ (d\phi/d\eta_2, (d\xi_2/dx in[0] + d\xi_2/dy in[1]
1629 * + d\xi_2/dz in[2])) \f]
1630 *
1631 */
1632 void operator()(const Array<OneD, const NekDouble> &entry0,
1633 Array<OneD, NekDouble> &entry1,
1634 Array<OneD, NekDouble> &entry2,
1635 Array<OneD, NekDouble> &entry3,
1636 Array<OneD, NekDouble> &wsp) final
1637 {
1638 unsigned int nPhys = m_stdExp->GetTotPoints();
1639 unsigned int ntot = m_numElmt * nPhys;
1640 unsigned int nmodes = m_stdExp->GetNcoeffs();
1641 unsigned int nmax = max(ntot, m_numElmt * nmodes);
1643 Array<OneD, NekDouble> output, wsp1;
1645
1646 in[0] = entry0;
1647 in[1] = entry1;
1648 in[2] = entry2;
1649
1650 output = entry3;
1651
1652 for (int i = 0; i < 3; ++i)
1653 {
1654 tmp[i] = wsp + i * nmax;
1655 }
1656
1657 if (m_isDeformed)
1658 {
1659 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
1660 for (int i = 0; i < 3; ++i)
1661 {
1662 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
1663 for (int j = 1; j < 3; ++j)
1664 {
1665 Vmath::Vvtvp(ntot, m_derivFac[i + 3 * j], 1, in[j], 1,
1666 tmp[i], 1, tmp[i], 1);
1667 }
1668 }
1669 }
1670 else
1671 {
1673 for (int e = 0; e < m_numElmt; ++e)
1674 {
1675 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
1676 for (int i = 0; i < 3; ++i)
1677 {
1678 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
1679 t = tmp[i] + e * m_nqe, 1);
1680 for (int j = 1; j < 3; ++j)
1681 {
1682 Vmath::Svtvp(m_nqe, m_derivFac[i + 3 * j][e],
1683 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
1684 1, t = tmp[i] + e * m_nqe, 1);
1685 }
1686 }
1687 }
1688 }
1689
1690 wsp1 = wsp + 3 * nmax;
1691
1692 // Sort into eta factors
1693 for (int i = 0; i < m_numElmt; ++i)
1694 {
1695 // scale tmp[0] by fac0
1696 Vmath::Vmul(nPhys, &m_fac0[0], 1, tmp[0].data() + i * nPhys, 1,
1697 tmp[0].data() + i * nPhys, 1);
1698
1699 // scale tmp[2] by fac1 and add to tmp0
1700 Vmath::Vvtvp(nPhys, &m_fac1[0], 1, tmp[2].data() + i * nPhys, 1,
1701 tmp[0].data() + i * nPhys, 1,
1702 tmp[0].data() + i * nPhys, 1);
1703 }
1704
1705 // calculate Iproduct WRT Std Deriv
1708 m_base2, m_jacWStdW, tmp[0], output, wsp1);
1709
1712 m_base2, m_jacWStdW, tmp[1], tmp[0], wsp1);
1713 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1714
1717 m_derbase2, m_jacWStdW, tmp[2], tmp[0], wsp1);
1718 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1719 }
1720
1721 void operator()([[maybe_unused]] int dir,
1722 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
1723 [[maybe_unused]] Array<OneD, NekDouble> &output,
1724 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
1725 {
1726 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
1727 }
1728
1729protected:
1730 const int m_nquad0;
1731 const int m_nquad1;
1732 const int m_nquad2;
1733 const int m_nmodes0;
1734 const int m_nmodes1;
1735 const int m_nmodes2;
1747
1748private:
1750 vector<LocalRegions::ExpansionSharedPtr> pCollExp,
1752 : Operator(pCollExp, pGeomData, factors), IProductWRTDerivBase_Helper(),
1753 m_nquad0(m_stdExp->GetNumPoints(0)),
1754 m_nquad1(m_stdExp->GetNumPoints(1)),
1755 m_nquad2(m_stdExp->GetNumPoints(2)),
1756 m_nmodes0(m_stdExp->GetBasisNumModes(0)),
1757 m_nmodes1(m_stdExp->GetBasisNumModes(1)),
1758 m_nmodes2(m_stdExp->GetBasisNumModes(2)),
1759 m_base0(m_stdExp->GetBasis(0)->GetBdata()),
1760 m_base1(m_stdExp->GetBasis(1)->GetBdata()),
1761 m_base2(m_stdExp->GetBasis(2)->GetBdata()),
1762 m_derbase0(m_stdExp->GetBasis(0)->GetDbdata()),
1763 m_derbase1(m_stdExp->GetBasis(1)->GetDbdata()),
1764 m_derbase2(m_stdExp->GetBasis(2)->GetDbdata())
1765
1766 {
1767 m_jacWStdW = pGeomData->GetJacWithStdWeights(pCollExp);
1768 m_wspSize = 6 * m_numElmt *
1771 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
1772
1773 if (m_stdExp->GetBasis(0)->GetBasisType() == LibUtilities::eModified_A)
1774 {
1775 m_sortTopVertex = true;
1776 }
1777 else
1778 {
1779 m_sortTopVertex = false;
1780 }
1781
1782 const Array<OneD, const NekDouble> &z0 = m_stdExp->GetBasis(0)->GetZ();
1783 const Array<OneD, const NekDouble> &z2 = m_stdExp->GetBasis(2)->GetZ();
1784
1787
1788 for (int i = 0; i < m_nquad0; ++i)
1789 {
1790 for (int j = 0; j < m_nquad1; ++j)
1791 {
1792 for (int k = 0; k < m_nquad2; ++k)
1793 {
1794 // set up geometric factor: 2/(1-z1)
1795 m_fac0[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
1796 2.0 / (1 - z2[k]);
1797 // set up geometric factor: (1+z0)/(1-z1)
1798 m_fac1[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
1799 (1 + z0[i]) / (1 - z2[k]);
1800 }
1801 }
1802 }
1803 }
1804};
1805
1806/// Factory initialisation for the IProductWRTDerivBase_SumFac_Prism operator
1807OperatorKey IProductWRTDerivBase_SumFac_Prism::m_type =
1809 OperatorKey(ePrism, eIProductWRTDerivBase, eSumFac, false),
1810 IProductWRTDerivBase_SumFac_Prism::create,
1811 "IProductWRTDerivBase_SumFac_Prism");
1812
1813/**
1814 * @brief Inner product WRT deriv base operator using sum-factorisation (Pyr)
1815 */
1816class IProductWRTDerivBase_SumFac_Pyr final : virtual public Operator,
1818{
1819public:
1821
1823
1824 /**
1825 * This method calculates:
1826 *
1827 * \f[ (d\phi/dx,in[0]) + (d\phi/dy,in[1]) + (d\phi/dz,in[2]) \f]
1828 *
1829 * which can be represented in terms of local cartesian
1830 * derivaties as:
1831 *
1832 * \f[ ((d\phi/d\xi_0\, d\xi_0/dx +
1833 * d\phi/d\xi_1\, d\xi_1/dx +
1834 * d\phi/d\xi_2\, d\xi_2/dx),in[0]) + \f]
1835 *
1836 * \f[ ((d\phi/d\xi_0\, d\xi_0/dy +
1837 * d\phi/d\xi_1\, d\xi_1/dy +
1838 * d\phi/d\xi_2\, d\xi_2/dy),in[1]) + \f]
1839 *
1840 * \f[ ((d\phi/d\xi_0\, d\xi_0/dz +
1841 * d\phi/d\xi_1\, d\xi_1/dz +
1842 * d\phi/d\xi_2\, d\xi_2/dz),in[2]) \, \f]
1843 *
1844 * where we note that
1845 *
1846 * \f[ d\phi/d\xi_0 =
1847 * d\phi/d\eta_0\, d\eta_0/d\xi_0 =
1848 * d\phi/d\eta_0\, 2/(1-\eta_2). \f]
1849 *
1850 * \f[ d\phi/d\xi_1 =
1851 * d\phi/d\eta_1\, d\eta_1/d\xi_1 =
1852 * d\phi/d\eta_1\, 2/(1-\eta_2) \f]
1853 *
1854 * \f[ d\phi/d\xi_2 =
1855 * d\phi/d\eta_0\, d\eta_0/d\xi_2 +
1856 * d\phi/d\eta_1\, d\eta_1/d\xi_2 +
1857 * d\phi/d\eta_2\, d\eta_2/d\xi_2 =
1858 * d\phi/d\eta_0 (1+\eta_0)/(1-\eta_2) +
1859 * d\phi/d\eta_1 (1+\eta_1)/(1-\eta_2) + d\phi/d\eta_2 \f]
1860 *
1861 * and so the full inner products are
1862 *
1863 * \f[ (d\phi/dx,in[0]) + (d\phi/dy,in[1]) + (d\phi/dz,in[2]) = \f]
1864 *
1865 * \f[ (d\phi/d\eta_0, ((2/(1-\eta_2) (d\xi_0/dx in[0] +
1866 * d\xi_0/dy in[1] +
1867 * (1-\eta_0)/(1-\eta_2) (d\xi_2/dx in[0] + d\xi_2/dy in[1]
1868 * + d\xi_2/dz in[2] )) + \f]
1869 * \f[ (d\phi/d\eta_1, ((2/(1-\eta_2) (d\xi_1/dx in[0] +
1870 * d\xi_0/dy in[1] + d\xi_0/dz in[2]) +
1871 * (1-\eta_1)/(1-\eta_2) (d\xi_2/dx in[0] + d\xi_2/dy in[1] +
1872 * d\xi_2/dz in[2] )) \f]
1873 *
1874 * \f[ (d\phi/d\eta_2, (d\xi_2/dx in[0] + d\xi_2/dy in[1] +
1875 * d\xi_2/dz in[2])) \f]
1876 */
1877 void operator()(const Array<OneD, const NekDouble> &entry0,
1878 Array<OneD, NekDouble> &entry1,
1879 Array<OneD, NekDouble> &entry2,
1880 Array<OneD, NekDouble> &entry3,
1881 Array<OneD, NekDouble> &wsp) final
1882 {
1883 unsigned int nPhys = m_stdExp->GetTotPoints();
1884 unsigned int ntot = m_numElmt * nPhys;
1885 unsigned int nmodes = m_stdExp->GetNcoeffs();
1886 unsigned int nmax = max(ntot, m_numElmt * nmodes);
1888 Array<OneD, NekDouble> output, wsp1;
1890
1891 in[0] = entry0;
1892 in[1] = entry1;
1893 in[2] = entry2;
1894
1895 output = entry3;
1896
1897 for (int i = 0; i < 3; ++i)
1898 {
1899 tmp[i] = wsp + i * nmax;
1900 }
1901
1902 if (m_isDeformed)
1903 {
1904 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
1905 for (int i = 0; i < 3; ++i)
1906 {
1907 Vmath::Vmul(ntot, m_derivFac[i], 1, in[0], 1, tmp[i], 1);
1908 for (int j = 1; j < 3; ++j)
1909 {
1910 Vmath::Vvtvp(ntot, m_derivFac[i + 3 * j], 1, in[j], 1,
1911 tmp[i], 1, tmp[i], 1);
1912 }
1913 }
1914 }
1915 else
1916 {
1918 for (int e = 0; e < m_numElmt; ++e)
1919 {
1920 // calculate dx/dxi in[0] + dy/dxi in[1] + dz/dxi in[2]
1921 for (int i = 0; i < 3; ++i)
1922 {
1923 Vmath::Smul(m_nqe, m_derivFac[i][e], in[0] + e * m_nqe, 1,
1924 t = tmp[i] + e * m_nqe, 1);
1925 for (int j = 1; j < 3; ++j)
1926 {
1927 Vmath::Svtvp(m_nqe, m_derivFac[i + 3 * j][e],
1928 in[j] + e * m_nqe, 1, tmp[i] + e * m_nqe,
1929 1, t = tmp[i] + e * m_nqe, 1);
1930 }
1931 }
1932 }
1933 }
1934
1935 wsp1 = wsp + 3 * nmax;
1936
1937 // Sort into eta factors
1938 for (int i = 0; i < m_numElmt; ++i)
1939 {
1940 // scale tmp[0] by fac0
1941 Vmath::Vmul(nPhys, &m_fac0[0], 1, tmp[0].data() + i * nPhys, 1,
1942 tmp[0].data() + i * nPhys, 1);
1943
1944 // scale tmp[2] by fac1 and add to tmp0
1945 Vmath::Vvtvp(nPhys, &m_fac1[0], 1, tmp[2].data() + i * nPhys, 1,
1946 tmp[0].data() + i * nPhys, 1,
1947 tmp[0].data() + i * nPhys, 1);
1948
1949 // scale tmp[1] by fac0
1950 Vmath::Vmul(nPhys, &m_fac0[0], 1, tmp[1].data() + i * nPhys, 1,
1951 tmp[1].data() + i * nPhys, 1);
1952
1953 // scale tmp[2] by fac2 and add to tmp1
1954 Vmath::Vvtvp(nPhys, &m_fac2[0], 1, tmp[2].data() + i * nPhys, 1,
1955 tmp[1].data() + i * nPhys, 1,
1956 tmp[1].data() + i * nPhys, 1);
1957 }
1958
1959 // calculate Iproduct WRT Std Deriv
1962 m_base2, m_jacWStdW, tmp[0], output, wsp1);
1963
1966 m_base2, m_jacWStdW, tmp[1], tmp[0], wsp1);
1967 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1968
1971 m_derbase2, m_jacWStdW, tmp[2], tmp[0], wsp1);
1972 Vmath::Vadd(m_numElmt * nmodes, tmp[0], 1, output, 1, output, 1);
1973 }
1974
1975 void operator()([[maybe_unused]] int dir,
1976 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
1977 [[maybe_unused]] Array<OneD, NekDouble> &output,
1978 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
1979 {
1980 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
1981 }
1982
1983protected:
1984 const int m_nquad0;
1985 const int m_nquad1;
1986 const int m_nquad2;
1987 const int m_nmodes0;
1988 const int m_nmodes1;
1989 const int m_nmodes2;
2002
2003private:
2005 vector<LocalRegions::ExpansionSharedPtr> pCollExp,
2007 : Operator(pCollExp, pGeomData, factors), IProductWRTDerivBase_Helper(),
2008 m_nquad0(m_stdExp->GetNumPoints(0)),
2009 m_nquad1(m_stdExp->GetNumPoints(1)),
2010 m_nquad2(m_stdExp->GetNumPoints(2)),
2011 m_nmodes0(m_stdExp->GetBasisNumModes(0)),
2012 m_nmodes1(m_stdExp->GetBasisNumModes(1)),
2013 m_nmodes2(m_stdExp->GetBasisNumModes(2)),
2014 m_base0(m_stdExp->GetBasis(0)->GetBdata()),
2015 m_base1(m_stdExp->GetBasis(1)->GetBdata()),
2016 m_base2(m_stdExp->GetBasis(2)->GetBdata()),
2017 m_derbase0(m_stdExp->GetBasis(0)->GetDbdata()),
2018 m_derbase1(m_stdExp->GetBasis(1)->GetDbdata()),
2019 m_derbase2(m_stdExp->GetBasis(2)->GetDbdata())
2020
2021 {
2022 m_jacWStdW = pGeomData->GetJacWithStdWeights(pCollExp);
2023 m_wspSize = 6 * m_numElmt *
2026 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
2027
2028 if (m_stdExp->GetBasis(0)->GetBasisType() == LibUtilities::eModified_A)
2029 {
2030 m_sortTopVertex = true;
2031 }
2032 else
2033 {
2034 m_sortTopVertex = false;
2035 }
2036
2037 const Array<OneD, const NekDouble> &z0 = m_stdExp->GetBasis(0)->GetZ();
2038 const Array<OneD, const NekDouble> &z1 = m_stdExp->GetBasis(1)->GetZ();
2039 const Array<OneD, const NekDouble> &z2 = m_stdExp->GetBasis(2)->GetZ();
2040
2044
2045 for (int i = 0; i < m_nquad0; ++i)
2046 {
2047 for (int j = 0; j < m_nquad1; ++j)
2048 {
2049 for (int k = 0; k < m_nquad2; ++k)
2050 {
2051 // set up geometric factor: 2/(1-z2)
2052 m_fac0[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
2053 2.0 / (1 - z2[k]);
2054 // set up geometric factor: (1+z0)/(1-z2)
2055 m_fac1[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
2056 (1 + z0[i]) / (1 - z2[k]);
2057 // set up geometric factor: (1+z1)/(1-z2)
2058 m_fac2[i + j * m_nquad0 + k * m_nquad0 * m_nquad1] =
2059 (1 + z1[j]) / (1 - z2[k]);
2060 }
2061 }
2062 }
2063 }
2064};
2065
2066/// Factory initialisation for the IProductWRTDerivBase_SumFac_Pyr operator
2067OperatorKey IProductWRTDerivBase_SumFac_Pyr::m_type =
2069 OperatorKey(ePyramid, eIProductWRTDerivBase, eSumFac, false),
2070 IProductWRTDerivBase_SumFac_Pyr::create,
2071 "IProductWRTDerivBase_SumFac_Pyr");
2072
2073} // namespace Nektar::Collections
#define ASSERTL0(condition, msg)
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
#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< LocalRegions::ExpansionSharedPtr > 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< LocalRegions::ExpansionSharedPtr > 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.
IProductWRTDerivBase_NoCollection(vector< LocalRegions::ExpansionSharedPtr > 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
vector< LocalRegions::ExpansionSharedPtr > m_expList
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< LocalRegions::ExpansionSharedPtr > 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< LocalRegions::ExpansionSharedPtr > pCollExp, CoalescedGeomDataSharedPtr pGeomData, StdRegions::FactorMap factors)
Inner product WRT deriv base operator using sum-factorisation (Prism)
IProductWRTDerivBase_SumFac_Prism(vector< LocalRegions::ExpansionSharedPtr > 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< LocalRegions::ExpansionSharedPtr > 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< LocalRegions::ExpansionSharedPtr > 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< LocalRegions::ExpansionSharedPtr > 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< LocalRegions::ExpansionSharedPtr > pCollExp, CoalescedGeomDataSharedPtr pGeomData, StdRegions::FactorMap factors)
Inner product WRT deriv base operator using sum-factorisation (Tri)
IProductWRTDerivBase_SumFac_Tri(vector< LocalRegions::ExpansionSharedPtr > 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
unsigned int m_nElmtPad
size after padding
Base class for operators on a collection of elements.
Definition Operator.h:138
StdRegions::StdExpansionSharedPtr m_stdExp
Definition Operator.h:230
unsigned int m_numElmt
number of elements that the operator is applied on
Definition Operator.h:232
unsigned int m_outputSize
number of modes or quadrature points that are taken as output from an operator
Definition Operator.h:240
unsigned int m_inputSize
number of modes or quadrature points that are passed as input to an operator
Definition Operator.h:237
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
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:324
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:406
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:339
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:171
@ eModified_A
Principle Modified Functions .
Definition BasisType.h:48
ConstFactorMap FactorMap
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.
scalarT< T > max(scalarT< T > lhs, scalarT< T > rhs)
Definition scalar.hpp:305