Nektar++
Loading...
Searching...
No Matches
library/Collections/Helmholtz.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: Helmholtz.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: Helmholtz operator implementations
32//
33///////////////////////////////////////////////////////////////////////////////
34
39#include <MatrixFreeOps/Operator.hpp>
40
41using namespace std;
42
43namespace Nektar::Collections
44{
45
56
57/**
58 * @brief Helmholtz help class to calculate the size of the collection
59 * that is given as an input and as an output to the Helmholtz Operator. The
60 * size evaluation takes into account that the evaluation of the Helmholtz
61 * operator takes input from the coeff space and gives the output in the coeff
62 * space too.
63 */
64class Helmholtz_Helper : virtual public Operator
65{
66protected:
68 {
69 // expect input to be number of elements by the number of coefficients
70 m_inputSize = m_numElmt * m_stdExp->GetNcoeffs();
71
72 // expect output to be number of elements by the number of coefficients
73 // computation is from coeff space to coeff space
75 }
76};
77
78/**
79 * @brief Helmholtz operator using LocalRegions implementation.
80 */
82{
83public:
85
86 ~Helmholtz_NoCollection() final = default;
87
88 void operator()(const Array<OneD, const NekDouble> &entry0,
89 Array<OneD, NekDouble> &entry1,
90 [[maybe_unused]] Array<OneD, NekDouble> &entry2,
91 [[maybe_unused]] Array<OneD, NekDouble> &entry3,
92 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
93 {
94 unsigned int nmodes = m_expList[0]->GetNcoeffs();
95 unsigned int nphys = m_expList[0]->GetTotPoints();
97
98 for (int n = 0; n < m_numElmt; ++n)
99 {
100 // Restrict varcoeffs to size of element
102 if (m_varcoeffs.size())
103 {
104 varcoeffs =
105 StdRegions::RestrictCoeffMap(m_varcoeffs, n * nphys, nphys);
106 }
107
109 StdRegions::eHelmholtz, (m_expList)[n]->DetShapeType(),
110 *(m_expList)[n], m_factors, varcoeffs);
111 m_expList[n]->GeneralMatrixOp(entry0 + n * nmodes,
112 tmp = entry1 + n * nmodes, mkey);
113 }
114 }
115
116 void operator()([[maybe_unused]] int dir,
117 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
118 [[maybe_unused]] Array<OneD, NekDouble> &output,
119 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
120 {
121 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
122 }
123
125 {
126 m_factors = factors;
127 }
128
129 void UpdateVarcoeffs(StdRegions::VarCoeffMap &varcoeffs) override
130 {
131 m_varcoeffs = varcoeffs;
132 }
133
134protected:
135 int m_dim;
137 vector<LocalRegions::ExpansionSharedPtr> m_expList;
140
141private:
142 Helmholtz_NoCollection(vector<LocalRegions::ExpansionSharedPtr> pCollExp,
144 StdRegions::FactorMap factors)
145 : Operator(pCollExp, pGeomData, factors), Helmholtz_Helper()
146 {
147 m_expList = pCollExp;
148 m_dim = pCollExp[0]->GetNumBases();
149 m_coordim = pCollExp[0]->GetCoordim();
150
151 m_factors = factors;
153 }
154};
155
156/// Factory initialisation for the Helmholtz_NoCollection operators
157OperatorKey Helmholtz_NoCollection::m_typeArr[] = {
159 OperatorKey(eSegment, eHelmholtz, eNoCollection, false),
160 Helmholtz_NoCollection::create, "Helmholtz_NoCollection_Seg"),
162 OperatorKey(eTriangle, eHelmholtz, eNoCollection, false),
163 Helmholtz_NoCollection::create, "Helmholtz_NoCollection_Tri"),
165 OperatorKey(eNodalTri, eHelmholtz, eNoCollection, true),
166 Helmholtz_NoCollection::create, "Helmholtz_NoCollection_NodalTri"),
168 OperatorKey(eQuadrilateral, eHelmholtz, eNoCollection, false),
169 Helmholtz_NoCollection::create, "Helmholtz_NoCollection_Quad"),
171 OperatorKey(eTetrahedron, eHelmholtz, eNoCollection, false),
172 Helmholtz_NoCollection::create, "Helmholtz_NoCollection_Tet"),
174 OperatorKey(eNodalTet, eHelmholtz, eNoCollection, true),
175 Helmholtz_NoCollection::create, "Helmholtz_NoCollection_NodalTet"),
177 OperatorKey(ePyramid, eHelmholtz, eNoCollection, false),
178 Helmholtz_NoCollection::create, "Helmholtz_NoCollection_Pyr"),
180 OperatorKey(ePrism, eHelmholtz, eNoCollection, false),
181 Helmholtz_NoCollection::create, "Helmholtz_NoCollection_Prism"),
183 OperatorKey(eNodalPrism, eHelmholtz, eNoCollection, true),
184 Helmholtz_NoCollection::create, "Helmholtz_NoCollection_NodalPrism"),
186 OperatorKey(eHexahedron, eHelmholtz, eNoCollection, false),
187 Helmholtz_NoCollection::create, "Helmholtz_NoCollection_Hex")};
188
189/**
190 * @brief Helmholtz operator using LocalRegions implementation.
191 */
192class Helmholtz_IterPerExp final : virtual public Operator, Helmholtz_Helper
193{
194public:
196
197 ~Helmholtz_IterPerExp() final = default;
198
199 void operator()(const Array<OneD, const NekDouble> &input,
200 Array<OneD, NekDouble> &output,
201 [[maybe_unused]] Array<OneD, NekDouble> &output1,
202 [[maybe_unused]] Array<OneD, NekDouble> &output2,
203 Array<OneD, NekDouble> &wsp) final
204 {
205 const int nCoeffs = m_stdExp->GetNcoeffs();
206 const int nPhys = m_stdExp->GetTotPoints();
207
208 ASSERTL1(input.size() >= m_numElmt * nCoeffs,
209 "input array size is insufficient");
210 ASSERTL1(output.size() >= m_numElmt * nCoeffs,
211 "output array size is insufficient");
212
213 Array<OneD, NekDouble> tmpphys, t1;
216
217 tmpphys = wsp;
218 for (int i = 1; i < m_coordim + 1; ++i)
219 {
220 dtmp[i - 1] = wsp + i * nPhys;
221 tmp[i - 1] = wsp + (i + m_coordim) * nPhys;
222 }
223
224 for (int i = 0; i < m_numElmt; ++i)
225 {
226 m_stdExp->BwdTrans(input + i * nCoeffs, tmpphys);
227
228 // local derivative
229 m_stdExp->PhysDeriv(tmpphys, dtmp[0], dtmp[1], dtmp[2]);
230
231 // determine mass matrix term
232 if (m_isDeformed)
233 {
234 Vmath::Vmul(nPhys, m_jac + i * nPhys, 1, tmpphys, 1, tmpphys,
235 1);
236 }
237 else
238 {
239 Vmath::Smul(nPhys, m_jac[i], tmpphys, 1, tmpphys, 1);
240 }
241
242 m_stdExp->IProductWRTBase(tmpphys, t1 = output + i * nCoeffs);
243 Vmath::Smul(nCoeffs, m_lambda, output + i * nCoeffs, 1,
244 t1 = output + i * nCoeffs, 1);
245
246 if (m_isDeformed)
247 {
248 // calculate full derivative
249 for (int j = 0; j < m_coordim; ++j)
250 {
251 Vmath::Vmul(nPhys,
252 m_derivFac[j * m_dim].origin() + i * nPhys, 1,
253 &dtmp[0][0], 1, &tmp[j][0], 1);
254
255 for (int k = 1; k < m_dim; ++k)
256 {
258 nPhys,
259 m_derivFac[j * m_dim + k].origin() + i * nPhys, 1,
260 &dtmp[k][0], 1, &tmp[j][0], 1, &tmp[j][0], 1);
261 }
262 }
263
265 {
266 // calculate dtmp[i] = dx/dxi sum_j diff[0][j] tmp[j]
267 // + dy/dxi sum_j diff[1][j] tmp[j]
268 // + dz/dxi sum_j diff[2][j] tmp[j]
269
270 // First term
271 Vmath::Smul(nPhys, m_diff[0][0], &tmp[0][0], 1, &tmpphys[0],
272 1);
273 for (int l = 1; l < m_coordim; ++l)
274 {
275 Vmath::Svtvp(nPhys, m_diff[0][l], &tmp[l][0], 1,
276 &tmpphys[0], 1, &tmpphys[0], 1);
277 }
278
279 for (int j = 0; j < m_dim; ++j)
280 {
281 Vmath::Vmul(nPhys, m_derivFac[j].origin() + i * nPhys,
282 1, &tmpphys[0], 1, &dtmp[j][0], 1);
283 }
284
285 // Second and third terms
286 for (int k = 1; k < m_coordim; ++k)
287 {
288 Vmath::Smul(nPhys, m_diff[k][0], &tmp[0][0], 1,
289 &tmpphys[0], 1);
290 for (int l = 1; l < m_coordim; ++l)
291 {
292 Vmath::Svtvp(nPhys, m_diff[k][l], &tmp[l][0], 1,
293 &tmpphys[0], 1, &tmpphys[0], 1);
294 }
295
296 for (int j = 0; j < m_dim; ++j)
297 {
298 Vmath::Vvtvp(nPhys,
299 m_derivFac[j + k * m_dim].origin() +
300 i * nPhys,
301 1, &tmpphys[0], 1, &dtmp[j][0], 1,
302 &dtmp[j][0], 1);
303 }
304 }
305 }
306 else
307 {
308 // calculate dx/dxi tmp[0] + dy/dxi tmp[1]
309 // + dz/dxi tmp[2]
310 for (int j = 0; j < m_dim; ++j)
311 {
312 Vmath::Vmul(nPhys, m_derivFac[j].origin() + i * nPhys,
313 1, &tmp[0][0], 1, &dtmp[j][0], 1);
314
315 for (int k = 1; k < m_coordim; ++k)
316 {
317 Vmath::Vvtvp(nPhys,
318 m_derivFac[j + k * m_dim].origin() +
319 i * nPhys,
320 1, &tmp[k][0], 1, &dtmp[j][0], 1,
321 &dtmp[j][0], 1);
322 }
323 }
324 }
325
326 // calculate Iproduct WRT Std Deriv
327 for (int j = 0; j < m_dim; ++j)
328 {
329 // multiply by Jacobian
330 Vmath::Vmul(nPhys, m_jac + i * nPhys, 1, dtmp[j], 1,
331 dtmp[j], 1);
332
333 m_stdExp->IProductWRTDerivBase(j, dtmp[j], tmp[0]);
334 Vmath::Vadd(nCoeffs, tmp[0], 1, output + i * nCoeffs, 1,
335 t1 = output + i * nCoeffs, 1);
336 }
337 }
338 else
339 {
340 // calculate full derivative
341 for (int j = 0; j < m_coordim; ++j)
342 {
343 Vmath::Smul(nPhys, m_derivFac[j * m_dim][i], &dtmp[0][0], 1,
344 &tmp[j][0], 1);
345
346 for (int k = 1; k < m_dim; ++k)
347 {
348 Vmath::Svtvp(nPhys, m_derivFac[j * m_dim + k][i],
349 &dtmp[k][0], 1, &tmp[j][0], 1, &tmp[j][0],
350 1);
351 }
352 }
353
355 {
356 // calculate dtmp[i] = dx/dxi sum_j diff[0][j] tmp[j]
357 // + dy/dxi sum_j diff[1][j] tmp[j]
358 // + dz/dxi sum_j diff[2][j] tmp[j]
359
360 // First term
361 Vmath::Smul(nPhys, m_diff[0][0], &tmp[0][0], 1, &tmpphys[0],
362 1);
363 for (int l = 1; l < m_coordim; ++l)
364 {
365 Vmath::Svtvp(nPhys, m_diff[0][l], &tmp[l][0], 1,
366 &tmpphys[0], 1, &tmpphys[0], 1);
367 }
368
369 for (int j = 0; j < m_dim; ++j)
370 {
371 Vmath::Smul(nPhys, m_derivFac[j][i], &tmpphys[0], 1,
372 &dtmp[j][0], 1);
373 }
374
375 // Second and third terms
376 for (int k = 1; k < m_coordim; ++k)
377 {
378 Vmath::Smul(nPhys, m_diff[k][0], &tmp[0][0], 1,
379 &tmpphys[0], 1);
380 for (int l = 1; l < m_coordim; ++l)
381 {
382 Vmath::Svtvp(nPhys, m_diff[k][l], &tmp[l][0], 1,
383 &tmpphys[0], 1, &tmpphys[0], 1);
384 }
385
386 for (int j = 0; j < m_dim; ++j)
387 {
388 Vmath::Svtvp(nPhys, m_derivFac[j + k * m_dim][i],
389 &tmpphys[0], 1, &dtmp[j][0], 1,
390 &dtmp[j][0], 1);
391 }
392 }
393 }
394 else
395 {
396 // calculate dx/dxi tmp[0] + dy/dxi tmp[2]
397 // + dz/dxi tmp[3]
398 for (int j = 0; j < m_dim; ++j)
399 {
400 Vmath::Smul(nPhys, m_derivFac[j][i], &tmp[0][0], 1,
401 &dtmp[j][0], 1);
402
403 for (int k = 1; k < m_coordim; ++k)
404 {
405 Vmath::Svtvp(nPhys, m_derivFac[j + k * m_dim][i],
406 &tmp[k][0], 1, &dtmp[j][0], 1,
407 &dtmp[j][0], 1);
408 }
409 }
410 }
411
412 // calculate Iproduct WRT Std Deriv
413 for (int j = 0; j < m_dim; ++j)
414 {
415 // multiply by Jacobian
416 Vmath::Smul(nPhys, m_jac[i], dtmp[j], 1, dtmp[j], 1);
417
418 m_stdExp->IProductWRTDerivBase(j, dtmp[j], tmp[0]);
419 Vmath::Vadd(nCoeffs, tmp[0], 1, output + i * nCoeffs, 1,
420 t1 = output + i * nCoeffs, 1);
421 }
422 }
423 }
424 }
425
426 void operator()([[maybe_unused]] int dir,
427 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
428 [[maybe_unused]] Array<OneD, NekDouble> &output,
429 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
430 {
431 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
432 }
433
434 /**
435 * @brief Check the validity of supplied constant factors.
436 *
437 * @param factors Map of factors
438 */
440 {
441 // If match previous factors, nothing to do.
442 if (m_factors == factors)
443 {
444 return;
445 }
446
447 m_factors = factors;
448
449 // Check Lambda constant of Helmholtz operator
450 auto x = factors.find(StdRegions::eFactorLambda);
451 ASSERTL1(
452 x != factors.end(),
453 "Constant factor not defined: " +
454 std::string(
456 m_lambda = x->second;
457
458 // If varcoeffs not supplied, nothing else to do.
459 m_HasVarCoeffDiff = false;
460 auto d = factors.find(StdRegions::eFactorCoeffD00);
461 if (d == factors.end())
462 {
463 return;
464 }
465
467 for (int i = 0; i < m_coordim; ++i)
468 {
470 }
471
472 for (int i = 0; i < m_coordim; ++i)
473 {
474 d = factors.find(m_factorCoeffDef[i][i]);
475 if (d != factors.end())
476 {
477 m_diff[i][i] = d->second;
478 }
479 else
480 {
481 m_diff[i][i] = 1.0;
482 }
483
484 for (int j = i + 1; j < m_coordim; ++j)
485 {
486 d = factors.find(m_factorCoeffDef[i][j]);
487 if (d != factors.end())
488 {
489 m_diff[i][j] = m_diff[j][i] = d->second;
490 }
491 }
492 }
493 m_HasVarCoeffDiff = true;
494 }
495
496 /**
497 * @brief Check the validity of supplied variable coefficients.
498 * Note that the m_varcoeffs are not implemented for the IterPerExp
499 * operator.
500 * There exists a specialised implementation for variable diffusion in the
501 * above function UpdateFactors.
502 *
503 * @param varcoeffs Map of varcoeffs
504 */
505 void UpdateVarcoeffs(StdRegions::VarCoeffMap &varcoeffs) override
506 {
507 m_varcoeffs = varcoeffs;
508 }
509
510protected:
513 int m_dim;
527
528private:
529 Helmholtz_IterPerExp(vector<LocalRegions::ExpansionSharedPtr> pCollExp,
531 StdRegions::FactorMap factors)
532 : Operator(pCollExp, pGeomData, factors), Helmholtz_Helper()
533 {
534 m_dim = pCollExp[0]->GetShapeDimension();
535 m_coordim = pCollExp[0]->GetCoordim();
536 int nqtot = m_stdExp->GetTotPoints();
537
538 m_derivFac = pGeomData->GetDerivFactors(pCollExp);
539 m_jac = pGeomData->GetJac(pCollExp);
540 m_wspSize = (2 * m_coordim + 1) * nqtot;
541
542 m_lambda = 1.0;
543 m_HasVarCoeffDiff = false;
546 this->UpdateFactors(factors);
547 }
548};
549
550/// Factory initialisation for the Helmholtz_IterPerExp operators
551OperatorKey Helmholtz_IterPerExp::m_typeArr[] = {
553 OperatorKey(eSegment, eHelmholtz, eIterPerExp, false),
554 Helmholtz_IterPerExp::create, "Helmholtz_IterPerExp_Seg"),
556 OperatorKey(eTriangle, eHelmholtz, eIterPerExp, false),
557 Helmholtz_IterPerExp::create, "Helmholtz_IterPerExp_Tri"),
559 OperatorKey(eNodalTri, eHelmholtz, eIterPerExp, true),
560 Helmholtz_IterPerExp::create, "Helmholtz_IterPerExp_NodalTri"),
562 OperatorKey(eQuadrilateral, eHelmholtz, eIterPerExp, false),
563 Helmholtz_IterPerExp::create, "Helmholtz_IterPerExp_Quad"),
565 OperatorKey(eTetrahedron, eHelmholtz, eIterPerExp, false),
566 Helmholtz_IterPerExp::create, "Helmholtz_IterPerExp_Tet"),
568 OperatorKey(eNodalTet, eHelmholtz, eIterPerExp, true),
569 Helmholtz_IterPerExp::create, "Helmholtz_IterPerExp_NodalTet"),
571 OperatorKey(ePyramid, eHelmholtz, eIterPerExp, false),
572 Helmholtz_IterPerExp::create, "Helmholtz_IterPerExp_Pyr"),
574 OperatorKey(ePrism, eHelmholtz, eIterPerExp, false),
575 Helmholtz_IterPerExp::create, "Helmholtz_IterPerExp_Prism"),
577 OperatorKey(eNodalPrism, eHelmholtz, eIterPerExp, true),
578 Helmholtz_IterPerExp::create, "Helmholtz_IterPerExp_NodalPrism"),
580 OperatorKey(eHexahedron, eHelmholtz, eIterPerExp, false),
581 Helmholtz_IterPerExp::create, "Helmholtz_IterPerExp_Hex")};
582
583/**
584 * @brief Helmholtz operator using matrix free operators.
585 */
586class Helmholtz_MatrixFree final : virtual public Operator,
589{
590public:
592
593 ~Helmholtz_MatrixFree() final = default;
594
595 void operator()(const Array<OneD, const NekDouble> &input,
596 Array<OneD, NekDouble> &output0,
597 [[maybe_unused]] Array<OneD, NekDouble> &output1,
598 [[maybe_unused]] Array<OneD, NekDouble> &output2,
599 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
600 {
601 (*m_oper)(input, output0);
602 }
603
604 void operator()([[maybe_unused]] int dir,
605 [[maybe_unused]] const Array<OneD, const NekDouble> &input,
606 [[maybe_unused]] Array<OneD, NekDouble> &output,
607 [[maybe_unused]] Array<OneD, NekDouble> &wsp) final
608 {
609 NEKERROR(ErrorUtil::efatal, "Not valid for this operator.");
610 }
611
612 /**
613 *
614 */
616 {
617 if (factors == m_factors)
618 {
619 return;
620 }
621
622 m_factors = factors;
623
624 // Set lambda for this call
625 auto x = factors.find(StdRegions::eFactorLambda);
626 ASSERTL1(
627 x != factors.end(),
628 "Constant factor not defined: " +
629 std::string(
631 m_oper->SetLambda(x->second);
632
633 // set constant diffusion coefficients
634 bool isConstVarDiff = false;
636 diff[0] = diff[2] = diff[5] = 1.0;
637
638 auto xd00 = factors.find(StdRegions::eFactorCoeffD00);
639 if (xd00 != factors.end() && xd00->second != 1.0)
640 {
641 isConstVarDiff = true;
642 diff[0] = xd00->second;
643 }
644
645 auto xd01 = factors.find(StdRegions::eFactorCoeffD01);
646 if (xd01 != factors.end() && xd01->second != 0.0)
647 {
648 isConstVarDiff = true;
649 diff[1] = xd01->second;
650 }
651
652 auto xd11 = factors.find(StdRegions::eFactorCoeffD11);
653 if (xd11 != factors.end() && xd11->second != 1.0)
654 {
655 isConstVarDiff = true;
656 diff[2] = xd11->second;
657 }
658
659 auto xd02 = factors.find(StdRegions::eFactorCoeffD02);
660 if (xd02 != factors.end() && xd02->second != 0.0)
661 {
662 isConstVarDiff = true;
663 diff[3] = xd02->second;
664 }
665
666 auto xd12 = factors.find(StdRegions::eFactorCoeffD12);
667 if (xd12 != factors.end() && xd12->second != 0.0)
668 {
669 isConstVarDiff = true;
670 diff[4] = xd12->second;
671 }
672
673 auto xd22 = factors.find(StdRegions::eFactorCoeffD22);
674 if (xd22 != factors.end() && xd22->second != 1.0)
675 {
676 isConstVarDiff = true;
677 diff[5] = xd22->second;
678 }
679
680 if (isConstVarDiff)
681 {
682 m_oper->SetConstVarDiffusion(diff);
683 }
684
685 // set random here for fn variable diffusion
686 auto k = factors.find(StdRegions::eFactorTau);
687 if (k != factors.end() && k->second != 0.0)
688 {
689 m_oper->SetVarDiffusion(diff);
690 }
691 }
692
693 /**
694 * @brief Check the validity of supplied variable coefficients.
695 * Note that the m_varcoeffs are not implemented for the MatrixFree
696 * operator.
697 * There exists a specialised implementation for variable diffusion in the
698 * above function UpdateFactors.
699 *
700 * @param varcoeffs Map of varcoeffs
701 */
702 void UpdateVarcoeffs(StdRegions::VarCoeffMap &varcoeffs) override
703 {
704 m_varcoeffs = varcoeffs;
705 }
706
707private:
708 std::shared_ptr<MatrixFree::Helmholtz> m_oper;
709 unsigned int m_nmtot;
712
713 Helmholtz_MatrixFree(vector<LocalRegions::ExpansionSharedPtr> pCollExp,
715 StdRegions::FactorMap factors)
716 : Operator(pCollExp, pGeomData, factors),
717 MatrixFreeBase(pCollExp[0]->GetNcoeffs(), pCollExp[0]->GetNcoeffs(),
718 pCollExp.size()),
720 {
721
722 m_nmtot = m_numElmt * pCollExp[0]->GetNcoeffs();
723
724 const auto dim = pCollExp[0]->GetShapeDimension();
725
726 // Basis vector.
727 std::vector<LibUtilities::BasisSharedPtr> basis(dim);
728 for (auto i = 0; i < dim; ++i)
729 {
730 basis[i] = pCollExp[0]->GetBasis(i);
731 }
732
733 // Get shape type
734 auto shapeType = pCollExp[0]->DetShapeType();
735
736 // Generate operator string and create operator.
737 std::string op_string = "Helmholtz";
738 op_string += MatrixFree::GetOpstring(shapeType, m_isDeformed);
739 auto oper = MatrixFree::GetOperatorFactory().CreateInstance(
740 op_string, basis, pCollExp.size());
741
742 // Set Jacobian
743 oper->SetJac(pGeomData->GetJacInterLeave(pCollExp, m_nElmtPad));
744
745 // Store derivative factor
746 oper->SetDF(pGeomData->GetDerivFactorsInterLeave(pCollExp, m_nElmtPad));
747
748 oper->SetUpBdata(basis);
749 oper->SetUpDBdata(basis);
750 oper->SetUpZW(basis);
751 oper->SetUpD(basis);
752
753 m_oper = std::dynamic_pointer_cast<MatrixFree::Helmholtz>(oper);
754 ASSERTL0(m_oper, "Failed to cast pointer.");
755
756 // Set factors
759 this->UpdateFactors(factors);
760 }
761};
762
763/// Factory initialisation for the Helmholtz_MatrixFree operators
764OperatorKey Helmholtz_MatrixFree::m_typeArr[] = {
766 OperatorKey(eQuadrilateral, eHelmholtz, eMatrixFree, false),
767 Helmholtz_MatrixFree::create, "Helmholtz_MatrixFree_Quad"),
769 OperatorKey(eTriangle, eHelmholtz, eMatrixFree, false),
770 Helmholtz_MatrixFree::create, "Helmholtz_MatrixFree_Tri"),
772 OperatorKey(eHexahedron, eHelmholtz, eMatrixFree, false),
773 Helmholtz_MatrixFree::create, "Helmholtz_MatrixFree_Hex"),
775 OperatorKey(ePrism, eHelmholtz, eMatrixFree, false),
776 Helmholtz_MatrixFree::create, "Helmholtz_MatrixFree_Prism"),
778 OperatorKey(ePyramid, eHelmholtz, eMatrixFree, false),
779 Helmholtz_MatrixFree::create, "Helmholtz_MatrixFree_Pyr"),
781 OperatorKey(eTetrahedron, eHelmholtz, eMatrixFree, false),
782 Helmholtz_MatrixFree::create, "Helmholtz_MatrixFree_Tet"),
783};
784
785} // 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 ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
#define OPERATOR_CREATE(cname)
Definition Operator.h:43
Helmholtz help class to calculate the size of the collection that is given as an input and as an outp...
Helmholtz operator using LocalRegions implementation.
void operator()(int dir, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp) final
void UpdateFactors(StdRegions::FactorMap factors) override
Check the validity of supplied constant factors.
void UpdateVarcoeffs(StdRegions::VarCoeffMap &varcoeffs) override
Check the validity of supplied variable coefficients. Note that the m_varcoeffs are not implemented f...
const StdRegions::ConstFactorType m_factorCoeffDef[3][3]
Helmholtz_IterPerExp(vector< LocalRegions::ExpansionSharedPtr > pCollExp, CoalescedGeomDataSharedPtr pGeomData, StdRegions::FactorMap factors)
Helmholtz operator using matrix free operators.
Helmholtz_MatrixFree(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
void UpdateVarcoeffs(StdRegions::VarCoeffMap &varcoeffs) override
Check the validity of supplied variable coefficients. Note that the m_varcoeffs are not implemented f...
std::shared_ptr< MatrixFree::Helmholtz > m_oper
void UpdateFactors(StdRegions::FactorMap factors) override
Update the supplied factor map.
Helmholtz operator using LocalRegions implementation.
void UpdateVarcoeffs(StdRegions::VarCoeffMap &varcoeffs) override
Update the supplied variable coefficients.
void operator()(int dir, const Array< OneD, const NekDouble > &input, Array< OneD, NekDouble > &output, Array< OneD, NekDouble > &wsp) final
void UpdateFactors(StdRegions::FactorMap factors) override
Update the supplied factor map.
Helmholtz_NoCollection(vector< LocalRegions::ExpansionSharedPtr > pCollExp, CoalescedGeomDataSharedPtr pGeomData, StdRegions::FactorMap factors)
vector< LocalRegions::ExpansionSharedPtr > m_expList
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.
std::tuple< LibUtilities::ShapeType, OperatorType, ImplementationType, ExpansionIsNodal > OperatorKey
Key for describing an Operator.
Definition Operator.h:120
std::shared_ptr< CoalescedGeomData > CoalescedGeomDataSharedPtr
OperatorFactory & GetOperatorFactory()
Returns the singleton Operator factory object.
Definition Operator.cpp:44
static FactorMap NullFactorMap
const char *const ConstFactorTypeMap[]
VarCoeffMap RestrictCoeffMap(const VarCoeffMap &m, size_t offset, size_t cnt)
ConstFactorMap FactorMap
static VarCoeffMap NullVarCoeffMap
std::map< StdRegions::VarCoeffType, VarCoeffEntry > VarCoeffMap
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
STL namespace.