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