Nektar++
Expansion2D.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: Expansion2D.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: File for Expansion2D routines
32//
33///////////////////////////////////////////////////////////////////////////////
34
42#include <LocalRegions/SegExp.h>
45
46using namespace std;
47
49{
51 : StdExpansion(), Expansion(pGeom), StdExpansion2D()
52{
53}
54
56{
57 DNekScalMatSharedPtr returnval;
59
61 "Geometric information is not set up");
62
63 switch (mkey.GetMatrixType())
64 {
66 {
67 if ((m_metricinfo->GetGtype() == SpatialDomains::eDeformed) ||
69 {
70 NekDouble one = 1.0;
71 DNekMatSharedPtr mat = GenMatrix(mkey);
72
73 returnval =
75 }
76 else
77 {
78 NekDouble jac = (m_metricinfo->GetJac(ptsKeys))[0];
80
81 returnval =
83 }
84 }
85 break;
87 {
88 MatrixKey masskey(mkey, StdRegions::eMass);
89 DNekScalMat &MassMat = *GetLocMatrix(masskey);
90
91 // Generate a local copy of traceMat
94
96 "Need to specify eFactorGJP to construct "
97 "a HelmholtzGJP matrix");
98
100
101 factor /= MassMat.Scale();
102
103 int ntot = MassMat.GetRows() * MassMat.GetColumns();
104
105 Vmath::Svtvp(ntot, factor, &NDTraceMat->GetPtr()[0], 1,
106 MassMat.GetRawPtr(), 1, &NDTraceMat->GetPtr()[0], 1);
107
109 MassMat.Scale(), NDTraceMat);
110 }
111 break;
113 {
114 if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
115 {
116 NekDouble one = 1.0;
118 DetShapeType(), *this);
119 DNekMatSharedPtr mat = GenMatrix(masskey);
120 mat->Invert();
121
122 returnval =
124 }
125 else
126 {
127 NekDouble fac = 1.0 / (m_metricinfo->GetJac(ptsKeys))[0];
128 DNekMatSharedPtr mat = GetStdMatrix(mkey);
129
130 returnval =
132 }
133 }
134 break;
138 {
139 if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed ||
147 {
148 NekDouble one = 1.0;
149 DNekMatSharedPtr mat = GenMatrix(mkey);
150
151 returnval =
153 }
154 else
155 {
156 NekDouble jac = (m_metricinfo->GetJac(ptsKeys))[0];
158 m_metricinfo->GetDerivFactors(ptsKeys);
159 int dir = 0;
161 {
162 dir = 0;
163 }
165 {
166 dir = 1;
167 }
169 {
170 dir = 2;
171 }
172
174 mkey.GetShapeType(), *this);
176 mkey.GetShapeType(), *this);
177
178 DNekMat &deriv0 = *GetStdMatrix(deriv0key);
179 DNekMat &deriv1 = *GetStdMatrix(deriv1key);
180
181 int rows = deriv0.GetRows();
182 int cols = deriv1.GetColumns();
183
184 DNekMatSharedPtr WeakDeriv =
186 (*WeakDeriv) =
187 df[2 * dir][0] * deriv0 + df[2 * dir + 1][0] * deriv1;
188
190 jac, WeakDeriv);
191 }
192 }
193 break;
195 {
196 if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed ||
197 mkey.GetNVarCoeff())
198 {
199 NekDouble one = 1.0;
200 DNekMatSharedPtr mat = GenMatrix(mkey);
201
202 returnval =
204 }
205 else
206 {
207 int shapedim = 2;
208
209 // dfdirxi = tan_{xi_x} * d \xi/dx
210 // + tan_{xi_y} * d \xi/dy
211 // + tan_{xi_z} * d \xi/dz
212 // dfdireta = tan_{eta_x} * d \eta/dx
213 // + tan_{xi_y} * d \xi/dy
214 // + tan_{xi_z} * d \xi/dz
215 NekDouble jac = (m_metricinfo->GetJac(ptsKeys))[0];
217 m_metricinfo->GetDerivFactors(ptsKeys);
218
219 Array<OneD, NekDouble> direction =
221
222 // d / dx = df[0]*deriv0 + df[1]*deriv1
223 // d / dy = df[2]*deriv0 + df[3]*deriv1
224 // d / dz = df[4]*deriv0 + df[5]*deriv1
225
226 // dfdir[dir] = e \cdot (d/dx, d/dy, d/dz)
227 // = (e^0 * df[0] + e^1 * df[2]
228 // + e^2 * df[4]) * deriv0
229 // + (e^0 * df[1] + e^1 * df[3]
230 // + e^2 * df[5]) * deriv1
231 // dfdir[dir] = e^0 * df[2 * 0 + dir]
232 // + e^1 * df[2 * 1 + dir]
233 // + e^2 * df [ 2 * 2 + dir]
234 Array<OneD, Array<OneD, NekDouble>> dfdir(shapedim);
235 Expansion::ComputeGmatcdotMF(df, direction, dfdir);
236
239
240 dfdirxi[StdRegions::eVarCoeffWeakDeriv] = dfdir[0];
241 dfdireta[StdRegions::eVarCoeffWeakDeriv] = dfdir[1];
242
244 mkey.GetShapeType(), *this,
247 mkey.GetShapeType(), *this,
249
250 DNekMat &derivxi = *GetStdMatrix(derivxikey);
251 DNekMat &deriveta = *GetStdMatrix(derivetakey);
252
253 int rows = derivxi.GetRows();
254 int cols = deriveta.GetColumns();
255
256 DNekMatSharedPtr WeakDirDeriv =
258
259 (*WeakDirDeriv) = derivxi + deriveta;
260
261 // Add (\nabla \cdot e^k ) Mass
263 DiveMass[StdRegions::eVarCoeffMass] =
265 StdRegions::StdMatrixKey stdmasskey(
266 StdRegions::eMass, mkey.GetShapeType(), *this,
268
269 DNekMatSharedPtr DiveMassmat = GetStdMatrix(stdmasskey);
270
271 (*WeakDirDeriv) = (*WeakDirDeriv) + (*DiveMassmat);
272
274 jac, WeakDirDeriv);
275 }
276 break;
277 }
279 {
280 if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed ||
292 {
293 NekDouble one = 1.0;
294 DNekMatSharedPtr mat = GenMatrix(mkey);
295
296 returnval =
298 }
299 else
300 {
302 mkey.GetShapeType(), *this);
304 mkey.GetShapeType(), *this);
306 mkey.GetShapeType(), *this);
307
308 DNekMat &lap00 = *GetStdMatrix(lap00key);
309 DNekMat &lap01 = *GetStdMatrix(lap01key);
310 DNekMat &lap11 = *GetStdMatrix(lap11key);
311
312 NekDouble jac = (m_metricinfo->GetJac(ptsKeys))[0];
314 m_metricinfo->GetGmat(ptsKeys);
315
316 int rows = lap00.GetRows();
317 int cols = lap00.GetColumns();
318
319 DNekMatSharedPtr lap =
321
322 (*lap) = gmat[0][0] * lap00 +
323 gmat[1][0] * (lap01 + Transpose(lap01)) +
324 gmat[3][0] * lap11;
325
326 returnval =
328 }
329 }
330 break;
332 {
333 DNekMatSharedPtr mat = GenMatrix(mkey);
334
336 }
337 break;
339 {
341
342 MatrixKey masskey(mkey, StdRegions::eMass);
343 DNekScalMat &MassMat = *GetLocMatrix(masskey);
344
345 MatrixKey lapkey(mkey, StdRegions::eLaplacian);
346 DNekScalMat &LapMat = *GetLocMatrix(lapkey);
347
348 int rows = LapMat.GetRows();
349 int cols = LapMat.GetColumns();
350
351 DNekMatSharedPtr helm =
353
354 NekDouble one = 1.0;
355 (*helm) = LapMat + factor * MassMat;
356
357 returnval =
359 }
360 break;
362 {
363 MatrixKey helmkey(mkey, StdRegions::eHelmholtz);
364 DNekScalMat &HelmMat = *GetLocMatrix(helmkey);
365
366 // Generate a local copy of traceMat
369
371 "Need to specify eFactorGJP to construct "
372 "a HelmholtzGJP matrix");
373
375
376 factor /= HelmMat.Scale();
377
378 int ntot = HelmMat.GetRows() * HelmMat.GetColumns();
379
380 Vmath::Svtvp(ntot, factor, &NDTraceMat->GetPtr()[0], 1,
381 HelmMat.GetRawPtr(), 1, &NDTraceMat->GetPtr()[0], 1);
382
384 HelmMat.Scale(), NDTraceMat);
385 }
386 break;
388 {
390
391 // Construct mass matrix
392 // Check for mass-specific varcoeffs to avoid unncessary
393 // re-computation of the elemental matrix every time step
396 {
397 massVarcoeffs[StdRegions::eVarCoeffMass] =
399 }
400 MatrixKey masskey(StdRegions::eMass, mkey.GetShapeType(), *this,
401 mkey.GetConstFactors(), massVarcoeffs);
402 DNekScalMat &MassMat = *GetLocMatrix(masskey);
403
404 // Construct laplacian matrix (Check for varcoeffs)
405 // Take all varcoeffs if one or more are detected
406 // TODO We might want to have a map
407 // from MatrixType to Vector of Varcoeffs and vice-versa
419 {
420 lapVarcoeffs = mkey.GetVarCoeffs();
421 }
422 MatrixKey lapkey(StdRegions::eLaplacian, mkey.GetShapeType(), *this,
423 mkey.GetConstFactors(), lapVarcoeffs);
424 DNekScalMat &LapMat = *GetLocMatrix(lapkey);
425
426 // Construct advection matrix
427 // Check for varcoeffs not required;
428 // assume advection velocity is always time-dependent
430 DNekScalMat &AdvMat = *GetLocMatrix(advkey);
431
432 int rows = LapMat.GetRows();
433 int cols = LapMat.GetColumns();
434
435 DNekMatSharedPtr adr =
437
438 NekDouble one = 1.0;
439 (*adr) = LapMat - lambda * MassMat + AdvMat;
440
442
443 // Clear memory for time-dependent matrices
444 DropLocMatrix(advkey);
445 if (!massVarcoeffs.empty())
446 {
447 DropLocMatrix(masskey);
448 }
449 if (!lapVarcoeffs.empty())
450 {
451 DropLocMatrix(lapkey);
452 }
453 }
454 break;
456 {
457 // Copied mostly from ADR solve to have fine-grain control
458 // over updating only advection matrix, relevant for performance!
460
461 // Construct mass matrix (Check for varcoeffs)
464 {
465 massVarcoeffs[StdRegions::eVarCoeffMass] =
467 }
468 MatrixKey masskey(StdRegions::eMass, mkey.GetShapeType(), *this,
469 mkey.GetConstFactors(), massVarcoeffs);
470 DNekScalMat &MassMat = *GetLocMatrix(masskey);
471
472 // Construct laplacian matrix (Check for varcoeffs)
484 {
485 lapVarcoeffs = mkey.GetVarCoeffs();
486 }
487 MatrixKey lapkey(StdRegions::eLaplacian, mkey.GetShapeType(), *this,
488 mkey.GetConstFactors(), lapVarcoeffs);
489 DNekScalMat &LapMat = *GetLocMatrix(lapkey);
490
491 // Construct advection matrix
492 // (assume advection velocity defined and non-zero)
493 // Could check L2(AdvectionVelocity) or HasVarCoeff
495 DNekScalMat &AdvMat = *GetLocMatrix(advkey);
496
497 // Generate a local copy of traceMat
499 *this, mkey.GetConstFactors());
500 DNekScalMat &NDTraceMat = *GetLocMatrix(gjpkey);
501
504 "Need to specify eFactorGJP to construct "
505 "a LinearAdvectionDiffusionReactionGJP matrix");
506
507 int rows = LapMat.GetRows();
508 int cols = LapMat.GetColumns();
509
510 DNekMatSharedPtr adr =
512
513 NekDouble one = 1.0;
514 (*adr) =
515 LapMat - lambda * MassMat + AdvMat + gjpfactor * NDTraceMat;
516
518
519 // Clear memory
520 DropLocMatrix(advkey);
521 DropLocMatrix(masskey);
522 DropLocMatrix(lapkey);
523 }
524 break;
526 {
527 NekDouble one = 1.0;
529
531 }
532 break;
534 {
535 if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
536 {
537 NekDouble one = 1.0;
538 DNekMatSharedPtr mat = GenMatrix(mkey);
539
540 returnval =
542 }
543 else
544 {
545 NekDouble jac = (m_metricinfo->GetJac(ptsKeys))[0];
546 DNekMatSharedPtr mat = GetStdMatrix(mkey);
547
548 returnval =
550 }
551 }
552 break;
556 {
557 if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
558 {
559 NekDouble one = 1.0;
560 DNekMatSharedPtr mat = GenMatrix(mkey);
561
562 returnval =
564 }
565 else
566 {
567 NekDouble jac = (m_metricinfo->GetJac(ptsKeys))[0];
568
570 m_metricinfo->GetDerivFactors(ptsKeys);
571 int dir = 0;
573 {
574 dir = 0;
575 }
577 {
578 dir = 1;
579 }
581 {
582 dir = 2;
583 }
584
586 mkey.GetShapeType(), *this);
588 mkey.GetShapeType(), *this);
589
590 DNekMat &stdiprod0 = *GetStdMatrix(iProdDeriv0Key);
591 DNekMat &stdiprod1 = *GetStdMatrix(iProdDeriv0Key);
592
593 int rows = stdiprod0.GetRows();
594 int cols = stdiprod1.GetColumns();
595
596 DNekMatSharedPtr mat =
598 (*mat) =
599 df[2 * dir][0] * stdiprod0 + df[2 * dir + 1][0] * stdiprod1;
600
601 returnval =
603 }
604 }
605 break;
606
608 {
609 NekDouble one = 1.0;
610
612 *this, mkey.GetConstFactors(), mkey.GetVarCoeffs());
613
614 DNekMatSharedPtr mat = GenMatrix(hkey);
615
616 mat->Invert();
617
619 }
620 break;
622 {
624 "Matrix only setup for quad elements currently");
625 DNekMatSharedPtr m_Ix;
626 Array<OneD, NekDouble> coords(1, 0.0);
628 int edge = static_cast<int>(factors[StdRegions::eFactorGaussEdge]);
629
630 coords[0] = (edge == 0 || edge == 3) ? -1.0 : 1.0;
631
632 m_Ix = m_base[(edge + 1) % 2]->GetI(coords);
633
634 returnval =
636 }
637 break;
639 {
640 NekDouble one = 1.0;
642 *this, mkey.GetConstFactors(),
643 mkey.GetVarCoeffs());
644 DNekScalBlkMatSharedPtr helmStatCond =
645 GetLocStaticCondMatrix(helmkey);
646 DNekScalMatSharedPtr A = helmStatCond->GetBlock(0, 0);
648
650 }
651 break;
652 default:
653 {
654 NekDouble one = 1.0;
655 DNekMatSharedPtr mat = GenMatrix(mkey);
656
658 }
659 break;
660 }
661
662 return returnval;
663}
664
666 const int edge, const ExpansionSharedPtr &EdgeExp,
669{
670 ASSERTL1(GetCoordim() == 2, "Routine only set up for two-dimensions");
671
673 GetTraceNormal(edge);
674
675 if (m_requireNeg.size() == 0)
676 {
677 int nedges = GetNtraces();
678 m_requireNeg.resize(nedges);
679
680 for (int i = 0; i < nedges; ++i)
681 {
682 m_requireNeg[i] = false;
683
684 ExpansionSharedPtr edgeExp = m_traceExp[i].lock();
685
686 if (edgeExp->GetRightAdjacentElementExp())
687 {
688 if (edgeExp->GetRightAdjacentElementExp()
689 ->GetGeom()
690 ->GetGlobalID() == GetGeom()->GetGlobalID())
691 {
692 m_requireNeg[i] = true;
693 }
694 }
695 }
696 }
697
698 // We allow the case of mixed polynomial order by supporting only
699 // those modes on the edge common to both adjoining elements. This
700 // is enforced here by taking the minimum size and padding with
701 // zeros.
702 int nquad_e = min(EdgeExp->GetNumPoints(0), int(normals[0].size()));
703
704 int nEdgePts = EdgeExp->GetTotPoints();
705 Array<OneD, NekDouble> edgePhys(nEdgePts);
706 Vmath::Vmul(nquad_e, normals[0], 1, Fx, 1, edgePhys, 1);
707 Vmath::Vvtvp(nquad_e, normals[1], 1, Fy, 1, edgePhys, 1, edgePhys, 1);
708
709 Expansion1DSharedPtr locExp = EdgeExp->as<Expansion1D>();
710
711 if (m_requireNeg[edge])
712 {
713 if (locExp->GetRightAdjacentElementExp()->GetGeom()->GetGlobalID() ==
714 m_geom->GetGlobalID())
715 {
716 Vmath::Neg(nquad_e, edgePhys, 1);
717 }
718 }
719
720 AddEdgeNormBoundaryInt(edge, EdgeExp, edgePhys, outarray);
721}
722
724 const int edge, const ExpansionSharedPtr &EdgeExp,
726{
727 int i;
728
729 if (m_requireNeg.size() == 0)
730 {
731 int nedges = GetNtraces();
732 m_requireNeg.resize(nedges);
733
734 for (i = 0; i < nedges; ++i)
735 {
736 m_requireNeg[i] = false;
737
738 ExpansionSharedPtr edgeExp = m_traceExp[i].lock();
739
740 if (edgeExp->GetRightAdjacentElementExp())
741 {
742 if (edgeExp->GetRightAdjacentElementExp()
743 ->GetGeom()
744 ->GetGlobalID() == GetGeom()->GetGlobalID())
745 {
746 m_requireNeg[i] = true;
747 }
748 }
749 }
750 }
751
753 GetBasisNumModes(1), 0, edge, GetTraceOrient(edge));
754
756
757 // Order of the element
758 int order_e = map->size();
759 // Order of the trace
760 int n_coeffs = EdgeExp->GetNcoeffs();
761
762 Array<OneD, NekDouble> edgeCoeffs(n_coeffs);
763 if (n_coeffs != order_e) // Going to orthogonal space
764 {
765 EdgeExp->FwdTrans(Fn, edgeCoeffs);
766 Expansion1DSharedPtr locExp = EdgeExp->as<Expansion1D>();
767
768 if (m_requireNeg[edge])
769 {
770 Vmath::Neg(n_coeffs, edgeCoeffs, 1);
771 }
772
773 Array<OneD, NekDouble> coeff(n_coeffs, 0.0);
775 ((LibUtilities::BasisType)1); // 1-->Ortho_A
776 LibUtilities::BasisKey bkey_ortho(btype,
777 EdgeExp->GetBasis(0)->GetNumModes(),
778 EdgeExp->GetBasis(0)->GetPointsKey());
779 LibUtilities::BasisKey bkey(EdgeExp->GetBasis(0)->GetBasisType(),
780 EdgeExp->GetBasis(0)->GetNumModes(),
781 EdgeExp->GetBasis(0)->GetPointsKey());
782 LibUtilities::InterpCoeff1D(bkey, edgeCoeffs, bkey_ortho, coeff);
783
784 // Cutting high frequencies
785 for (i = order_e; i < n_coeffs; i++)
786 {
787 coeff[i] = 0.0;
788 }
789
790 LibUtilities::InterpCoeff1D(bkey_ortho, coeff, bkey, edgeCoeffs);
791
793 LibUtilities::eSegment, *EdgeExp);
794 EdgeExp->MassMatrixOp(edgeCoeffs, edgeCoeffs, masskey);
795 }
796 else
797 {
798 EdgeExp->IProductWRTBase(Fn, edgeCoeffs);
799
800 Expansion1DSharedPtr locExp = EdgeExp->as<Expansion1D>();
801
802 if (m_requireNeg[edge])
803 {
804 Vmath::Neg(n_coeffs, edgeCoeffs, 1);
805 }
806 }
807
808 // Implementation for all the basis except Gauss points
809 if (EdgeExp->GetBasis(0)->GetBasisType() != LibUtilities::eGauss_Lagrange)
810 {
811 // add data to outarray if forward edge normal is outwards
812 for (i = 0; i < order_e; ++i)
813 {
814 outarray[(*map)[i].index] += (*map)[i].sign * edgeCoeffs[i];
815 }
816 }
817 else
818 {
819 int nCoeffs0, nCoeffs1;
820 int j;
821
825 *this, factors);
826
827 DNekMatSharedPtr mat_gauss = m_stdMatrixManager[key];
828
829 switch (edge)
830 {
831 case 0:
832 {
833 nCoeffs1 = m_base[1]->GetNumModes();
834
835 for (i = 0; i < order_e; ++i)
836 {
837 for (j = 0; j < nCoeffs1; j++)
838 {
839 outarray[(*map)[i].index + j * order_e] +=
840 mat_gauss->GetPtr()[j] * (*map)[i].sign *
841 edgeCoeffs[i];
842 }
843 }
844 break;
845 }
846 case 1:
847 {
848 nCoeffs0 = m_base[0]->GetNumModes();
849
850 for (i = 0; i < order_e; ++i)
851 {
852 for (j = 0; j < nCoeffs0; j++)
853 {
854 outarray[(*map)[i].index - j] +=
855 mat_gauss->GetPtr()[order_e - 1 - j] *
856 (*map)[i].sign * edgeCoeffs[i];
857 }
858 }
859 break;
860 }
861 case 2:
862 {
863 nCoeffs1 = m_base[1]->GetNumModes();
864
865 for (i = 0; i < order_e; ++i)
866 {
867 for (j = 0; j < nCoeffs1; j++)
868 {
869 outarray[(*map)[i].index - j * order_e] +=
870 mat_gauss->GetPtr()[order_e - 1 - j] *
871 (*map)[i].sign * edgeCoeffs[i];
872 }
873 }
874 break;
875 }
876 case 3:
877 {
878 nCoeffs0 = m_base[0]->GetNumModes();
879
880 for (i = 0; i < order_e; ++i)
881 {
882 for (j = 0; j < nCoeffs0; j++)
883 {
884 outarray[(*map)[i].index + j] +=
885 mat_gauss->GetPtr()[j] * (*map)[i].sign *
886 edgeCoeffs[i];
887 }
888 }
889 break;
890 }
891 default:
892 ASSERTL0(false, "edge value (< 3) is out of range");
893 break;
894 }
895 }
896}
897
900{
901 int i, cnt = 0;
902 int nedges = GetNtraces();
904
905 for (i = 0; i < nedges; ++i)
906 {
907 EdgeExp[i]->SetCoeffsToOrientation(
908 GetTraceOrient(i), e_tmp = inout + cnt, e_tmp = inout + cnt);
909 cnt += GetTraceNcoeffs(i);
910 }
911}
912
913/**
914 * Computes the C matrix entries due to the presence of the identity
915 * matrix in Eqn. 32.
916 */
920 Array<OneD, NekDouble> &outarray,
921 const StdRegions::VarCoeffMap &varcoeffs)
922{
923 int i, e, cnt;
924 int order_e, nquad_e;
925 int nedges = GetNtraces();
926
927 cnt = 0;
928 for (e = 0; e < nedges; ++e)
929 {
930 order_e = EdgeExp[e]->GetNcoeffs();
931 nquad_e = EdgeExp[e]->GetNumPoints(0);
932
935 Array<OneD, NekDouble> edgeCoeffs(order_e);
936 Array<OneD, NekDouble> edgePhys(nquad_e);
937
938 for (i = 0; i < order_e; ++i)
939 {
940 edgeCoeffs[i] = inarray[i + cnt];
941 }
942 cnt += order_e;
943
944 EdgeExp[e]->BwdTrans(edgeCoeffs, edgePhys);
945
946 // Multiply by variable coefficient
947 /// @TODO: Document this
948 // StdRegions::VarCoeffType VarCoeff[3] = {StdRegions::eVarCoeffD00,
949 // StdRegions::eVarCoeffD11,
950 // StdRegions::eVarCoeffD22};
951 // StdRegions::VarCoeffMap::const_iterator x;
952 // Array<OneD, NekDouble> varcoeff_work(nquad_e);
953
954 // if ((x = varcoeffs.find(VarCoeff[dir])) != varcoeffs.end())
955 // {
956 // GetPhysEdgeVarCoeffsFromElement(e,EdgeExp[e],x->second,varcoeff_work);
957 // Vmath::Vmul(nquad_e,varcoeff_work,1,EdgeExp[e]->GetPhys(),1,EdgeExp[e]->UpdatePhys(),1);
958 // }
959
960 if (varcoeffs.find(StdRegions::eVarCoeffMF1x) != varcoeffs.end())
961 {
962 // MMF case
963 Array<OneD, NekDouble> ncdotMF_e =
964 GetnEdgecdotMF(dir, e, EdgeExp[e], normals, varcoeffs);
965
966 Vmath::Vmul(nquad_e, ncdotMF_e, 1, edgePhys, 1, edgePhys, 1);
967 }
968 else
969 {
970 Vmath::Vmul(nquad_e, normals[dir], 1, edgePhys, 1, edgePhys, 1);
971 }
972
973 AddEdgeBoundaryInt(e, EdgeExp[e], edgePhys, outarray, varcoeffs);
974 }
975}
976
978 const int dir, Array<OneD, ExpansionSharedPtr> &EdgeExp,
979 Array<OneD, Array<OneD, NekDouble>> &edgeCoeffs,
980 Array<OneD, NekDouble> &outarray)
981{
982 int e;
983 int nquad_e;
984 int nedges = GetNtraces();
985
986 for (e = 0; e < nedges; ++e)
987 {
988 nquad_e = EdgeExp[e]->GetNumPoints(0);
989
990 Array<OneD, NekDouble> edgePhys(nquad_e);
993
994 EdgeExp[e]->BwdTrans(edgeCoeffs[e], edgePhys);
995
996 Vmath::Vmul(nquad_e, normals[dir], 1, edgePhys, 1, edgePhys, 1);
997
998 AddEdgeBoundaryInt(e, EdgeExp[e], edgePhys, outarray);
999 }
1000}
1001
1002/**
1003 * For a given edge add the \tilde{F}_1j contributions
1004 */
1006 ExpansionSharedPtr &EdgeExp,
1007 Array<OneD, NekDouble> &edgePhys,
1008 Array<OneD, NekDouble> &outarray,
1009 const StdRegions::VarCoeffMap &varcoeffs)
1010{
1011 int i;
1012 int order_e = EdgeExp->GetNcoeffs();
1013 int nquad_e = EdgeExp->GetNumPoints(0);
1016 Array<OneD, NekDouble> coeff(order_e);
1017
1018 GetTraceToElementMap(edge, map, sign, v_GetTraceOrient(edge));
1019
1023 StdRegions::VarCoeffMap::const_iterator x;
1024
1025 /// @TODO Variable coeffs
1026 if ((x = varcoeffs.find(VarCoeff[0])) != varcoeffs.end())
1027 {
1028 Array<OneD, NekDouble> work(nquad_e);
1029 GetPhysEdgeVarCoeffsFromElement(edge, EdgeExp, x->second.GetValue(),
1030 work);
1031 Vmath::Vmul(nquad_e, work, 1, edgePhys, 1, edgePhys, 1);
1032 }
1033
1034 EdgeExp->IProductWRTBase(edgePhys, coeff);
1035
1036 // add data to out array
1037 for (i = 0; i < order_e; ++i)
1038 {
1039 outarray[map[i]] += sign[i] * coeff[i];
1040 }
1041}
1042
1043// This method assumes that data in EdgeExp is orientated according to
1044// elemental counter clockwise format AddHDGHelmholtzTraceTerms with
1045// directions
1047 const NekDouble tau, const Array<OneD, const NekDouble> &inarray,
1049 const StdRegions::VarCoeffMap &dirForcing, Array<OneD, NekDouble> &outarray)
1050{
1051 ASSERTL0(&inarray[0] != &outarray[0],
1052 "Input and output arrays use the same memory");
1053
1054 int e, cnt, order_e, nedges = GetNtraces();
1056
1057 cnt = 0;
1058
1059 for (e = 0; e < nedges; ++e)
1060 {
1061 order_e = EdgeExp[e]->GetNcoeffs();
1062 Array<OneD, NekDouble> edgeCoeffs(order_e);
1063 Array<OneD, NekDouble> edgePhys(EdgeExp[e]->GetTotPoints());
1064
1065 Vmath::Vcopy(order_e, tmp = inarray + cnt, 1, edgeCoeffs, 1);
1066 EdgeExp[e]->BwdTrans(edgeCoeffs, edgePhys);
1067 AddHDGHelmholtzEdgeTerms(tau, e, EdgeExp, edgePhys, dirForcing,
1068 outarray);
1069
1070 cnt += order_e;
1071 }
1072}
1073
1074// evaluate additional terms in HDG edges. Not that this assumes that
1075// edges are unpacked into local cartesian order.
1077 const NekDouble tau, const int edge,
1079 const StdRegions::VarCoeffMap &varcoeffs, Array<OneD, NekDouble> &outarray)
1080{
1081 bool mmf = (varcoeffs.find(StdRegions::eVarCoeffMF1x) != varcoeffs.end());
1082 int i, j, n;
1083 int nquad_e = EdgeExp[edge]->GetNumPoints(0);
1084 int order_e = EdgeExp[edge]->GetNcoeffs();
1085 int coordim = mmf ? 2 : GetCoordim();
1086 int ncoeffs = GetNcoeffs();
1087
1088 Array<OneD, NekDouble> inval(nquad_e);
1089 Array<OneD, NekDouble> outcoeff(order_e);
1090 Array<OneD, NekDouble> tmpcoeff(ncoeffs);
1091
1093 GetTraceNormal(edge);
1094
1097
1099
1100 DNekVec Coeffs(ncoeffs, outarray, eWrapper);
1101 DNekVec Tmpcoeff(ncoeffs, tmpcoeff, eWrapper);
1102
1103 GetTraceToElementMap(edge, emap, sign, edgedir);
1104
1108
1112
1113 StdRegions::VarCoeffMap::const_iterator x;
1114 /// @TODO: What direction to use here??
1115 if ((x = varcoeffs.find(VarCoeff[0])) != varcoeffs.end())
1116 {
1117 Array<OneD, NekDouble> work(nquad_e);
1118 GetPhysEdgeVarCoeffsFromElement(edge, EdgeExp[edge],
1119 x->second.GetValue(), work);
1120 Vmath::Vmul(nquad_e, work, 1, edgePhys, 1, edgePhys, 1);
1121 }
1122
1123 //================================================================
1124 // Add F = \tau <phi_i,in_phys>
1125 // Fill edge and take inner product
1126 EdgeExp[edge]->IProductWRTBase(edgePhys, outcoeff);
1127 // add data to out array
1128 for (i = 0; i < order_e; ++i)
1129 {
1130 outarray[emap[i]] += sign[i] * tau * outcoeff[i];
1131 }
1132 //================================================================
1133
1134 //===============================================================
1135 // Add -\sum_i D_i^T M^{-1} G_i + E_i M^{-1} G_i =
1136 // \sum_i D_i M^{-1} G_i term
1137
1138 // Two independent direction
1139 DNekScalMatSharedPtr invMass;
1140 for (n = 0; n < coordim; ++n)
1141 {
1142 if (mmf)
1143 {
1145 Weight[StdRegions::eVarCoeffMass] = GetMFMag(n, varcoeffs);
1146
1147 MatrixKey invMasskey(StdRegions::eInvMass, DetShapeType(), *this,
1149
1150 invMass = GetLocMatrix(invMasskey);
1151
1152 Array<OneD, NekDouble> ncdotMF_e =
1153 GetnEdgecdotMF(n, edge, EdgeExp[edge], normals, varcoeffs);
1154
1155 Vmath::Vmul(nquad_e, ncdotMF_e, 1, edgePhys, 1, inval, 1);
1156 }
1157 else
1158 {
1159 Vmath::Vmul(nquad_e, normals[n], 1, edgePhys, 1, inval, 1);
1161 }
1162
1163 // Multiply by variable coefficient
1164 /// @TODO: Document this (probably not needed)
1165 // StdRegions::VarCoeffMap::const_iterator x;
1166 // if ((x = varcoeffs.find(VarCoeff[n])) !=
1167 // varcoeffs.end())
1168 // {
1169 // GetPhysEdgeVarCoeffsFromElement(edge,EdgeExp[edge],x->second,varcoeff_work);
1170 // Vmath::Vmul(nquad_e,varcoeff_work,1,EdgeExp[edge]->GetPhys(),1,EdgeExp[edge]->UpdatePhys(),1);
1171 // }
1172
1173 EdgeExp[edge]->IProductWRTBase(inval, outcoeff);
1174
1175 // M^{-1} G
1176 for (i = 0; i < ncoeffs; ++i)
1177 {
1178 tmpcoeff[i] = 0;
1179 for (j = 0; j < order_e; ++j)
1180 {
1181 tmpcoeff[i] += (*invMass)(i, emap[j]) * sign[j] * outcoeff[j];
1182 }
1183 }
1184
1185 if (mmf)
1186 {
1187 StdRegions::VarCoeffMap VarCoeffDirDeriv;
1188 VarCoeffDirDeriv[StdRegions::eVarCoeffMF] =
1189 GetMF(n, coordim, varcoeffs);
1190 VarCoeffDirDeriv[StdRegions::eVarCoeffMFDiv] =
1191 GetMFDiv(n, varcoeffs);
1192
1195 VarCoeffDirDeriv);
1196
1197 DNekScalMat &Dmat = *GetLocMatrix(Dmatkey);
1198
1199 Coeffs = Coeffs + Dmat * Tmpcoeff;
1200 }
1201 else
1202 {
1203 if (varcoeffs.find(VarCoeff[n]) != varcoeffs.end())
1204 {
1205 MatrixKey mkey(DerivType[n], DetShapeType(), *this,
1207
1208 DNekScalMat &Dmat = *GetLocMatrix(mkey);
1209 Coeffs = Coeffs + Dmat * Tmpcoeff;
1210 }
1211 else
1212 {
1213 DNekScalMat &Dmat = *GetLocMatrix(DerivType[n]);
1214 Coeffs = Coeffs + Dmat * Tmpcoeff;
1215 }
1216 }
1217 }
1218}
1219
1220/**
1221 * Extracts the variable coefficients along an edge
1222 */
1224 const int edge, ExpansionSharedPtr &EdgeExp,
1225 const Array<OneD, const NekDouble> &varcoeff,
1226 Array<OneD, NekDouble> &outarray)
1227{
1229 Array<OneD, NekDouble> edgetmp(EdgeExp->GetNcoeffs());
1230
1231 // FwdTrans varcoeffs
1232 FwdTrans(varcoeff, tmp);
1233
1234 // Map to edge
1238 GetTraceToElementMap(edge, emap, sign, edgedir);
1239
1240 for (unsigned int i = 0; i < EdgeExp->GetNcoeffs(); ++i)
1241 {
1242 edgetmp[i] = tmp[emap[i]];
1243 }
1244
1245 // BwdTrans
1246 EdgeExp->BwdTrans(edgetmp, outarray);
1247}
1248
1249/**
1250 * Computes matrices needed for the HDG formulation. References to
1251 * equations relate to the following paper:
1252 * R. M. Kirby, S. J. Sherwin, B. Cockburn, To CG or to HDG: A
1253 * Comparative Study, J. Sci. Comp P1-30
1254 * DOI 10.1007/s10915-011-9501-7
1255 */
1257{
1258 DNekMatSharedPtr returnval;
1259
1260 switch (mkey.GetMatrixType())
1261 {
1262 // (Z^e)^{-1} (Eqn. 33, P22)
1264 {
1266 "HybridDGHelmholtz matrix not set up "
1267 "for non boundary-interior expansions");
1268
1269 int i, j, k;
1270 NekDouble lambdaval =
1273 int ncoeffs = GetNcoeffs();
1274 int nedges = GetNtraces();
1275 int shapedim = 2;
1276 const StdRegions::VarCoeffMap &varcoeffs = mkey.GetVarCoeffs();
1277 bool mmf =
1278 (varcoeffs.find(StdRegions::eVarCoeffMF1x) != varcoeffs.end());
1279
1283 ExpansionSharedPtr EdgeExp;
1284
1285 int order_e, coordim = GetCoordim();
1290 DNekMat LocMat(ncoeffs, ncoeffs);
1291
1292 returnval =
1294 DNekMat &Mat = *returnval;
1295 Vmath::Zero(ncoeffs * ncoeffs, Mat.GetPtr(), 1);
1296
1300
1301 StdRegions::VarCoeffMap::const_iterator x;
1302
1303 for (i = 0; i < coordim; ++i)
1304 {
1305 if (mmf)
1306 {
1307 if (i < shapedim)
1308 {
1309 StdRegions::VarCoeffMap VarCoeffDirDeriv;
1310 VarCoeffDirDeriv[StdRegions::eVarCoeffMF] =
1311 GetMF(i, shapedim, varcoeffs);
1312 VarCoeffDirDeriv[StdRegions::eVarCoeffMFDiv] =
1313 GetMFDiv(i, varcoeffs);
1314
1316 DetShapeType(), *this,
1318 VarCoeffDirDeriv);
1319
1320 DNekScalMat &Dmat = *GetLocMatrix(Dmatkey);
1321
1324 GetMFMag(i, mkey.GetVarCoeffs());
1325
1326 MatrixKey invMasskey(
1329
1330 DNekScalMat &invMass = *GetLocMatrix(invMasskey);
1331
1332 Mat = Mat + Dmat * invMass * Transpose(Dmat);
1333 }
1334 }
1335 else if (mkey.HasVarCoeff(Coeffs[i]))
1336 {
1337 MatrixKey DmatkeyL(DerivType[i], DetShapeType(), *this,
1339 mkey.GetVarCoeffAsMap(Coeffs[i]));
1340
1341 MatrixKey DmatkeyR(DerivType[i], DetShapeType(), *this);
1342
1343 DNekScalMat &DmatL = *GetLocMatrix(DmatkeyL);
1344 DNekScalMat &DmatR = *GetLocMatrix(DmatkeyR);
1345 Mat = Mat + DmatL * invMass * Transpose(DmatR);
1346 }
1347 else
1348 {
1349 DNekScalMat &Dmat = *GetLocMatrix(DerivType[i]);
1350 Mat = Mat + Dmat * invMass * Transpose(Dmat);
1351 }
1352 }
1353
1354 // Add Mass Matrix Contribution for Helmholtz problem
1356 Mat = Mat + lambdaval * Mass;
1357
1358 // Add tau*E_l using elemental mass matrices on each edge
1359 for (i = 0; i < nedges; ++i)
1360 {
1361 EdgeExp = GetTraceExp(i);
1362 order_e = EdgeExp->GetNcoeffs();
1363
1364 int nq = EdgeExp->GetNumPoints(0);
1365 GetTraceToElementMap(i, emap, sign, edgedir);
1366
1367 // @TODO: Document
1368 StdRegions::VarCoeffMap edgeVarCoeffs;
1370 {
1373 i, EdgeExp, mkey.GetVarCoeff(StdRegions::eVarCoeffD00),
1374 mu);
1375 edgeVarCoeffs[StdRegions::eVarCoeffMass] = mu;
1376 }
1377 DNekScalMat &eMass = *EdgeExp->GetLocMatrix(
1379 edgeVarCoeffs);
1380 // DNekScalMat &eMass =
1381 // *EdgeExp->GetLocMatrix(StdRegions::eMass);
1382
1383 for (j = 0; j < order_e; ++j)
1384 {
1385 for (k = 0; k < order_e; ++k)
1386 {
1387 Mat(emap[j], emap[k]) =
1388 Mat(emap[j], emap[k]) +
1389 tau * sign[j] * sign[k] * eMass(j, k);
1390 }
1391 }
1392 }
1393 }
1394 break;
1395 // U^e (P22)
1397 {
1398 int i, j, k;
1399 int nbndry = NumDGBndryCoeffs();
1400 int ncoeffs = GetNcoeffs();
1401 int nedges = GetNtraces();
1403
1404 Array<OneD, NekDouble> lambda(nbndry);
1405 DNekVec Lambda(nbndry, lambda, eWrapper);
1406 Array<OneD, NekDouble> ulam(ncoeffs);
1407 DNekVec Ulam(ncoeffs, ulam, eWrapper);
1408 Array<OneD, NekDouble> f(ncoeffs);
1409 DNekVec F(ncoeffs, f, eWrapper);
1410
1411 Array<OneD, ExpansionSharedPtr> EdgeExp(nedges);
1412 // declare matrix space
1413 returnval =
1415 DNekMat &Umat = *returnval;
1416
1417 // Z^e matrix
1419 *this, mkey.GetConstFactors(),
1420 mkey.GetVarCoeffs());
1421 DNekScalMat &invHmat = *GetLocMatrix(newkey);
1422
1425
1426 for (i = 0; i < nedges; ++i)
1427 {
1428 EdgeExp[i] = GetTraceExp(i);
1429 }
1430
1431 // for each degree of freedom of the lambda space
1432 // calculate Umat entry
1433 // Generate Lambda to U_lambda matrix
1434 for (j = 0; j < nbndry; ++j)
1435 {
1436 // standard basis vectors e_j
1437 Vmath::Zero(nbndry, &lambda[0], 1);
1438 Vmath::Zero(ncoeffs, &f[0], 1);
1439 lambda[j] = 1.0;
1440
1441 SetTraceToGeomOrientation(EdgeExp, lambda);
1442
1443 // Compute F = [I D_1 M^{-1} D_2 M^{-1}] C e_j
1444 AddHDGHelmholtzTraceTerms(tau, lambda, EdgeExp,
1445 mkey.GetVarCoeffs(), f);
1446
1447 // Compute U^e_j
1448 Ulam = invHmat * F; // generate Ulam from lambda
1449
1450 // fill column of matrix
1451 for (k = 0; k < ncoeffs; ++k)
1452 {
1453 Umat(k, j) = Ulam[k];
1454 }
1455 }
1456 }
1457 break;
1458 // Q_0, Q_1, Q_2 matrices (P23)
1459 // Each are a product of a row of Eqn 32 with the C matrix.
1460 // Rather than explicitly computing all of Eqn 32, we note each
1461 // row is almost a multiple of U^e, so use that as our starting
1462 // point.
1466 {
1467 int i = 0;
1468 int j = 0;
1469 int k = 0;
1470 int dir = 0;
1471 int nbndry = NumDGBndryCoeffs();
1472 int ncoeffs = GetNcoeffs();
1473 int nedges = GetNtraces();
1474 int shapedim = 2;
1475
1476 Array<OneD, NekDouble> lambda(nbndry);
1477 DNekVec Lambda(nbndry, lambda, eWrapper);
1478 Array<OneD, ExpansionSharedPtr> EdgeExp(nedges);
1479
1480 Array<OneD, NekDouble> ulam(ncoeffs);
1481 DNekVec Ulam(ncoeffs, ulam, eWrapper);
1482 Array<OneD, NekDouble> f(ncoeffs);
1483 DNekVec F(ncoeffs, f, eWrapper);
1484
1485 // declare matrix space
1486 returnval =
1488 DNekMat &Qmat = *returnval;
1489
1490 // Lambda to U matrix
1492 *this, mkey.GetConstFactors(),
1493 mkey.GetVarCoeffs());
1494 DNekScalMat &lamToU = *GetLocMatrix(lamToUkey);
1495
1496 // Inverse mass matrix
1498
1499 for (i = 0; i < nedges; ++i)
1500 {
1501 EdgeExp[i] = GetTraceExp(i);
1502 }
1503
1504 // Weak Derivative matrix
1506 switch (mkey.GetMatrixType())
1507 {
1509 dir = 0;
1511 break;
1513 dir = 1;
1515 break;
1517 dir = 2;
1519 break;
1520 default:
1521 ASSERTL0(false, "Direction not known");
1522 break;
1523 }
1524
1525 const StdRegions::VarCoeffMap &varcoeffs = mkey.GetVarCoeffs();
1526 if (varcoeffs.find(StdRegions::eVarCoeffMF1x) != varcoeffs.end())
1527 {
1528 StdRegions::VarCoeffMap VarCoeffDirDeriv;
1529 VarCoeffDirDeriv[StdRegions::eVarCoeffMF] =
1530 GetMF(dir, shapedim, varcoeffs);
1531 VarCoeffDirDeriv[StdRegions::eVarCoeffMFDiv] =
1532 GetMFDiv(dir, varcoeffs);
1533
1534 MatrixKey Dmatkey(
1536 StdRegions::NullConstFactorMap, VarCoeffDirDeriv);
1537
1538 Dmat = GetLocMatrix(Dmatkey);
1539
1542 GetMFMag(dir, mkey.GetVarCoeffs());
1543
1546 Weight);
1547
1548 invMass = *GetLocMatrix(invMasskey);
1549 }
1550 else
1551 {
1555
1556 Dmat = GetLocMatrix(DerivType[dir]);
1557
1559 *this);
1560 invMass = *GetLocMatrix(invMasskey);
1561 }
1562
1563 // for each degree of freedom of the lambda space
1564 // calculate Qmat entry
1565 // Generate Lambda to Q_lambda matrix
1566 for (j = 0; j < nbndry; ++j)
1567 {
1568 Vmath::Zero(nbndry, &lambda[0], 1);
1569 lambda[j] = 1.0;
1570
1571 // for lambda[j] = 1 this is the solution to ulam
1572 for (k = 0; k < ncoeffs; ++k)
1573 {
1574 Ulam[k] = lamToU(k, j);
1575 }
1576
1577 // -D^T ulam
1578 Vmath::Neg(ncoeffs, &ulam[0], 1);
1579 F = Transpose(*Dmat) * Ulam;
1580
1581 SetTraceToGeomOrientation(EdgeExp, lambda);
1582
1583 // Add the C terms resulting from the I's on the
1584 // diagonals of Eqn 32
1585 AddNormTraceInt(dir, lambda, EdgeExp, f, mkey.GetVarCoeffs());
1586
1587 // finally multiply by inverse mass matrix
1588 Ulam = invMass * F;
1589
1590 // fill column of matrix (Qmat is in column major format)
1591 Vmath::Vcopy(ncoeffs, &ulam[0], 1,
1592 &(Qmat.GetPtr())[0] + j * ncoeffs, 1);
1593 }
1594 }
1595 break;
1596 // Matrix K (P23)
1598 {
1599 int i, j, e, cnt;
1600 int order_e, nquad_e;
1601 int nbndry = NumDGBndryCoeffs();
1602 int coordim = GetCoordim();
1603 int nedges = GetNtraces();
1605 StdRegions::VarCoeffMap::const_iterator x;
1606 const StdRegions::VarCoeffMap &varcoeffs = mkey.GetVarCoeffs();
1607 bool mmf =
1608 (varcoeffs.find(StdRegions::eVarCoeffMF1x) != varcoeffs.end());
1609
1610 Array<OneD, NekDouble> work, varcoeff_work;
1612 Array<OneD, ExpansionSharedPtr> EdgeExp(nedges);
1613 Array<OneD, NekDouble> lam(nbndry);
1614
1618
1619 // declare matrix space
1620 returnval =
1622 DNekMat &BndMat = *returnval;
1623
1624 DNekScalMatSharedPtr LamToQ[3];
1625
1626 // Matrix to map Lambda to U
1628 *this, mkey.GetConstFactors(),
1629 mkey.GetVarCoeffs());
1630 DNekScalMat &LamToU = *GetLocMatrix(LamToUkey);
1631
1632 // Matrix to map Lambda to Q0
1634 *this, mkey.GetConstFactors(),
1635 mkey.GetVarCoeffs());
1636 LamToQ[0] = GetLocMatrix(LamToQ0key);
1637
1638 // Matrix to map Lambda to Q1
1640 *this, mkey.GetConstFactors(),
1641 mkey.GetVarCoeffs());
1642 LamToQ[1] = GetLocMatrix(LamToQ1key);
1643
1644 // Matrix to map Lambda to Q2 for 3D coordinates
1645 if (coordim == 3)
1646 {
1647 MatrixKey LamToQ2key(
1649 mkey.GetConstFactors(), mkey.GetVarCoeffs());
1650 LamToQ[2] = GetLocMatrix(LamToQ2key);
1651 }
1652
1653 // Set up edge segment expansions from local geom info
1654 for (i = 0; i < nedges; ++i)
1655 {
1656 EdgeExp[i] = GetTraceExp(i);
1657 }
1658
1659 // Set up matrix derived from <mu, Q_lam.n - \tau (U_lam - Lam) >
1660 for (i = 0; i < nbndry; ++i)
1661 {
1662 cnt = 0;
1663
1664 Vmath::Zero(nbndry, lam, 1);
1665 lam[i] = 1.0;
1666 SetTraceToGeomOrientation(EdgeExp, lam);
1667
1668 for (e = 0; e < nedges; ++e)
1669 {
1670 order_e = EdgeExp[e]->GetNcoeffs();
1671 nquad_e = EdgeExp[e]->GetNumPoints(0);
1672
1673 normals = GetTraceNormal(e);
1674 edgedir = GetTraceOrient(e);
1675
1676 work = Array<OneD, NekDouble>(nquad_e);
1677 varcoeff_work = Array<OneD, NekDouble>(nquad_e);
1678
1679 GetTraceToElementMap(e, emap, sign, edgedir);
1680
1681 StdRegions::VarCoeffType VarCoeff[3] = {
1684
1685 // Q0 * n0 (BQ_0 terms)
1686 Array<OneD, NekDouble> edgeCoeffs(order_e);
1687 Array<OneD, NekDouble> edgePhys(nquad_e);
1688 for (j = 0; j < order_e; ++j)
1689 {
1690 edgeCoeffs[j] = sign[j] * (*LamToQ[0])(emap[j], i);
1691 }
1692
1693 EdgeExp[e]->BwdTrans(edgeCoeffs, edgePhys);
1694 // @TODO Var coeffs
1695 // Multiply by variable coefficient
1696 // if ((x =
1697 // varcoeffs.find(VarCoeff[0]))
1698 // != varcoeffs.end())
1699 // {
1700 // GetPhysEdgeVarCoeffsFromElement(e,EdgeExp[e],x->second,varcoeff_work);
1701 // Vmath::Vmul(nquad_e,varcoeff_work,1,EdgeExp[e]->GetPhys(),1,EdgeExp[e]->UpdatePhys(),1);
1702 // }
1703 if (mmf)
1704 {
1706 0, e, EdgeExp[e], normals, varcoeffs);
1707 Vmath::Vmul(nquad_e, ncdotMF, 1, edgePhys, 1, work, 1);
1708 }
1709 else
1710 {
1711 Vmath::Vmul(nquad_e, normals[0], 1, edgePhys, 1, work,
1712 1);
1713 }
1714
1715 // Q1 * n1 (BQ_1 terms)
1716 for (j = 0; j < order_e; ++j)
1717 {
1718 edgeCoeffs[j] = sign[j] * (*LamToQ[1])(emap[j], i);
1719 }
1720
1721 EdgeExp[e]->BwdTrans(edgeCoeffs, edgePhys);
1722
1723 // @TODO var coeffs
1724 // Multiply by variable coefficients
1725 // if ((x =
1726 // varcoeffs.find(VarCoeff[1]))
1727 // != varcoeffs.end())
1728 // {
1729 // GetPhysEdgeVarCoeffsFromElement(e,EdgeExp[e],x->second,varcoeff_work);
1730 // Vmath::Vmul(nquad_e,varcoeff_work,1,EdgeExp[e]->GetPhys(),1,EdgeExp[e]->UpdatePhys(),1);
1731 // }
1732
1733 if (mmf)
1734 {
1736 1, e, EdgeExp[e], normals, varcoeffs);
1737 Vmath::Vvtvp(nquad_e, ncdotMF, 1, edgePhys, 1, work, 1,
1738 work, 1);
1739 }
1740 else
1741 {
1742 Vmath::Vvtvp(nquad_e, normals[1], 1, edgePhys, 1, work,
1743 1, work, 1);
1744 }
1745
1746 // Q2 * n2 (BQ_2 terms)
1747 if (coordim == 3)
1748 {
1749 for (j = 0; j < order_e; ++j)
1750 {
1751 edgeCoeffs[j] = sign[j] * (*LamToQ[2])(emap[j], i);
1752 }
1753
1754 EdgeExp[e]->BwdTrans(edgeCoeffs, edgePhys);
1755 // @TODO var coeffs
1756 // Multiply by variable coefficients
1757 // if ((x =
1758 // varcoeffs.find(VarCoeff[2]))
1759 // != varcoeffs.end())
1760 // {
1761 // GetPhysEdgeVarCoeffsFromElement(e,EdgeExp[e],x->second,varcoeff_work);
1762 // Vmath::Vmul(nquad_e,varcoeff_work,1,EdgeExp[e]->GetPhys(),1,EdgeExp[e]->UpdatePhys(),1);
1763 // }
1764
1765 Vmath::Vvtvp(nquad_e, normals[2], 1, edgePhys, 1, work,
1766 1, work, 1);
1767 }
1768
1769 // - tau (ulam - lam)
1770 // Corresponds to the G and BU terms.
1771 for (j = 0; j < order_e; ++j)
1772 {
1773 edgeCoeffs[j] =
1774 sign[j] * LamToU(emap[j], i) - lam[cnt + j];
1775 }
1776
1777 EdgeExp[e]->BwdTrans(edgeCoeffs, edgePhys);
1778
1779 // Multiply by variable coefficients
1780 if ((x = varcoeffs.find(VarCoeff[0])) != varcoeffs.end())
1781 {
1783 e, EdgeExp[e], x->second.GetValue(), varcoeff_work);
1784 Vmath::Vmul(nquad_e, varcoeff_work, 1, edgePhys, 1,
1785 edgePhys, 1);
1786 }
1787
1788 Vmath::Svtvp(nquad_e, -tau, edgePhys, 1, work, 1, work, 1);
1789 /// TODO: Add variable coeffs
1790 EdgeExp[e]->IProductWRTBase(work, edgeCoeffs);
1791
1792 EdgeExp[e]->SetCoeffsToOrientation(edgedir, edgeCoeffs,
1793 edgeCoeffs);
1794
1795 for (j = 0; j < order_e; ++j)
1796 {
1797 BndMat(cnt + j, i) = edgeCoeffs[j];
1798 }
1799
1800 cnt += order_e;
1801 }
1802 }
1803 }
1804 break;
1805 // HDG postprocessing
1807 {
1809 mkey.GetConstFactors(), mkey.GetVarCoeffs());
1810 DNekScalMat &LapMat = *GetLocMatrix(lapkey);
1811
1813 LapMat.GetRows(), LapMat.GetColumns());
1814 DNekMatSharedPtr lmat = returnval;
1815
1816 (*lmat) = LapMat;
1817
1818 // replace first column with inner product wrt 1
1819 int nq = GetTotPoints();
1820 Array<OneD, NekDouble> tmp(nq);
1822 Vmath::Fill(nq, 1.0, tmp, 1);
1823 IProductWRTBase(tmp, outarray);
1824
1825 Vmath::Vcopy(m_ncoeffs, &outarray[0], 1, &(lmat->GetPtr())[0], 1);
1826 lmat->Invert();
1827 }
1828 break;
1830 {
1831 int ntraces = GetNtraces();
1832 int ncoords = GetCoordim();
1833 int nphys = GetTotPoints();
1835 Array<OneD, NekDouble> phys(nphys);
1836 returnval =
1838 DNekMat &Mat = *returnval;
1839 Vmath::Zero(m_ncoeffs * m_ncoeffs, Mat.GetPtr(), 1);
1840
1842
1843 for (int d = 0; d < ncoords; ++d)
1844 {
1845 Deriv[d] = Array<OneD, NekDouble>(nphys);
1846 }
1847
1848 Array<OneD, int> tracepts(ntraces);
1849 Array<OneD, ExpansionSharedPtr> traceExp(ntraces);
1850 int maxtpts = 0;
1851 for (int t = 0; t < ntraces; ++t)
1852 {
1853 traceExp[t] = GetTraceExp(t);
1854 tracepts[t] = traceExp[t]->GetTotPoints();
1855 maxtpts = (maxtpts > tracepts[t]) ? maxtpts : tracepts[t];
1856 }
1857
1858 Array<OneD, NekDouble> val(maxtpts), tmp, tmp1;
1859
1860 Array<OneD, Array<OneD, NekDouble>> dphidn(ntraces);
1861 for (int t = 0; t < ntraces; ++t)
1862 {
1863 dphidn[t] =
1864 Array<OneD, NekDouble>(m_ncoeffs * tracepts[t], 0.0);
1865 }
1866
1867 for (int i = 0; i < m_ncoeffs; ++i)
1868 {
1869 FillMode(i, phys);
1870 PhysDeriv(phys, Deriv[0], Deriv[1], Deriv[2]);
1871
1872 for (int t = 0; t < ntraces; ++t)
1873 {
1874 const NormalVector norm = GetTraceNormal(t);
1875
1878 traceExp[t]->GetBasis(0)->GetBasisKey();
1879 bool DoInterp = (fromkey != tokey);
1880
1881 Array<OneD, NekDouble> n(tracepts[t]);
1882 ;
1883 for (int d = 0; d < ncoords; ++d)
1884 {
1885 // if variable p may need to interpolate
1886 if (DoInterp)
1887 {
1888 LibUtilities::Interp1D(fromkey, norm[d], tokey, n);
1889 }
1890 else
1891 {
1892 n = norm[d];
1893 }
1894
1895 GetTracePhysVals(t, traceExp[t], Deriv[d], val,
1896 v_GetTraceOrient(t));
1897
1898 Vmath::Vvtvp(tracepts[t], n, 1, val, 1,
1899 tmp = dphidn[t] + i * tracepts[t], 1,
1900 tmp1 = dphidn[t] + i * tracepts[t], 1);
1901 }
1902 }
1903 }
1904
1905 for (int t = 0; t < ntraces; ++t)
1906 {
1907 int nt = tracepts[t];
1908 NekDouble h, p;
1909 TraceNormLen(t, h, p);
1910
1911 // scaling from GJP paper
1912 NekDouble scale =
1913 (p == 1) ? 0.02 * h * h : 0.8 * pow(p + 1, -4.0) * h * h;
1914
1915 for (int i = 0; i < m_ncoeffs; ++i)
1916 {
1917 for (int j = i; j < m_ncoeffs; ++j)
1918 {
1919 Vmath::Vmul(nt, dphidn[t] + i * nt, 1,
1920 dphidn[t] + j * nt, 1, val, 1);
1921 Mat(i, j) =
1922 Mat(i, j) + scale * traceExp[t]->Integral(val);
1923 }
1924 }
1925 }
1926
1927 // fill in symmetric components.
1928 for (int i = 0; i < m_ncoeffs; ++i)
1929 {
1930 for (int j = 0; j < i; ++j)
1931 {
1932 Mat(i, j) = Mat(j, i);
1933 }
1934 }
1935 }
1936 break;
1937 default:
1938 ASSERTL0(false,
1939 "This matrix type cannot be generated from this class");
1940 break;
1941 }
1942
1943 return returnval;
1944}
1945
1946// Evaluate Coefficients of weak deriviative in the direction dir
1947// given the input coefficicents incoeffs and the imposed
1948// boundary values in EdgeExp (which will have its phys space updated);
1950 const Array<OneD, const NekDouble> &incoeffs,
1952 Array<OneD, Array<OneD, NekDouble>> &edgeCoeffs,
1954{
1958
1959 int ncoeffs = GetNcoeffs();
1960
1962 DNekScalMat &Dmat = *GetLocMatrix(DerivType[dir]);
1963
1964 Array<OneD, NekDouble> coeffs = incoeffs;
1965 DNekVec Coeffs(ncoeffs, coeffs, eWrapper);
1966
1967 Coeffs = Transpose(Dmat) * Coeffs;
1968 Vmath::Neg(ncoeffs, coeffs, 1);
1969
1970 // Add the boundary integral including the relevant part of
1971 // the normal
1972 AddNormTraceInt(dir, EdgeExp, edgeCoeffs, coeffs);
1973
1974 DNekVec Out_d(ncoeffs, out_d, eWrapper);
1975
1976 Out_d = InvMass * Coeffs;
1977}
1978
1980{
1985
1987 const int edge, const Array<OneD, const NekDouble> &primCoeffs,
1988 DNekMatSharedPtr &inoutmat)
1989{
1991 "Not set up for non boundary-interior expansions");
1992 ASSERTL1(inoutmat->GetRows() == inoutmat->GetColumns(),
1993 "Assuming that input matrix was square");
1994 int i, j;
1995 int id1, id2;
1996 ExpansionSharedPtr edgeExp = m_traceExp[edge].lock();
1997 int order_e = edgeExp->GetNcoeffs();
1998
2001
2002 StdRegions::VarCoeffMap varcoeffs;
2003 varcoeffs[StdRegions::eVarCoeffMass] = primCoeffs;
2004
2007 varcoeffs);
2008 DNekScalMat &edgemat = *edgeExp->GetLocMatrix(mkey);
2009
2010 // Now need to identify a map which takes the local edge
2011 // mass matrix to the matrix stored in inoutmat;
2012 // This can currently be deduced from the size of the matrix
2013
2014 // - if inoutmat.m_rows() == v_NCoeffs() it is a full
2015 // matrix system
2016
2017 // - if inoutmat.m_rows() == v_NumBndCoeffs() it is a
2018 // boundary CG system
2019
2020 // - if inoutmat.m_rows() == v_NumDGBndCoeffs() it is a
2021 // trace DG system
2022 int rows = inoutmat->GetRows();
2023
2024 if (rows == GetNcoeffs())
2025 {
2026 GetTraceToElementMap(edge, map, sign, v_GetTraceOrient(edge));
2027 }
2028 else if (rows == NumBndryCoeffs())
2029 {
2030 int nbndry = NumBndryCoeffs();
2031 Array<OneD, unsigned int> bmap(nbndry);
2032
2033 GetTraceToElementMap(edge, map, sign, v_GetTraceOrient(edge));
2034
2035 GetBoundaryMap(bmap);
2036
2037 for (i = 0; i < order_e; ++i)
2038 {
2039 for (j = 0; j < nbndry; ++j)
2040 {
2041 if (map[i] == bmap[j])
2042 {
2043 map[i] = j;
2044 break;
2045 }
2046 }
2047 ASSERTL1(j != nbndry, "Did not find number in map");
2048 }
2049 }
2050 else if (rows == NumDGBndryCoeffs())
2051 {
2052 // possibly this should be a separate method
2053 int cnt = 0;
2054 map = Array<OneD, unsigned int>(order_e);
2055 sign = Array<OneD, int>(order_e, 1);
2056
2057 for (i = 0; i < edge; ++i)
2058 {
2059 cnt += GetTraceNcoeffs(i);
2060 }
2061
2062 for (i = 0; i < order_e; ++i)
2063 {
2064 map[i] = cnt++;
2065 }
2066 // check for mapping reversal
2068 {
2069 switch (edgeExp->GetBasis(0)->GetBasisType())
2070 {
2072 reverse(map.get(), map.get() + order_e);
2073 break;
2075 reverse(map.get(), map.get() + order_e);
2076 break;
2078 {
2079 swap(map[0], map[1]);
2080 for (i = 3; i < order_e; i += 2)
2081 {
2082 sign[i] = -1;
2083 }
2084 }
2085 break;
2086 default:
2087 ASSERTL0(false,
2088 "Edge boundary type not valid for this method");
2089 }
2090 }
2091 }
2092 else
2093 {
2094 ASSERTL0(false, "Could not identify matrix type from dimension");
2095 }
2096
2097 for (i = 0; i < order_e; ++i)
2098 {
2099 id1 = map[i];
2100 for (j = 0; j < order_e; ++j)
2101 {
2102 id2 = map[j];
2103 (*inoutmat)(id1, id2) += edgemat(i, j) * sign[i] * sign[j];
2104 }
2105 }
2106}
2107
2108/**
2109 * Given an edge and vector of element coefficients:
2110 * - maps those elemental coefficients corresponding to the edge into
2111 * an edge-vector.
2112 * - resets the element coefficients
2113 * - multiplies the edge vector by the edge mass matrix
2114 * - maps the edge coefficients back onto the elemental coefficients
2115 */
2117 const int edgeid, const Array<OneD, const NekDouble> &primCoeffs,
2118 const Array<OneD, NekDouble> &incoeffs, Array<OneD, NekDouble> &coeffs)
2119{
2121 "Not set up for non boundary-interior expansions");
2122 int i;
2123 ExpansionSharedPtr edgeExp = m_traceExp[edgeid].lock();
2124 int order_e = edgeExp->GetNcoeffs();
2125
2128
2129 StdRegions::VarCoeffMap varcoeffs;
2130 varcoeffs[StdRegions::eVarCoeffMass] = primCoeffs;
2131
2134 varcoeffs);
2135 DNekScalMat &edgemat = *edgeExp->GetLocMatrix(mkey);
2136
2137 NekVector<NekDouble> vEdgeCoeffs(order_e);
2138
2139 GetTraceToElementMap(edgeid, map, sign, v_GetTraceOrient(edgeid));
2140
2141 for (i = 0; i < order_e; ++i)
2142 {
2143 vEdgeCoeffs[i] = incoeffs[map[i]] * sign[i];
2144 }
2145
2146 vEdgeCoeffs = edgemat * vEdgeCoeffs;
2147
2148 for (i = 0; i < order_e; ++i)
2149 {
2150 coeffs[map[i]] += vEdgeCoeffs[i] * sign[i];
2151 }
2152}
2153
2155 const DNekScalMatSharedPtr &r_bnd)
2156{
2157 MatrixStorage storage = eFULL;
2158 DNekMatSharedPtr m_vertexmatrix;
2159
2160 int nVerts, vid1, vid2, vMap1, vMap2;
2161 NekDouble VertexValue;
2162
2163 nVerts = GetNverts();
2164
2165 m_vertexmatrix =
2166 MemoryManager<DNekMat>::AllocateSharedPtr(nVerts, nVerts, 0.0, storage);
2167 DNekMat &VertexMat = (*m_vertexmatrix);
2168
2169 for (vid1 = 0; vid1 < nVerts; ++vid1)
2170 {
2171 vMap1 = GetVertexMap(vid1);
2172
2173 for (vid2 = 0; vid2 < nVerts; ++vid2)
2174 {
2175 vMap2 = GetVertexMap(vid2);
2176 VertexValue = (*r_bnd)(vMap1, vMap2);
2177 VertexMat.SetValue(vid1, vid2, VertexValue);
2178 }
2179 }
2180
2181 return m_vertexmatrix;
2182}
2183
2185{
2187 GetTraceBasisKey(traceid), m_geom->GetEdge(traceid));
2188}
2189
2191{
2192 int n, j;
2193 int nEdgeCoeffs;
2194 int nBndCoeffs = NumBndryCoeffs();
2195
2196 Array<OneD, unsigned int> bmap(nBndCoeffs);
2197 GetBoundaryMap(bmap);
2198
2199 // Map from full system to statically condensed system (i.e reverse
2200 // GetBoundaryMap)
2201 map<int, int> invmap;
2202 for (j = 0; j < nBndCoeffs; ++j)
2203 {
2204 invmap[bmap[j]] = j;
2205 }
2206
2207 // Number of interior edge coefficients
2208 nEdgeCoeffs = GetTraceNcoeffs(eid) - 2;
2209
2211
2212 Array<OneD, unsigned int> edgemaparray(nEdgeCoeffs);
2213 Array<OneD, unsigned int> maparray(nEdgeCoeffs);
2214 Array<OneD, int> signarray(nEdgeCoeffs, 1);
2215 StdRegions::Orientation eOrient = geom->GetEorient(eid);
2216
2217 // maparray is the location of the edge within the matrix
2218 GetTraceInteriorToElementMap(eid, maparray, signarray, eOrient);
2219
2220 for (n = 0; n < nEdgeCoeffs; ++n)
2221 {
2222 edgemaparray[n] = invmap[maparray[n]];
2223 }
2224
2225 return edgemaparray;
2226}
2227
2229{
2231}
2232
2234 Array<OneD, int> &idmap, const int nq0,
2235 [[maybe_unused]] const int nq1)
2236{
2237 if (idmap.size() != nq0)
2238 {
2239 idmap = Array<OneD, int>(nq0);
2240 }
2241 switch (orient)
2242 {
2244 // Fwd
2245 for (int i = 0; i < nq0; ++i)
2246 {
2247 idmap[i] = i;
2248 }
2249 break;
2251 {
2252 // Bwd
2253 for (int i = 0; i < nq0; ++i)
2254 {
2255 idmap[i] = nq0 - 1 - i;
2256 }
2257 }
2258 break;
2259 default:
2260 ASSERTL0(false, "Unknown orientation");
2261 break;
2262 }
2263}
2264
2265// Compute edgenormal \cdot vector
2267 const int dir, const int edge, ExpansionSharedPtr &EdgeExp_e,
2268 const Array<OneD, const Array<OneD, NekDouble>> &normals,
2269 const StdRegions::VarCoeffMap &varcoeffs)
2270{
2271 int nquad_e = EdgeExp_e->GetNumPoints(0);
2272 int coordim = GetCoordim();
2273 int nquad0 = m_base[0]->GetNumPoints();
2274 int nquad1 = m_base[1]->GetNumPoints();
2275 int nqtot = nquad0 * nquad1;
2276
2277 StdRegions::VarCoeffType MMFCoeffs[15] = {
2286
2287 StdRegions::VarCoeffMap::const_iterator MFdir;
2288
2289 Array<OneD, NekDouble> ncdotMF(nqtot, 0.0);
2290 Array<OneD, NekDouble> tmp(nqtot);
2291 Array<OneD, NekDouble> tmp_e(nquad_e);
2292 for (int k = 0; k < coordim; k++)
2293 {
2294 MFdir = varcoeffs.find(MMFCoeffs[dir * 5 + k]);
2295 tmp = MFdir->second.GetValue();
2296
2297 GetPhysEdgeVarCoeffsFromElement(edge, EdgeExp_e, tmp, tmp_e);
2298
2299 Vmath::Vvtvp(nquad_e, &tmp_e[0], 1, &normals[k][0], 1, &ncdotMF[0], 1,
2300 &ncdotMF[0], 1);
2301 }
2302 return ncdotMF;
2303}
2304
2306 const Array<OneD, Array<OneD, NekDouble>> &vec)
2307{
2309 GetLeftAdjacentElementExp()->GetTraceNormal(
2311
2312 int nq = GetTotPoints();
2314 Vmath::Vmul(nq, &vec[0][0], 1, &normals[0][0], 1, &Fn[0], 1);
2315 Vmath::Vvtvp(nq, &vec[1][0], 1, &normals[1][0], 1, &Fn[0], 1, &Fn[0], 1);
2316 Vmath::Vvtvp(nq, &vec[2][0], 1, &normals[2][0], 1, &Fn[0], 1, &Fn[0], 1);
2317
2318 return StdExpansion::Integral(Fn);
2319}
2320
2322{
2324
2325 int nverts = geom->GetNumVerts();
2326
2327 // vertices on edges
2328 SpatialDomains::PointGeom ev0 = *geom->GetVertex(traceid);
2329 SpatialDomains::PointGeom ev1 = *geom->GetVertex((traceid + 1) % nverts);
2330
2331 // vertex on adjacent edge to ev0
2333 *geom->GetVertex((traceid + (nverts - 1)) % nverts);
2334
2335 // calculate perpendicular distance of normal length
2336 // from first vertex
2337 NekDouble h1 = ev0.dist(vadj);
2339
2340 Dx.Sub(ev1, ev0);
2341 Dx1.Sub(vadj, ev0);
2342
2343 NekDouble d1 = Dx.dot(Dx1);
2344 NekDouble lenDx = Dx.dot(Dx);
2345 h = sqrt(h1 * h1 - d1 * d1 / lenDx);
2346
2347 // perpendicular distanace from second vertex
2348 SpatialDomains::PointGeom vadj1 = *geom->GetVertex((traceid + 2) % nverts);
2349
2350 h1 = ev1.dist(vadj1);
2351 Dx1.Sub(vadj1, ev1);
2352 d1 = Dx.dot(Dx1);
2353
2354 h = (h + sqrt(h1 * h1 - d1 * d1 / lenDx)) * 0.5;
2355
2356 int dirn = (geom->GetDir(traceid) == 0) ? 1 : 0;
2357
2358 p = (NekDouble)(GetBasisNumModes(dirn) - 1);
2359}
2360} // namespace Nektar::LocalRegions
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:208
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:242
#define ASSERTL2(condition, msg)
Assert Level 2 – Debugging which is used FULLDEBUG compilation mode. This level assert is designed to...
Definition: ErrorUtil.hpp:265
#define sign(a, b)
return the sign(b)*a
Definition: Polylib.cpp:47
Describes the specification for a Basis.
Definition: Basis.h:45
void v_AddEdgeNormBoundaryInt(const int edge, const ExpansionSharedPtr &EdgeExp, const Array< OneD, const NekDouble > &Fx, const Array< OneD, const NekDouble > &Fy, Array< OneD, NekDouble > &outarray) override
DNekMatSharedPtr v_GenMatrix(const StdRegions::StdMatrixKey &mkey) override
std::vector< bool > m_requireNeg
Definition: Expansion2D.h:112
void v_AddRobinTraceContribution(const int traceid, const Array< OneD, const NekDouble > &primCoeffs, const Array< OneD, NekDouble > &incoeffs, Array< OneD, NekDouble > &coeffs) override
void v_SetUpPhysNormals(const int edge) override
void v_AddRobinMassMatrix(const int edgeid, const Array< OneD, const NekDouble > &primCoeffs, DNekMatSharedPtr &inoutmat) override
Array< OneD, NekDouble > GetnEdgecdotMF(const int dir, const int edge, ExpansionSharedPtr &EdgeExp_e, const Array< OneD, const Array< OneD, NekDouble > > &normals, const StdRegions::VarCoeffMap &varcoeffs)
void SetTraceToGeomOrientation(Array< OneD, ExpansionSharedPtr > &EdgeExp, Array< OneD, NekDouble > &inout)
DNekMatSharedPtr v_BuildVertexMatrix(const DNekScalMatSharedPtr &r_bnd) override
NekDouble v_VectorFlux(const Array< OneD, Array< OneD, NekDouble > > &vec) override
DNekScalMatSharedPtr CreateMatrix(const MatrixKey &mkey)
Definition: Expansion2D.cpp:55
Array< OneD, unsigned int > GetTraceInverseBoundaryMap(int eid)
void v_ReOrientTracePhysMap(const StdRegions::Orientation orient, Array< OneD, int > &idmap, const int nq0, const int nq1) override
Expansion2D(SpatialDomains::Geometry2DSharedPtr pGeom)
Definition: Expansion2D.cpp:50
void AddNormTraceInt(const int dir, Array< OneD, ExpansionSharedPtr > &EdgeExp, Array< OneD, Array< OneD, NekDouble > > &edgeCoeffs, Array< OneD, NekDouble > &outarray)
SpatialDomains::Geometry2DSharedPtr GetGeom2D() const
Definition: Expansion2D.h:164
void AddHDGHelmholtzEdgeTerms(const NekDouble tau, const int edge, Array< OneD, ExpansionSharedPtr > &EdgeExp, Array< OneD, NekDouble > &edgePhys, const StdRegions::VarCoeffMap &dirForcing, Array< OneD, NekDouble > &outarray)
void v_DGDeriv(const int dir, const Array< OneD, const NekDouble > &incoeffs, Array< OneD, ExpansionSharedPtr > &EdgeExp, Array< OneD, Array< OneD, NekDouble > > &edgeCoeffs, Array< OneD, NekDouble > &out_d) override
void v_TraceNormLen(const int traceid, NekDouble &h, NekDouble &p) override
void GetPhysEdgeVarCoeffsFromElement(const int edge, ExpansionSharedPtr &EdgeExp, const Array< OneD, const NekDouble > &varcoeff, Array< OneD, NekDouble > &outarray)
void AddEdgeBoundaryInt(const int edge, ExpansionSharedPtr &EdgeExp, Array< OneD, NekDouble > &edgePhys, Array< OneD, NekDouble > &outarray, const StdRegions::VarCoeffMap &varcoeffs=StdRegions::NullVarCoeffMap)
void AddHDGHelmholtzTraceTerms(const NekDouble tau, const Array< OneD, const NekDouble > &inarray, Array< OneD, ExpansionSharedPtr > &EdgeExp, const StdRegions::VarCoeffMap &dirForcing, Array< OneD, NekDouble > &outarray)
void v_GenTraceExp(const int traceid, ExpansionSharedPtr &exp) override
SpatialDomains::GeometrySharedPtr GetGeom() const
Definition: Expansion.cpp:167
SpatialDomains::GeometrySharedPtr m_geom
Definition: Expansion.h:273
void DropLocMatrix(const LocalRegions::MatrixKey &mkey)
Definition: Expansion.cpp:90
ExpansionSharedPtr GetLeftAdjacentElementExp() const
Definition: Expansion.h:441
DNekMatSharedPtr BuildVertexMatrix(const DNekScalMatSharedPtr &r_bnd)
Definition: Expansion.cpp:101
void ComputeGmatcdotMF(const Array< TwoD, const NekDouble > &df, const Array< OneD, const NekDouble > &direction, Array< OneD, Array< OneD, NekDouble > > &dfdir)
Definition: Expansion.cpp:603
virtual void v_ComputeTraceNormal(const int id)
Definition: Expansion.cpp:868
Array< OneD, NekDouble > GetMFMag(const int dir, const StdRegions::VarCoeffMap &varcoeffs)
Definition: Expansion.cpp:709
int GetLeftAdjacentElementTrace() const
Definition: Expansion.h:454
void GetTracePhysVals(const int trace, const StdRegions::StdExpansionSharedPtr &TraceExp, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, StdRegions::Orientation orient=StdRegions::eNoOrientation)
Definition: Expansion.h:200
std::map< int, ExpansionWeakPtr > m_traceExp
Definition: Expansion.h:272
void AddEdgeNormBoundaryInt(const int edge, const std::shared_ptr< Expansion > &EdgeExp, const Array< OneD, const NekDouble > &Fx, const Array< OneD, const NekDouble > &Fy, Array< OneD, NekDouble > &outarray)
Definition: Expansion.cpp:114
SpatialDomains::GeomFactorsSharedPtr m_metricinfo
Definition: Expansion.h:274
virtual StdRegions::Orientation v_GetTraceOrient(int trace)
Definition: Expansion.cpp:813
ExpansionSharedPtr GetTraceExp(const int traceid)
Definition: Expansion.h:414
StdRegions::Orientation GetTraceOrient(int trace)
Definition: Expansion.h:168
IndexMapValuesSharedPtr GetIndexMap(const IndexMapKey &ikey)
Definition: Expansion.h:146
DNekScalMatSharedPtr GetLocMatrix(const LocalRegions::MatrixKey &mkey)
Definition: Expansion.cpp:84
Array< OneD, NekDouble > GetMFDiv(const int dir, const StdRegions::VarCoeffMap &varcoeffs)
Definition: Expansion.cpp:686
void TraceNormLen(const int traceid, NekDouble &h, NekDouble &p)
Definition: Expansion.h:250
const NormalVector & GetTraceNormal(const int id)
Definition: Expansion.cpp:251
Array< OneD, NekDouble > GetMF(const int dir, const int shapedim, const StdRegions::VarCoeffMap &varcoeffs)
Definition: Expansion.cpp:633
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
PointGeomSharedPtr GetVertex(int i) const
Returns vertex i of this object.
Definition: Geometry.h:358
void Sub(PointGeom &a, PointGeom &b)
Definition: PointGeom.cpp:122
NekDouble dot(PointGeom &a)
retun the dot product between this and input a
Definition: PointGeom.cpp:185
NekDouble dist(PointGeom &a)
return distance between this and input a
Definition: PointGeom.cpp:178
void GetBoundaryMap(Array< OneD, unsigned int > &outarray)
Definition: StdExpansion.h:669
int GetNcoeffs(void) const
This function returns the total number of coefficients used in the expansion.
Definition: StdExpansion.h:124
int GetTotPoints() const
This function returns the total number of quadrature points used in the element.
Definition: StdExpansion.h:134
void FillMode(const int mode, Array< OneD, NekDouble > &outarray)
This function fills the array outarray with the mode-th mode of the expansion.
Definition: StdExpansion.h:491
DNekMatSharedPtr GetStdMatrix(const StdMatrixKey &mkey)
Definition: StdExpansion.h:603
const LibUtilities::PointsKeyVector GetPointsKeys() const
DNekScalBlkMatSharedPtr GetLocStaticCondMatrix(const LocalRegions::MatrixKey &mkey)
Definition: StdExpansion.h:641
const LibUtilities::BasisKey GetTraceBasisKey(const int i, int k=-1) const
This function returns the basis key belonging to the i-th trace.
Definition: StdExpansion.h:299
int GetVertexMap(const int localVertexId, bool useCoeffPacking=false)
Definition: StdExpansion.h:679
void IProductWRTBase(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
this function calculates the inner product of a given function f with the different modes of the expa...
Definition: StdExpansion.h:528
int GetNtraces() const
Returns the number of trace elements connected to this element.
Definition: StdExpansion.h:351
int GetNverts() const
This function returns the number of vertices of the expansion domain.
Definition: StdExpansion.h:246
void GetTraceToElementMap(const int tid, Array< OneD, unsigned int > &maparray, Array< OneD, int > &signarray, Orientation traceOrient=eForwards, int P=-1, int Q=-1)
Definition: StdExpansion.h:684
LibUtilities::ShapeType DetShapeType() const
This function returns the shape of the expansion domain.
Definition: StdExpansion.h:367
void GetTraceInteriorToElementMap(const int tid, Array< OneD, unsigned int > &maparray, Array< OneD, int > &signarray, const Orientation traceOrient=eForwards)
Definition: StdExpansion.h:708
int GetTraceNcoeffs(const int i) const
This function returns the number of expansion coefficients belonging to the i-th trace.
Definition: StdExpansion.h:261
DNekMatSharedPtr GenMatrix(const StdMatrixKey &mkey)
Definition: StdExpansion.h:844
void FwdTrans(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
This function performs the Forward transformation from physical space to coefficient space.
LibUtilities::NekManager< StdMatrixKey, DNekMat, StdMatrixKey::opLess > m_stdMatrixManager
int GetBasisNumModes(const int dir) const
This function returns the number of expansion modes in the dir direction.
Definition: StdExpansion.h:169
void PhysDeriv(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &out_d0, Array< OneD, NekDouble > &out_d1=NullNekDouble1DArray, Array< OneD, NekDouble > &out_d2=NullNekDouble1DArray)
Definition: StdExpansion.h:849
Array< OneD, LibUtilities::BasisSharedPtr > m_base
LibUtilities::ShapeType GetShapeType() const
Definition: StdMatrixKey.h:88
const VarCoeffMap & GetVarCoeffs() const
Definition: StdMatrixKey.h:169
MatrixType GetMatrixType() const
Definition: StdMatrixKey.h:83
bool HasVarCoeff(const StdRegions::VarCoeffType &coeff) const
Definition: StdMatrixKey.h:174
const ConstFactorMap & GetConstFactors() const
Definition: StdMatrixKey.h:138
const Array< OneD, const NekDouble > & GetVarCoeff(const StdRegions::VarCoeffType &coeff) const
Definition: StdMatrixKey.h:148
NekDouble GetConstFactor(const ConstFactorType &factor) const
Definition: StdMatrixKey.h:124
bool ConstFactorExists(const ConstFactorType &factor) const
Definition: StdMatrixKey.h:133
const VarCoeffMap GetVarCoeffAsMap(const VarCoeffType &coeff) const
Definition: StdMatrixKey.h:158
void Interp1D(const BasisKey &fbasis0, const Array< OneD, const NekDouble > &from, const BasisKey &tbasis0, Array< OneD, NekDouble > &to)
this function interpolates a 1D function evaluated at the quadrature points of the basis fbasis0 to ...
Definition: Interp.cpp:47
void InterpCoeff1D(const BasisKey &fbasis0, const Array< OneD, const NekDouble > &from, const BasisKey &tbasis0, Array< OneD, NekDouble > &to)
Definition: InterpCoeff.cpp:42
std::vector< PointsKey > PointsKeyVector
Definition: Points.h:231
@ eGauss_Lagrange
Lagrange Polynomials using the Gauss points.
Definition: BasisType.h:57
@ eGLL_Lagrange
Lagrange for SEM basis .
Definition: BasisType.h:56
@ eModified_A
Principle Modified Functions .
Definition: BasisType.h:48
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:66
std::shared_ptr< IndexMapValues > IndexMapValuesSharedPtr
Definition: IndexMapKey.h:126
std::shared_ptr< Expansion1D > Expansion1DSharedPtr
Definition: Expansion1D.h:50
@ eNoGeomType
No type defined.
@ eDeformed
Geometry is curved or has non-constant factors.
std::shared_ptr< Geometry2D > Geometry2DSharedPtr
Definition: Geometry.h:62
std::shared_ptr< Geometry > GeometrySharedPtr
Definition: Geometry.h:51
@ eLinearAdvectionDiffusionReactionGJP
Definition: StdRegions.hpp:105
std::map< ConstFactorType, NekDouble > ConstFactorMap
Definition: StdRegions.hpp:430
static ConstFactorMap NullConstFactorMap
Definition: StdRegions.hpp:431
static VarCoeffMap NullVarCoeffMap
Definition: StdRegions.hpp:376
std::map< StdRegions::VarCoeffType, VarCoeffEntry > VarCoeffMap
Definition: StdRegions.hpp:375
std::vector< double > d(NPUPPER *NPUPPER)
StdRegions::ConstFactorMap factors
std::shared_ptr< DNekScalMat > DNekScalMatSharedPtr
std::shared_ptr< DNekScalBlkMat > DNekScalBlkMatSharedPtr
Definition: NekTypeDefs.hpp:79
static Array< OneD, NekDouble > NullNekDouble1DArray
NekMatrix< InnerMatrixType, BlockMatrixTag > Transpose(NekMatrix< InnerMatrixType, BlockMatrixTag > &rhs)
std::shared_ptr< DNekMat > DNekMatSharedPtr
Definition: NekTypeDefs.hpp:75
double NekDouble
void Vmul(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Multiply vector z = x*y.
Definition: Vmath.hpp:72
void Svtvp(int n, const T alpha, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Svtvp (scalar times vector plus vector): z = alpha*x + y.
Definition: Vmath.hpp:396
void Neg(int n, T *x, const int incx)
Negate x = -x.
Definition: Vmath.hpp:292
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 Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.hpp:273
void Fill(int n, const T alpha, T *x, const int incx)
Fill a vector with a constant value.
Definition: Vmath.hpp:54
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.hpp:825
STL namespace.
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:294