Nektar++
ExpList.cpp
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // File: ExpList.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: Expansion list definition
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
35 #include <iomanip>
36 
37 #include <boost/core/ignore_unused.hpp>
38 
40 #include <MultiRegions/ExpList.h>
42 
45 #include <LocalRegions/HexExp.h>
46 #include <LocalRegions/MatrixKey.h> // for MatrixKey
48 #include <LocalRegions/PointExp.h>
49 #include <LocalRegions/PrismExp.h>
50 #include <LocalRegions/PyrExp.h>
51 #include <LocalRegions/QuadExp.h>
52 #include <LocalRegions/SegExp.h>
53 #include <LocalRegions/TetExp.h>
54 #include <LocalRegions/TriExp.h>
55 
56 #include <MultiRegions/AssemblyMap/AssemblyMapCG.h> // for AssemblyMapCG, etc
57 #include <MultiRegions/AssemblyMap/AssemblyMapDG.h> // for AssemblyMapCG, etc
58 #include <MultiRegions/GlobalLinSysKey.h> // for GlobalLinSysKey
59 #include <MultiRegions/GlobalMatrix.h> // for GlobalMatrix, etc
60 #include <MultiRegions/GlobalMatrixKey.h> // for GlobalMatrixKey
61 
63 #include <LibUtilities/Foundations/ManagerAccess.h> // for PointsManager, etc
69 
71 #include <Collections/Operator.h>
72 
75 
76 using namespace std;
77 
78 namespace Nektar
79 {
80 namespace MultiRegions
81 {
82 /**
83  * @class ExpList
84  * All multi-elemental expansions \f$u^{\delta}(\boldsymbol{x})\f$ can
85  * be considered as the assembly of the various elemental contributions.
86  * On a discrete level, this yields,
87  * \f[u^{\delta}(\boldsymbol{x}_i)=\sum_{e=1}^{{N_{\mathrm{el}}}}
88  * \sum_{n=0}^{N^{e}_m-1}\hat{u}_n^e\phi_n^e(\boldsymbol{x}_i).\f]
89  * where \f${N_{\mathrm{el}}}\f$ is the number of elements and
90  * \f$N^{e}_m\f$ is the local elemental number of expansion modes.
91  * As it is the lowest level class, it contains the definition of the
92  * common data and common routines to all multi-elemental expansions.
93  *
94  * The class stores a vector of expansions, \a m_exp, (each derived from
95  * StdRegions#StdExpansion) which define the constituent components of
96  * the domain.
97  */
98 
99 /**
100  * Creates an empty expansion list.
101  */
102 ExpList::ExpList(const ExpansionType type)
103  : m_expType(type), m_ncoeffs(0), m_npoints(0), m_physState(false),
104  m_exp(MemoryManager<LocalRegions::ExpansionVector>::AllocateSharedPtr()),
105  m_blockMat(MemoryManager<BlockMatrixMap>::AllocateSharedPtr()),
106  m_WaveSpace(false)
107 {
108 }
109 
110 /*----------------------------------------------------------------*/
111 /* Copy Construtor */
112 /*-----------------------------------------------------------------*/
113 
114 /**
115  * Copies an existing expansion list.
116  * @param in Source expansion list.
117  */
118 ExpList::ExpList(const ExpList &in, const bool DeclareCoeffPhysArrays)
119  : std::enable_shared_from_this<ExpList>(in), m_expType(in.m_expType),
120 
121  m_comm(in.m_comm), m_session(in.m_session), m_graph(in.m_graph),
122  m_ncoeffs(in.m_ncoeffs), m_npoints(in.m_npoints), m_physState(false),
123  m_exp(in.m_exp), m_collections(in.m_collections),
124  m_collectionsDoInit(in.m_collectionsDoInit),
125  m_coll_coeff_offset(in.m_coll_coeff_offset),
126  m_coll_phys_offset(in.m_coll_phys_offset),
127  m_coeff_offset(in.m_coeff_offset), m_phys_offset(in.m_phys_offset),
128  m_blockMat(in.m_blockMat), m_WaveSpace(false),
129  m_elmtToExpId(in.m_elmtToExpId)
130 {
131 
132  // Set up m_coeffs, m_phys and offset arrays.
133  // use this to keep memory declaration in one place
134  SetupCoeffPhys(DeclareCoeffPhysArrays, false);
135 }
136 
137 /**
138  * Copies the eIds elements from an existing expansion list.
139  * @param in Source expansion list.
140  * @param in elements that will be in the new exp list.
141  */
142 ExpList::ExpList(const ExpList &in, const std::vector<unsigned int> &eIDs,
143  const bool DeclareCoeffPhysArrays,
144  const Collections::ImplementationType ImpType)
145  : m_expType(in.m_expType), m_comm(in.m_comm), m_session(in.m_session),
146  m_graph(in.m_graph), m_physState(false),
147  m_exp(MemoryManager<LocalRegions::ExpansionVector>::AllocateSharedPtr()),
148  m_blockMat(MemoryManager<BlockMatrixMap>::AllocateSharedPtr()),
149  m_WaveSpace(false)
150 {
151  for (int i = 0; i < eIDs.size(); ++i)
152  {
153  (*m_exp).push_back((*(in.m_exp))[eIDs[i]]);
154  }
155 
156  // Set up m_coeffs, m_phys and offset arrays.
157  SetupCoeffPhys(DeclareCoeffPhysArrays);
158 
159  // set up collections
160  CreateCollections(ImpType);
161 }
162 
163 /**
164  * Given a meshgraph \a graph, containing information about
165  * the domain and the spectral/hp element expansion, this
166  * constructor fills the list of local expansions
167  * \texttt{m_exp} with the proper expansions, calculates the
168  * total number of quadrature points \f$x_i\f$ and local
169  * expansion coefficients \f$\hat{u}^e_n\f$ and
170  *
171  * @param pSession A session within information about expansion
172  *
173  * @param graph A meshgraph, containing information about the
174  * domain and the spectral/hp element expansion.
175  *
176  * @param DeclareCoeffPhysArrays Declare the coefficient and
177  * phys space arrays
178  *
179  * @param ImpType Detail about the implementation type to use
180  * in operators
181  */
184  const bool DeclareCoeffPhysArrays, const std::string &var,
185  const Collections::ImplementationType ImpType)
186  : m_comm(pSession->GetComm()), m_session(pSession), m_graph(graph),
187  m_physState(false),
188  m_exp(MemoryManager<LocalRegions::ExpansionVector>::AllocateSharedPtr()),
189  m_blockMat(MemoryManager<BlockMatrixMap>::AllocateSharedPtr()),
190  m_WaveSpace(false)
191 {
192  // Retrieve the list of expansions
193  const SpatialDomains::ExpansionInfoMap &expansions =
194  graph->GetExpansionInfo(var);
195 
196  // Initialise Expansionn Vector
197  InitialiseExpVector(expansions);
198 
199  // Setup phys coeff space
200  SetupCoeffPhys(DeclareCoeffPhysArrays);
201 
202  // Initialise collection
203  CreateCollections(ImpType);
204 }
205 
206 /**
207  * Given an expansion vector \a expansions, containing
208  * information about the domain and the spectral/hp element
209  * expansion, this constructor fills the list of local
210  * expansions \texttt{m_exp} with the proper expansions,
211  * calculates the total number of quadrature points
212  * \f$\boldsymbol{x}_i\f$ and local expansion coefficients
213  * \f$\hat{u}^e_n\f$.
214  *
215  * @param pSession A session within information about expansion
216  * @param expansions A vector containing information about the
217  * domain and the spectral/hp element
218  * expansion.
219  * @param DeclareCoeffPhysArrays Declare the coefficient and
220  * phys space arrays
221  * @param ImpType Detail about the implementation type to use
222  * in operators
223  */
225  const SpatialDomains::ExpansionInfoMap &expansions,
226  const bool DeclareCoeffPhysArrays,
227  const Collections::ImplementationType ImpType)
228  : m_comm(pSession->GetComm()), m_session(pSession), m_physState(false),
229  m_exp(MemoryManager<LocalRegions::ExpansionVector>::AllocateSharedPtr()),
230  m_blockMat(MemoryManager<BlockMatrixMap>::AllocateSharedPtr()),
231  m_WaveSpace(false)
232 {
233 
234  // Initialise expansion vector
235  InitialiseExpVector(expansions);
236 
237  // Set up m_coeffs, m_phys and offset arrays.
238  SetupCoeffPhys(DeclareCoeffPhysArrays);
239 
240  // Setup Collection
241  CreateCollections(ImpType);
242 }
243 
244 //----------------------------------------------------------------------
245 // 0D Expansion Constructors
246 //----------------------------------------------------------------------
248  : m_expType(e0D), m_ncoeffs(1), m_npoints(1), m_physState(false),
249  m_exp(MemoryManager<LocalRegions::ExpansionVector>::AllocateSharedPtr()),
250  m_blockMat(MemoryManager<BlockMatrixMap>::AllocateSharedPtr()),
251  m_WaveSpace(false)
252 {
255  (*m_exp).push_back(Point);
256 
257  SetupCoeffPhys();
258 }
259 
260 /**
261  * Store expansions for the trace space expansions used in
262  * DisContField
263  *
264  * @param pSession A session within information about expansion
265  * @param bndConstraint Array of ExpList1D objects each containing a
266  * 1D spectral/hp element expansion on a single
267  * boundary region.
268  * @param bndCond Array of BoundaryCondition objects which contain
269  * information about the boundary conditions on the
270  * different boundary regions.
271  * @param locexp Complete domain expansion list.
272  * @param graph mesh corresponding to the expansion list.
273  * @param DeclareCoeffPhysArrays Declare the coefficient and
274  * phys space arrays
275  * @param variable The variable name associated with the expansion
276  * @param ImpType Detail about the implementation type to use
277  * in operators
278  */
280  const LibUtilities::SessionReaderSharedPtr &pSession,
281  const Array<OneD, const ExpListSharedPtr> &bndConstraint,
283  const LocalRegions::ExpansionVector &locexp,
285  const LibUtilities::CommSharedPtr &comm, const bool DeclareCoeffPhysArrays,
286  const std::string variable, const Collections::ImplementationType ImpType)
287  : m_comm(comm), m_session(pSession), m_graph(graph), m_physState(false),
288  m_exp(MemoryManager<LocalRegions::ExpansionVector>::AllocateSharedPtr()),
289  m_blockMat(MemoryManager<BlockMatrixMap>::AllocateSharedPtr()),
290  m_WaveSpace(false)
291 {
292  boost::ignore_unused(variable, ImpType);
293  int i, j, id, elmtid = 0;
294  set<int> tracesDone;
295 
302 
308 
309  // First loop over boundary conditions to reorder
310  // Dirichlet boundaries
311  for (i = 0; i < bndCond.size(); ++i)
312  {
313  if (bndCond[i]->GetBoundaryConditionType() ==
315  {
316  for (j = 0; j < bndConstraint[i]->GetExpSize(); ++j)
317  {
318  if ((exp0D =
319  std::dynamic_pointer_cast<LocalRegions::Expansion0D>(
320  bndConstraint[i]->GetExp(j))))
321  {
322  m_expType = e0D;
323 
324  PointGeom = exp0D->GetGeom()->GetVertex(0);
325  exp = MemoryManager<
326  LocalRegions::PointExp>::AllocateSharedPtr(PointGeom);
327  tracesDone.insert(PointGeom->GetVid());
328  }
329  else if ((exp1D = std::dynamic_pointer_cast<
331  bndConstraint[i]->GetExp(j))))
332  {
333  m_expType = e1D;
334 
336  exp1D->GetBasis(0)->GetBasisKey();
337  segGeom = exp1D->GetGeom1D();
338  exp =
340  bkey, segGeom);
341  tracesDone.insert(segGeom->GetGlobalID());
342  }
343  else if ((exp2D = std::dynamic_pointer_cast<
344  LocalRegions::Expansion2D>(
345  bndConstraint[i]->GetExp(j))))
346  {
347  m_expType = e2D;
348 
349  LibUtilities::BasisKey bkey0 =
350  exp2D->GetBasis(0)->GetBasisKey();
351  LibUtilities::BasisKey bkey1 =
352  exp2D->GetBasis(1)->GetBasisKey();
353  FaceGeom = exp2D->GetGeom2D();
354 
355  // if face is a quad
356  if ((QuadGeom = std::dynamic_pointer_cast<
357  SpatialDomains::QuadGeom>(FaceGeom)))
358  {
359  exp = MemoryManager<
360  LocalRegions::QuadExp>::AllocateSharedPtr(bkey0,
361  bkey1,
362  QuadGeom);
363  tracesDone.insert(QuadGeom->GetGlobalID());
364  }
365  // if face is a triangle
366  else if ((TriGeom = std::dynamic_pointer_cast<
367  SpatialDomains::TriGeom>(FaceGeom)))
368  {
369  exp = MemoryManager<
370  LocalRegions::TriExp>::AllocateSharedPtr(bkey0,
371  bkey1,
372  TriGeom);
373  tracesDone.insert(TriGeom->GetGlobalID());
374  }
375  else
376  {
378  "dynamic cast to a "
379  "proper face geometry failed");
380  }
381  }
382  // Assign next id
383  exp->SetElmtId(elmtid++);
384 
385  // Add the expansion
386  (*m_exp).push_back(exp);
387  }
388  }
389  }
390 
391  map<int, pair<SpatialDomains::Geometry1DSharedPtr, LibUtilities::BasisKey>>
392  edgeOrders;
393 
395  pair<LibUtilities::BasisKey, LibUtilities::BasisKey>>>
396  faceOrders;
397 
398  for (i = 0; i < locexp.size(); ++i)
399  {
400  if ((exp1D = std::dynamic_pointer_cast<LocalRegions::Expansion1D>(
401  locexp[i])))
402  {
403  m_expType = e0D;
404 
405  for (j = 0; j < 2; ++j)
406  {
407  PointGeom = (exp1D->GetGeom1D())->GetVertex(j);
408  id = PointGeom->GetVid();
409 
410  // Ignore Dirichlet edges
411  if (tracesDone.count(id) != 0)
412  {
413  continue;
414  }
415 
417  PointGeom);
418  tracesDone.insert(id);
419  exp->SetElmtId(elmtid++);
420  (*m_exp).push_back(exp);
421  }
422  }
423  else if ((exp2D = std::dynamic_pointer_cast<LocalRegions::Expansion2D>(
424  locexp[i])))
425  {
426  m_expType = e1D;
427  for (j = 0; j < locexp[i]->GetNtraces(); ++j)
428  {
429  segGeom = exp2D->GetGeom2D()->GetEdge(j);
430  id = segGeom->GetGlobalID();
431  // Ignore Dirichlet edges
432  if (tracesDone.count(id) != 0)
433  {
434  continue;
435  }
436 
437  auto it = edgeOrders.find(id);
438 
439  if (it == edgeOrders.end())
440  {
441  edgeOrders.insert(std::make_pair(
442  id, std::make_pair(segGeom,
443  locexp[i]->GetTraceBasisKey(j))));
444  }
445  else // variable modes/points
446  {
447  LibUtilities::BasisKey edge =
448  locexp[i]->GetTraceBasisKey(j);
449  LibUtilities::BasisKey existing = it->second.second;
450 
451  int np1 = edge.GetNumPoints();
452  int np2 = existing.GetNumPoints();
453  int nm1 = edge.GetNumModes();
454  int nm2 = existing.GetNumModes();
455 
456  if (np2 >= np1 && nm2 >= nm1)
457  {
458  continue;
459  }
460  else if (np2 < np1 && nm2 < nm1)
461  {
462  it->second.second = edge;
463  }
464  else
465  {
467  "inappropriate number of points/modes (max"
468  "num of points is not set with max order)");
469  }
470  }
471  }
472  }
473  else if ((exp3D = dynamic_pointer_cast<LocalRegions::Expansion3D>(
474  locexp[i])))
475  {
476  m_expType = e2D;
477  for (j = 0; j < exp3D->GetNtraces(); ++j)
478  {
479  FaceGeom = exp3D->GetGeom3D()->GetFace(j);
480  id = FaceGeom->GetGlobalID();
481 
482  if (tracesDone.count(id) != 0)
483  {
484  continue;
485  }
486  auto it = faceOrders.find(id);
487 
488  if (it == faceOrders.end())
489  {
490  LibUtilities::BasisKey face_dir0 =
491  locexp[i]->GetTraceBasisKey(j, 0);
492  LibUtilities::BasisKey face_dir1 =
493  locexp[i]->GetTraceBasisKey(j, 1);
494 
495  faceOrders.insert(std::make_pair(
496  id,
497  std::make_pair(FaceGeom,
498  std::make_pair(face_dir0, face_dir1))));
499  }
500  else // variable modes/points
501  {
502  LibUtilities::BasisKey face0 =
503  locexp[i]->GetTraceBasisKey(j, 0);
504  LibUtilities::BasisKey face1 =
505  locexp[i]->GetTraceBasisKey(j, 1);
506  LibUtilities::BasisKey existing0 = it->second.second.first;
507  LibUtilities::BasisKey existing1 = it->second.second.second;
508 
509  int np11 = face0.GetNumPoints();
510  int np12 = face1.GetNumPoints();
511  int np21 = existing0.GetNumPoints();
512  int np22 = existing1.GetNumPoints();
513  int nm11 = face0.GetNumModes();
514  int nm12 = face1.GetNumModes();
515  int nm21 = existing0.GetNumModes();
516  int nm22 = existing1.GetNumModes();
517 
518  if ((np22 >= np12 || np21 >= np11) &&
519  (nm22 >= nm12 || nm21 >= nm11))
520  {
521  continue;
522  }
523  else if ((np22 < np12 || np21 < np11) &&
524  (nm22 < nm12 || nm21 < nm11))
525  {
526  it->second.second.first = face0;
527  it->second.second.second = face1;
528  }
529  else
530  {
532  "inappropriate number of points/modes (max"
533  "num of points is not set with max order)");
534  }
535  }
536  }
537  }
538  }
539 
540  int nproc = m_comm->GetRowComm()->GetSize(); // number of processors
541  int tracepr = m_comm->GetRowComm()->GetRank(); // ID processor
542 
543  if (nproc > 1)
544  {
545  int tCnt = 0;
546 
547  // Count the number of traces on each partition
548  for (i = 0; i < locexp.size(); ++i)
549  {
550  tCnt += locexp[i]->GetNtraces();
551  }
552 
553  // Set up the offset and the array that will contain the list of
554  // edge IDs, then reduce this across processors.
555  Array<OneD, int> tracesCnt(nproc, 0);
556  tracesCnt[tracepr] = tCnt;
557  m_comm->GetRowComm()->AllReduce(tracesCnt, LibUtilities::ReduceSum);
558 
559  // Set up offset array.
560  int totTraceCnt = Vmath::Vsum(nproc, tracesCnt, 1);
561  Array<OneD, int> tTotOffsets(nproc, 0);
562 
563  for (i = 1; i < nproc; ++i)
564  {
565  tTotOffsets[i] = tTotOffsets[i - 1] + tracesCnt[i - 1];
566  }
567 
568  // Local list of the edges per element
569  Array<OneD, int> TracesTotID(totTraceCnt, 0);
570  Array<OneD, int> TracesTotNm0(totTraceCnt, 0);
571  Array<OneD, int> TracesTotNm1(totTraceCnt, 0);
572  Array<OneD, int> TracesTotPnts0(totTraceCnt, 0);
573  Array<OneD, int> TracesTotPnts1(totTraceCnt, 0);
574 
575  int cntr = tTotOffsets[tracepr];
576 
577  for (i = 0; i < locexp.size(); ++i)
578  {
579  if ((exp2D = locexp[i]->as<LocalRegions::Expansion2D>()))
580  {
581 
582  int nedges = locexp[i]->GetNtraces();
583 
584  for (j = 0; j < nedges; ++j, ++cntr)
585  {
586  LibUtilities::BasisKey bkeyEdge =
587  locexp[i]->GetTraceBasisKey(j);
588  TracesTotID[cntr] = exp2D->GetGeom2D()->GetEid(j);
589  TracesTotNm0[cntr] = bkeyEdge.GetNumModes();
590  TracesTotPnts0[cntr] = bkeyEdge.GetNumPoints();
591  }
592  }
593  else if ((exp3D = locexp[i]->as<LocalRegions::Expansion3D>()))
594  {
595  int nfaces = locexp[i]->GetNtraces();
596 
597  for (j = 0; j < nfaces; ++j, ++cntr)
598  {
599  LibUtilities::BasisKey face_dir0 =
600  locexp[i]->GetTraceBasisKey(j, 0);
601  LibUtilities::BasisKey face_dir1 =
602  locexp[i]->GetTraceBasisKey(j, 1);
603 
604  TracesTotID[cntr] = exp3D->GetGeom3D()->GetFid(j);
605  TracesTotNm0[cntr] = face_dir0.GetNumModes();
606  TracesTotNm1[cntr] = face_dir1.GetNumModes();
607  TracesTotPnts0[cntr] = face_dir0.GetNumPoints();
608  TracesTotPnts1[cntr] = face_dir1.GetNumPoints();
609  }
610  }
611  }
612 
613  m_comm->GetRowComm()->AllReduce(TracesTotID, LibUtilities::ReduceSum);
614  m_comm->GetRowComm()->AllReduce(TracesTotNm0, LibUtilities::ReduceSum);
615  m_comm->GetRowComm()->AllReduce(TracesTotPnts0,
617  if (m_expType == e2D)
618  {
619  m_comm->AllReduce(TracesTotNm1, LibUtilities::ReduceSum);
620  m_comm->AllReduce(TracesTotPnts1, LibUtilities::ReduceSum);
621  }
622 
623  if (edgeOrders.size())
624  {
625  for (i = 0; i < totTraceCnt; ++i)
626  {
627  auto it = edgeOrders.find(TracesTotID[i]);
628 
629  if (it == edgeOrders.end())
630  {
631  continue;
632  }
633 
634  LibUtilities::BasisKey existing = it->second.second;
635  LibUtilities::BasisKey edge(
636  existing.GetBasisType(), TracesTotNm0[i],
637  LibUtilities::PointsKey(TracesTotPnts0[i],
638  existing.GetPointsType()));
639 
640  int np1 = edge.GetNumPoints();
641  int np2 = existing.GetNumPoints();
642  int nm1 = edge.GetNumModes();
643  int nm2 = existing.GetNumModes();
644 
645  if (np2 >= np1 && nm2 >= nm1)
646  {
647  continue;
648  }
649  else if (np2 < np1 && nm2 < nm1)
650  {
651  it->second.second = edge;
652  }
653  else
654  {
656  "inappropriate number of points/modes (max "
657  "num of points is not set with max order)");
658  }
659  }
660  }
661  else if (faceOrders.size())
662  {
663  for (i = 0; i < totTraceCnt; ++i)
664  {
665  auto it = faceOrders.find(TracesTotID[i]);
666 
667  if (it == faceOrders.end())
668  {
669  continue;
670  }
671 
672  LibUtilities::BasisKey existing0 = it->second.second.first;
673  LibUtilities::BasisKey existing1 = it->second.second.second;
674  LibUtilities::BasisKey face0(
675  existing0.GetBasisType(), TracesTotNm0[i],
676  LibUtilities::PointsKey(TracesTotPnts0[i],
677  existing0.GetPointsType()));
678  LibUtilities::BasisKey face1(
679  existing1.GetBasisType(), TracesTotNm1[i],
680  LibUtilities::PointsKey(TracesTotPnts1[i],
681  existing1.GetPointsType()));
682 
683  int np11 = face0.GetNumPoints();
684  int np12 = face1.GetNumPoints();
685  int np21 = existing0.GetNumPoints();
686  int np22 = existing1.GetNumPoints();
687  int nm11 = face0.GetNumModes();
688  int nm12 = face1.GetNumModes();
689  int nm21 = existing0.GetNumModes();
690  int nm22 = existing1.GetNumModes();
691 
692  if ((np22 >= np12 || np21 >= np11) &&
693  (nm22 >= nm12 || nm21 >= nm11))
694  {
695  continue;
696  }
697  else if ((np22 < np12 || np21 < np11) &&
698  (nm22 < nm12 || nm21 < nm11))
699  {
700  it->second.second.first = face0;
701  it->second.second.second = face1;
702  }
703  else
704  {
706  "inappropriate number of points/modes (max "
707  "num of points is not set with max order)");
708  }
709  }
710  }
711  }
712 
713  if (edgeOrders.size())
714  {
715  for (auto &it : edgeOrders)
716  {
718  it.second.second, it.second.first);
719  exp->SetElmtId(elmtid++);
720  (*m_exp).push_back(exp);
721  }
722  }
723  else
724  {
725  for (auto &it : faceOrders)
726  {
727  FaceGeom = it.second.first;
728 
729  if ((QuadGeom = std::dynamic_pointer_cast<SpatialDomains::QuadGeom>(
730  FaceGeom)))
731  {
733  it.second.second.first, it.second.second.second, QuadGeom);
734  }
735  else if ((TriGeom =
736  std::dynamic_pointer_cast<SpatialDomains::TriGeom>(
737  FaceGeom)))
738  {
740  it.second.second.first, it.second.second.second, TriGeom);
741  }
742  exp->SetElmtId(elmtid++);
743  (*m_exp).push_back(exp);
744  }
745  }
746 
747  // Set up m_coeffs, m_phys and offset arrays.
748  SetupCoeffPhys(DeclareCoeffPhysArrays);
749 
750  // Set up collections
751  if (m_expType != e0D)
752  {
753  CreateCollections(ImpType);
754  }
755 
756  // Setup element to expansion ID maps for the trace elements
757  // Loop in reverse order so that in case where using a
758  // Homogeneous expansion it sets geometry ids to first part of
759  // m_exp list. Otherwise will set to second (complex) expansion
760  for (int i = (*m_exp).size() - 1; i >= 0; --i)
761  {
762  m_elmtToExpId[(*m_exp)[i]->GetGeom()->GetGlobalID()] = i;
763  }
764 }
765 
766 /**
767  * Set expansions for localtrace space expansions used in
768  * DisContField as part of Gradient Jump Penalisation
769  *
770  * @param pSession A session within information about expansion
771  * @param locexp Complete domain expansion list.
772  * @param graph mesh corresponding to the expansion list.
773  * @param DeclareCoeffPhysArrays Declare the coefficient and
774  * phys space arrays
775  * @param variable The variable name associated with the expansion
776  * @param ImpType Detail about the implementation type to use
777  * in operators
778  */
780  const LocalRegions::ExpansionVector &locexp,
782  const bool DeclareCoeffPhysArrays, const std::string variable,
783  const Collections::ImplementationType ImpType)
784  : m_comm(pSession->GetComm()), m_session(pSession), m_graph(graph),
785  m_physState(false),
786  m_exp(MemoryManager<LocalRegions::ExpansionVector>::AllocateSharedPtr()),
787  m_blockMat(MemoryManager<BlockMatrixMap>::AllocateSharedPtr()),
788  m_WaveSpace(false)
789 {
790  boost::ignore_unused(variable, ImpType);
791  int i, j, elmtid = 0;
792 
799 
805 
806  for (i = 0; i < locexp.size(); ++i)
807  {
808  if ((exp1D = std::dynamic_pointer_cast<LocalRegions::Expansion1D>(
809  locexp[i])))
810  {
811  m_expType = e0D;
812 
813  for (j = 0; j < 2; ++j)
814  {
815  PointGeom = (exp1D->GetGeom1D())->GetVertex(j);
816 
818  PointGeom);
819  exp->SetElmtId(elmtid++);
820  (*m_exp).push_back(exp);
821  }
822  }
823  else if ((exp2D = std::dynamic_pointer_cast<LocalRegions::Expansion2D>(
824  locexp[i])))
825  {
826  m_expType = e1D;
827  LibUtilities::BasisKey edgeKey0 =
828  locexp[i]->GetBasis(0)->GetBasisKey();
829 
830  for (j = 0; j < locexp[i]->GetNtraces(); ++j)
831  {
832  segGeom = exp2D->GetGeom2D()->GetEdge(j);
833 
834  int dir = exp2D->GetGeom2D()->GetDir(j);
835 
836  if (locexp[i]->GetNtraces() == 3)
837  {
838  LibUtilities::BasisKey edgeKey =
839  locexp[i]->GetBasis(dir)->GetBasisKey();
840 
841  LibUtilities::BasisKey nEdgeKey(edgeKey0.GetBasisType(),
842  edgeKey.GetNumModes(),
843  edgeKey.GetPointsKey());
844 
845  exp =
847  nEdgeKey, segGeom);
848  }
849  else
850  {
851  exp =
853  locexp[i]->GetBasis(dir)->GetBasisKey(), segGeom);
854  }
855 
856  exp->SetElmtId(elmtid++);
857  (*m_exp).push_back(exp);
858  }
859  }
860  else if ((exp3D = dynamic_pointer_cast<LocalRegions::Expansion3D>(
861  locexp[i])))
862  {
863  m_expType = e2D;
864 
865  LibUtilities::BasisKey face0_dir0 =
866  locexp[i]->GetBasis(0)->GetBasisKey();
867  LibUtilities::BasisKey face0_dir1 =
868  locexp[i]->GetBasis(1)->GetBasisKey();
869 
870  for (j = 0; j < exp3D->GetNtraces(); ++j)
871  {
872  FaceGeom = exp3D->GetGeom3D()->GetFace(j);
873 
874  int dir0 = exp3D->GetGeom3D()->GetDir(j, 0);
875  int dir1 = exp3D->GetGeom3D()->GetDir(j, 1);
876 
877  LibUtilities::BasisKey face_dir0 =
878  locexp[i]->GetBasis(dir0)->GetBasisKey();
879  LibUtilities::BasisKey face_dir1 =
880  locexp[i]->GetBasis(dir1)->GetBasisKey();
881 
882  if ((QuadGeom =
883  std::dynamic_pointer_cast<SpatialDomains::QuadGeom>(
884  FaceGeom)))
885  {
886  exp =
888  face_dir0, face_dir1, QuadGeom);
889  }
890  else if ((TriGeom = std::dynamic_pointer_cast<
891  SpatialDomains::TriGeom>(FaceGeom)))
892  {
893 
894  LibUtilities::BasisKey nface_dir0(face0_dir0.GetBasisType(),
895  face_dir0.GetNumModes(),
896  face_dir0.GetPointsKey());
897  LibUtilities::BasisKey nface_dir1(face0_dir1.GetBasisType(),
898  face_dir1.GetNumModes(),
899  face_dir1.GetPointsKey());
900  exp =
902  nface_dir0, nface_dir1, TriGeom);
903  }
904  exp->SetElmtId(elmtid++);
905  (*m_exp).push_back(exp);
906  }
907  }
908  }
909 
910  // Set up m_coeffs, m_phys and offset arrays.
911  SetupCoeffPhys(DeclareCoeffPhysArrays);
912 
913  // Set up collections
914  if (m_expType != e0D)
915  {
916  CreateCollections(ImpType);
917  }
918 }
919 
920 /**
921  * Fills the list of local expansions with the trace from the mesh
922  * specified by \a domain. This CompositeMap contains a list of
923  * Composites which define the boundary. It is also used to set up
924  * expansion domains in the 1D Pulse Wave solver.
925  *
926  * @param pSession A session within information about expansion
927  * @param domain A domain, comprising of one or more composite
928  * regions,
929  * @param graph A mesh, containing information about the
930  * domain and the spectral/hp element expansion.
931  * @param DeclareCoeffPhysArrays Declare the coefficient and
932  * phys space arrays. Default is true.
933  * @param variable The variable name associated with the expansion
934  * @param SetToOneSpaceDimension Reduce to one space dimension expansion
935  * @param comm An optional communicator that can be used with the
936  * boundary expansion in case of more global
937  * parallel operations. Default to a Null Communicator
938  * @param ImpType Detail about the implementation type to use
939  * in operators. Default is eNoImpType.
940  *
941  */
943  const SpatialDomains::CompositeMap &domain,
945  const bool DeclareCoeffPhysArrays, const std::string variable,
946  bool SetToOneSpaceDimension,
947  const LibUtilities::CommSharedPtr comm,
948  const Collections::ImplementationType ImpType)
949  : m_comm(comm), m_session(pSession), m_graph(graph), m_physState(false),
950  m_exp(MemoryManager<LocalRegions::ExpansionVector>::AllocateSharedPtr()),
951  m_blockMat(MemoryManager<BlockMatrixMap>::AllocateSharedPtr()),
952  m_WaveSpace(false)
953 {
954  int j, elmtid = 0;
959 
961 
963 
964  int meshdim = graph->GetMeshDimension();
965 
966  // Retrieve the list of expansions (needed of meshdim == 1
967  const SpatialDomains::ExpansionInfoMap &expansions =
968  graph->GetExpansionInfo(variable);
969 
970  // Retrieve the list of expansions
971  // Process each composite region.
972  for (auto &compIt : domain)
973  {
974  // Process each expansion in the region.
975  for (j = 0; j < compIt.second->m_geomVec.size(); ++j)
976  {
977  if ((PtGeom = std::dynamic_pointer_cast<SpatialDomains::PointGeom>(
978  compIt.second->m_geomVec[j])))
979  {
980  m_expType = e0D;
981 
983  PtGeom);
984  }
985  else if ((SegGeom =
986  std::dynamic_pointer_cast<SpatialDomains::SegGeom>(
987  compIt.second->m_geomVec[j])))
988  {
989  m_expType = e1D;
990 
991  // Retrieve the basis key from the expansion.
993 
994  if (meshdim == 1)
995  {
996  auto expIt = expansions.find(SegGeom->GetGlobalID());
997  ASSERTL0(expIt != expansions.end(),
998  "Failed to find basis key");
999  bkey = expIt->second->m_basisKeyVector[0];
1000  }
1001  else
1002  {
1003  bkey = graph->GetEdgeBasisKey(SegGeom, variable);
1004  }
1005 
1006  if (SetToOneSpaceDimension)
1007  {
1008  SpatialDomains::SegGeomSharedPtr OneDSegmentGeom =
1009  SegGeom->GenerateOneSpaceDimGeom();
1010 
1011  exp =
1013  bkey, OneDSegmentGeom);
1014  }
1015  else
1016  {
1017 
1018  exp =
1020  bkey, SegGeom);
1021  }
1022  }
1023  else if ((TriGeom =
1024  std::dynamic_pointer_cast<SpatialDomains::TriGeom>(
1025  compIt.second->m_geomVec[j])))
1026  {
1027  m_expType = e2D;
1028 
1029  LibUtilities::BasisKey TriBa =
1030  graph->GetFaceBasisKey(TriGeom, 0, variable);
1031  LibUtilities::BasisKey TriBb =
1032  graph->GetFaceBasisKey(TriGeom, 1, variable);
1033 
1034  if (graph->GetExpansionInfo()
1035  .begin()
1036  ->second->m_basisKeyVector[0]
1037  .GetBasisType() == LibUtilities::eGLL_Lagrange)
1038  {
1039  NEKERROR(ErrorUtil::efatal, "This method needs sorting");
1041 
1042  exp = MemoryManager<
1043  LocalRegions::NodalTriExp>::AllocateSharedPtr(TriBa,
1044  TriBb,
1045  TriNb,
1046  TriGeom);
1047  }
1048  else
1049  {
1050  exp =
1052  TriBa, TriBb, TriGeom);
1053  }
1054  }
1055  else if ((QuadGeom =
1056  std::dynamic_pointer_cast<SpatialDomains::QuadGeom>(
1057  compIt.second->m_geomVec[j])))
1058  {
1059  m_expType = e2D;
1060 
1061  LibUtilities::BasisKey QuadBa =
1062  graph->GetFaceBasisKey(QuadGeom, 0, variable);
1063  LibUtilities::BasisKey QuadBb =
1064  graph->GetFaceBasisKey(QuadGeom, 1, variable);
1065 
1067  QuadBa, QuadBb, QuadGeom);
1068  }
1069  else
1070  {
1072  "dynamic cast to a Geom (possibly 3D) failed");
1073  }
1074 
1075  exp->SetElmtId(elmtid++);
1076  (*m_exp).push_back(exp);
1077  }
1078  }
1079 
1080  // Set up m_coeffs, m_phys and offset arrays.
1081  SetupCoeffPhys(DeclareCoeffPhysArrays);
1082 
1083  if (m_expType != e0D)
1084  {
1085  CreateCollections(ImpType);
1086  }
1087 }
1088 
1089 /**
1090  * Each expansion (local element) is processed in turn to
1091  * determine the number of coefficients and physical data
1092  * points it contributes to the domain. Two arrays,
1093  * #m_coeff_offset are #m_phys_offset are also initialised and
1094  * updated to store the data offsets of each element in the
1095  * #m_coeffs and #m_phys arrays, and the element id that each
1096  * consecutive block is associated respectively.
1097  * Finally we initialise #m_coeffs and #m_phys
1098  */
1099 void ExpList::SetupCoeffPhys(bool DeclareCoeffPhysArrays, bool SetupOffsets)
1100 {
1101  if (SetupOffsets)
1102  {
1103  int i;
1104 
1105  // Set up offset information and array sizes
1108 
1109  m_ncoeffs = m_npoints = 0;
1110 
1111  for (i = 0; i < m_exp->size(); ++i)
1112  {
1114  m_phys_offset[i] = m_npoints;
1115  m_ncoeffs += (*m_exp)[i]->GetNcoeffs();
1116  m_npoints += (*m_exp)[i]->GetTotPoints();
1117  }
1118  }
1119 
1120  if (DeclareCoeffPhysArrays)
1121  {
1124  }
1125 
1127 
1128  for (int i = 0; i < m_exp->size(); ++i)
1129  {
1130  int coeffs_offset = m_coeff_offset[i];
1131 
1132  int loccoeffs = (*m_exp)[i]->GetNcoeffs();
1133 
1134  for (int j = 0; j < loccoeffs; ++j)
1135  {
1136  m_coeffsToElmt[coeffs_offset + j].first = i;
1137  m_coeffsToElmt[coeffs_offset + j].second = j;
1138  }
1139  }
1140 }
1141 
1143  const SpatialDomains::ExpansionInfoMap &expmap)
1144 {
1145 
1147  SpatialDomains::TriGeomSharedPtr TriangleGeom;
1148  SpatialDomains::QuadGeomSharedPtr QuadrilateralGeom;
1153 
1154  int id = 0;
1156 
1157  m_expType = eNoType;
1158  // Process each expansion in the graph
1159  for (auto &expIt : expmap)
1160  {
1161  const SpatialDomains::ExpansionInfoShPtr expInfo = expIt.second;
1162 
1163  switch (expInfo->m_basisKeyVector.size())
1164  {
1165  case 1: // Segment Expansions
1166  {
1168  "Cannot mix expansion dimensions in one vector");
1169  m_expType = e1D;
1170 
1171  if ((SegmentGeom =
1172  std::dynamic_pointer_cast<SpatialDomains::SegGeom>(
1173  expInfo->m_geomShPtr)))
1174  {
1175  // Retrieve basis key from expansion
1176  LibUtilities::BasisKey bkey = expInfo->m_basisKeyVector[0];
1177 
1178  exp =
1180  bkey, SegmentGeom);
1181  }
1182  else
1183  {
1185  "dynamic cast to a 1D Geom failed");
1186  }
1187  }
1188  break;
1189  case 2:
1190  {
1192  "Cannot mix expansion dimensions in one vector");
1193  m_expType = e2D;
1194 
1195  LibUtilities::BasisKey Ba = expInfo->m_basisKeyVector[0];
1196  LibUtilities::BasisKey Bb = expInfo->m_basisKeyVector[1];
1197 
1198  if ((TriangleGeom =
1199  std::dynamic_pointer_cast<SpatialDomains ::TriGeom>(
1200  expInfo->m_geomShPtr)))
1201  {
1202 
1203  // This is not elegantly implemented needs re-thinking.
1205  {
1207  Ba.GetNumModes(),
1208  Ba.GetPointsKey());
1209 
1210  LibUtilities::PointsType TriNb =
1213  AllocateSharedPtr(newBa, Bb, TriNb, TriangleGeom);
1214  }
1215  else
1216  {
1218  AllocateSharedPtr(Ba, Bb, TriangleGeom);
1219  }
1220  }
1221  else if ((QuadrilateralGeom = std::dynamic_pointer_cast<
1222  SpatialDomains::QuadGeom>(expInfo->m_geomShPtr)))
1223  {
1224  exp =
1226  Ba, Bb, QuadrilateralGeom);
1227  }
1228  else
1229  {
1231  "dynamic cast to a 2D Geom failed");
1232  }
1233  }
1234  break;
1235  case 3:
1236  {
1238  "Cannot mix expansion dimensions in one vector");
1239  m_expType = e3D;
1240 
1241  LibUtilities::BasisKey Ba = expInfo->m_basisKeyVector[0];
1242  LibUtilities::BasisKey Bb = expInfo->m_basisKeyVector[1];
1243  LibUtilities::BasisKey Bc = expInfo->m_basisKeyVector[2];
1244 
1245  if ((TetGeom =
1246  std::dynamic_pointer_cast<SpatialDomains::TetGeom>(
1247  expInfo->m_geomShPtr)))
1248  {
1249 
1252  {
1254  "LocalRegions::NodalTetExp is not implemented "
1255  "yet");
1256  }
1257  else
1258  {
1259  exp = MemoryManager<
1260  LocalRegions::TetExp>::AllocateSharedPtr(Ba, Bb, Bc,
1261  TetGeom);
1262  }
1263  }
1264  else if ((PrismGeom = std::dynamic_pointer_cast<
1265  SpatialDomains ::PrismGeom>(
1266  expInfo->m_geomShPtr)))
1267  {
1268  exp = MemoryManager<
1269  LocalRegions::PrismExp>::AllocateSharedPtr(Ba, Bb, Bc,
1270  PrismGeom);
1271  }
1272  else if ((PyrGeom = std::dynamic_pointer_cast<
1273  SpatialDomains::PyrGeom>(expInfo->m_geomShPtr)))
1274  {
1275 
1276  exp =
1278  Ba, Bb, Bc, PyrGeom);
1279  }
1280  else if ((HexGeom = std::dynamic_pointer_cast<
1281  SpatialDomains::HexGeom>(expInfo->m_geomShPtr)))
1282  {
1283  exp =
1285  Ba, Bb, Bc, HexGeom);
1286  }
1287  else
1288  {
1290  "dynamic cast to a Geom failed");
1291  }
1292  }
1293  break;
1294  default:
1296  "Dimension of basis key is greater than 3");
1297  }
1298 
1299  // Assign next id
1300  exp->SetElmtId(id++);
1301 
1302  // Add the expansion
1303  (*m_exp).push_back(exp);
1304  }
1305 }
1306 
1307 /**
1308  *
1309  */
1311 {
1312  return m_expType;
1313 }
1314 
1316 {
1317 }
1318 
1319 /**
1320  * Retrieves the block matrix specified by \a bkey, and computes
1321  * \f$ y=Mx \f$.
1322  * @param gkey GlobalMatrixKey specifying the block matrix to
1323  * use in the matrix-vector multiply.
1324  * @param inarray Input vector \f$ x \f$.
1325  * @param outarray Output vector \f$ y \f$.
1326  */
1328  const Array<OneD, const NekDouble> &inarray,
1329  Array<OneD, NekDouble> &outarray)
1330 {
1331  // Retrieve the block matrix using the given key.
1332  const DNekScalBlkMatSharedPtr &blockmat = GetBlockMatrix(gkey);
1333  int nrows = blockmat->GetRows();
1334  int ncols = blockmat->GetColumns();
1335 
1336  // Create NekVectors from the given data arrays
1337  NekVector<NekDouble> in(ncols, inarray, eWrapper);
1338  NekVector<NekDouble> out(nrows, outarray, eWrapper);
1339 
1340  // Perform matrix-vector multiply.
1341  out = (*blockmat) * in;
1342 }
1343 
1344 /**
1345  * multiply the metric jacobi and quadrature weights
1346  */
1348  const Array<OneD, const NekDouble> &inarray,
1349  Array<OneD, NekDouble> &outarray)
1350 {
1351  Array<OneD, NekDouble> e_outarray;
1352 
1353  for (int i = 0; i < (*m_exp).size(); ++i)
1354  {
1355  (*m_exp)[i]->MultiplyByQuadratureMetric(inarray + m_phys_offset[i],
1356  e_outarray = outarray +
1357  m_phys_offset[i]);
1358  }
1359 }
1360 
1361 /**
1362  * Divided by the metric jacobi and quadrature weights
1363  */
1365  const Array<OneD, const NekDouble> &inarray,
1366  Array<OneD, NekDouble> &outarray)
1367 {
1368  Array<OneD, NekDouble> e_outarray;
1369 
1370  for (int i = 0; i < (*m_exp).size(); ++i)
1371  {
1372  (*m_exp)[i]->DivideByQuadratureMetric(inarray + m_phys_offset[i],
1373  e_outarray =
1374  outarray + m_phys_offset[i]);
1375  }
1376 }
1377 
1378 /**
1379  * The operation is evaluated locally for every element by the function
1380  * StdRegions#Expansion#IProductWRTDerivBase.
1381  *
1382  * @param dir {0,1} is the direction in which the
1383  * derivative of the basis should be taken
1384  * @param inarray An array of size \f$Q_{\mathrm{tot}}\f$
1385  * containing the values of the function
1386  * \f$f(\boldsymbol{x})\f$ at the quadrature
1387  * points \f$\boldsymbol{x}_i\f$.
1388  * @param outarray An array of size \f$N_{\mathrm{eof}}\f$
1389  * used to store the result.
1390  */
1392  const Array<OneD, const NekDouble> &inarray,
1393  Array<OneD, NekDouble> &outarray)
1394 {
1395  int i;
1396 
1397  Array<OneD, NekDouble> e_outarray;
1398 
1399  for (i = 0; i < (*m_exp).size(); ++i)
1400  {
1401  (*m_exp)[i]->IProductWRTDerivBase(dir, inarray + m_phys_offset[i],
1402  e_outarray =
1403  outarray + m_coeff_offset[i]);
1404  }
1405 }
1406 
1407 /**
1408  * @brief Directional derivative along a given direction
1409  *
1410  */
1412  const Array<OneD, const NekDouble> &direction,
1413  const Array<OneD, const NekDouble> &inarray,
1414  Array<OneD, NekDouble> &outarray)
1415 {
1416  int npts_e;
1417  int coordim = (*m_exp)[0]->GetGeom()->GetCoordim();
1418  int nq = direction.size() / coordim;
1419 
1420  Array<OneD, NekDouble> e_outarray;
1421  Array<OneD, NekDouble> e_MFdiv;
1422 
1423  Array<OneD, NekDouble> locdir;
1424 
1425  for (int i = 0; i < (*m_exp).size(); ++i)
1426  {
1427  npts_e = (*m_exp)[i]->GetTotPoints();
1428  locdir = Array<OneD, NekDouble>(npts_e * coordim);
1429 
1430  for (int k = 0; k < coordim; ++k)
1431  {
1432  Vmath::Vcopy(npts_e, &direction[k * nq + m_phys_offset[i]], 1,
1433  &locdir[k * npts_e], 1);
1434  }
1435 
1436  (*m_exp)[i]->IProductWRTDirectionalDerivBase(
1437  locdir, inarray + m_phys_offset[i],
1438  e_outarray = outarray + m_coeff_offset[i]);
1439  }
1440 }
1441 
1442 /**
1443  * The operation is evaluated locally for every element by the function
1444  * StdRegions#StdExpansion#IProductWRTDerivBase.
1445  *
1446  * @param inarray An array of arrays of size \f$Q_{\mathrm{tot}}\f$
1447  * containing the values of the function
1448  * \f$f(\boldsymbol{x})\f$ at the quadrature
1449  * points \f$\boldsymbol{x}_i\f$ in dir directions.
1450  * @param outarray An array of size \f$N_{\mathrm{eof}}\f$
1451  * used to store the result.
1452  */
1454  const Array<OneD, const Array<OneD, NekDouble>> &inarray,
1455  Array<OneD, NekDouble> &outarray)
1456 {
1457  Array<OneD, NekDouble> tmp0, tmp1, tmp2;
1458  // assume coord dimension defines the size of Deriv Base
1459  int dim = GetCoordim(0);
1460 
1461  ASSERTL1(inarray.size() >= dim, "inarray is not of sufficient dimension");
1462 
1463  // initialise if required
1465  {
1466  for (int i = 0; i < m_collections.size(); ++i)
1467  {
1469  }
1471  }
1472 
1473  LibUtilities::Timer timer;
1474 
1475  LIKWID_MARKER_START("IProductWRTDerivBase_coll");
1476  timer.Start();
1477 
1478  switch (dim)
1479  {
1480  case 1:
1481  for (int i = 0; i < m_collections.size(); ++i)
1482  {
1483  m_collections[i].ApplyOperator(
1485  inarray[0] + m_coll_phys_offset[i],
1486  tmp0 = outarray + m_coll_coeff_offset[i]);
1487  }
1488  break;
1489  case 2:
1490  for (int i = 0; i < m_collections.size(); ++i)
1491  {
1492  m_collections[i].ApplyOperator(
1494  inarray[0] + m_coll_phys_offset[i],
1495  tmp0 = inarray[1] + m_coll_phys_offset[i],
1496  tmp1 = outarray + m_coll_coeff_offset[i]);
1497  }
1498  break;
1499  case 3:
1500  for (int i = 0; i < m_collections.size(); ++i)
1501  {
1502  m_collections[i].ApplyOperator(
1504  inarray[0] + m_coll_phys_offset[i],
1505  tmp0 = inarray[1] + m_coll_phys_offset[i],
1506  tmp1 = inarray[2] + m_coll_phys_offset[i],
1507  tmp2 = outarray + m_coll_coeff_offset[i]);
1508  }
1509  break;
1510  default:
1511  NEKERROR(ErrorUtil::efatal, "Dimension of inarray not correct");
1512  break;
1513  }
1514 
1515  timer.Stop();
1516  LIKWID_MARKER_STOP("IProductWRTDerivBase_coll");
1517 
1518  // Elapsed time
1519  timer.AccumulateRegion("Collections:IProductWRTDerivBase", 10);
1520 }
1521 /**
1522  * Given a function \f$f(\boldsymbol{x})\f$ evaluated at
1523  * the quadrature points, this function calculates the
1524  * derivatives \f$\frac{d}{dx_1}\f$, \f$\frac{d}{dx_2}\f$
1525  * and \f$\frac{d}{dx_3}\f$ of the function
1526  * \f$f(\boldsymbol{x})\f$ at the same quadrature
1527  * points. The local distribution of the quadrature points
1528  * allows an elemental evaluation of the derivative. This
1529  * is done by a call to the function
1530  * StdRegions#StdExpansion#PhysDeriv.
1531  *
1532  * @param inarray An array of size \f$Q_{\mathrm{tot}}\f$
1533  * containing the values of the function
1534  * \f$f(\boldsymbol{x})\f$ at the quadrature
1535  * points \f$\boldsymbol{x}_i\f$.
1536  * @param out_d0 The discrete evaluation of the
1537  * derivative\f$\frac{d}{dx_1}\f$ will
1538  * be stored in this array of size
1539  * \f$Q_{\mathrm{tot}}\f$.
1540  * @param out_d1 The discrete evaluation of the
1541  * derivative\f$\frac{d}{dx_2}\f$ will be
1542  * stored in this array of size
1543  * \f$Q_{\mathrm{tot}}\f$. Note that if no
1544  * memory is allocated for \a out_d1, the
1545  * derivative \f$\frac{d}{dx_2}\f$ will not be
1546  * calculated.
1547  * @param out_d2 The discrete evaluation of the
1548  * derivative\f$\frac{d}{dx_3}\f$ will be
1549  * stored in this array of size
1550  * \f$Q_{\mathrm{tot}}\f$. Note that if no
1551  * memory is allocated for \a out_d2, the
1552  * derivative \f$\frac{d}{dx_3}\f$ will not be
1553  * calculated.
1554  */
1556  Array<OneD, NekDouble> &out_d0,
1557  Array<OneD, NekDouble> &out_d1,
1558  Array<OneD, NekDouble> &out_d2)
1559 {
1560  Array<OneD, NekDouble> e_out_d0;
1561  Array<OneD, NekDouble> e_out_d1;
1562  Array<OneD, NekDouble> e_out_d2;
1563  int offset;
1564 
1565  // initialise if required
1567  {
1568  for (int i = 0; i < m_collections.size(); ++i)
1569  {
1570  m_collections[i].Initialise(Collections::ePhysDeriv);
1571  }
1573  }
1574 
1575  LibUtilities::Timer timer;
1576  timer.Start();
1577  for (int i = 0; i < m_collections.size(); ++i)
1578  {
1579  offset = m_coll_phys_offset[i];
1580  e_out_d0 = out_d0 + offset;
1581  e_out_d1 = out_d1 + offset;
1582  e_out_d2 = out_d2 + offset;
1583 
1584  m_collections[i].ApplyOperator(Collections::ePhysDeriv,
1585  inarray + offset, e_out_d0, e_out_d1,
1586  e_out_d2);
1587  }
1588  timer.Stop();
1589  // Elapsed time
1590  timer.AccumulateRegion("Collections:PhysDeriv", 10);
1591 }
1592 
1593 void ExpList::v_PhysDeriv(const int dir,
1594  const Array<OneD, const NekDouble> &inarray,
1595  Array<OneD, NekDouble> &out_d)
1596 {
1597  Direction edir = DirCartesianMap[dir];
1598  v_PhysDeriv(edir, inarray, out_d);
1599 }
1600 
1602  const Array<OneD, const NekDouble> &inarray,
1603  Array<OneD, NekDouble> &out_d)
1604 {
1605  int i;
1606  if (edir == MultiRegions::eS)
1607  {
1608  Array<OneD, NekDouble> e_out_ds;
1609  for (i = 0; i < (*m_exp).size(); ++i)
1610  {
1611  e_out_ds = out_d + m_phys_offset[i];
1612  (*m_exp)[i]->PhysDeriv_s(inarray + m_phys_offset[i], e_out_ds);
1613  }
1614  }
1615  else if (edir == MultiRegions::eN)
1616  {
1617  Array<OneD, NekDouble> e_out_dn;
1618  for (i = 0; i < (*m_exp).size(); i++)
1619  {
1620  e_out_dn = out_d + m_phys_offset[i];
1621  (*m_exp)[i]->PhysDeriv_n(inarray + m_phys_offset[i], e_out_dn);
1622  }
1623  }
1624  else
1625  {
1626 
1627  // initialise if required
1629  {
1630  for (int i = 0; i < m_collections.size(); ++i)
1631  {
1632  m_collections[i].Initialise(Collections::ePhysDeriv);
1633  }
1635  }
1636 
1637  // convert enum into int
1638  int intdir = (int)edir;
1639  Array<OneD, NekDouble> e_out_d;
1640  int offset;
1641  for (int i = 0; i < m_collections.size(); ++i)
1642  {
1643  offset = m_coll_phys_offset[i];
1644  e_out_d = out_d + offset;
1645 
1646  m_collections[i].ApplyOperator(Collections::ePhysDeriv, intdir,
1647  inarray + offset, e_out_d);
1648  }
1649  }
1650 }
1651 
1654 {
1655  int nq = GetTotPoints();
1656  Array<OneD, NekDouble> Vx(nq);
1657  Array<OneD, NekDouble> Uy(nq);
1659 
1660  bool halfMode = false;
1661  if (GetExpType() == e3DH1D)
1662  {
1663  m_session->MatchSolverInfo("ModeType", "HalfMode", halfMode, false);
1664  }
1665 
1666  switch (m_expType)
1667  {
1668  case e2D:
1669  {
1670  PhysDeriv(xDir, Vel[yDir], Vx);
1671  PhysDeriv(yDir, Vel[xDir], Uy);
1672 
1673  Vmath::Vsub(nq, Vx, 1, Uy, 1, Dummy, 1);
1674 
1675  PhysDeriv(Dummy, Q[1], Q[0]);
1676 
1677  Vmath::Smul(nq, -1.0, Q[1], 1, Q[1], 1);
1678  }
1679  break;
1680 
1681  case e3D:
1682  case e3DH1D:
1683  case e3DH2D:
1684  {
1685  Array<OneD, NekDouble> Vz(nq);
1686  Array<OneD, NekDouble> Uz(nq);
1687  Array<OneD, NekDouble> Wx(nq);
1688  Array<OneD, NekDouble> Wy(nq);
1689 
1690  PhysDeriv(Vel[xDir], Dummy, Uy, Uz);
1691  PhysDeriv(Vel[yDir], Vx, Dummy, Vz);
1692  PhysDeriv(Vel[zDir], Wx, Wy, Dummy);
1693 
1694  Vmath::Vsub(nq, Wy, 1, Vz, 1, Q[0], 1);
1695  Vmath::Vsub(nq, Uz, 1, Wx, 1, Q[1], 1);
1696  Vmath::Vsub(nq, Vx, 1, Uy, 1, Q[2], 1);
1697 
1698  PhysDeriv(Q[0], Dummy, Uy, Uz);
1699  PhysDeriv(Q[1], Vx, Dummy, Vz);
1700  PhysDeriv(Q[2], Wx, Wy, Dummy);
1701 
1702  // For halfmode, need to change the sign of z derivatives
1703  if (halfMode)
1704  {
1705  Vmath::Neg(nq, Uz, 1);
1706  Vmath::Neg(nq, Vz, 1);
1707  }
1708 
1709  Vmath::Vsub(nq, Wy, 1, Vz, 1, Q[0], 1);
1710  Vmath::Vsub(nq, Uz, 1, Wx, 1, Q[1], 1);
1711  Vmath::Vsub(nq, Vx, 1, Uy, 1, Q[2], 1);
1712  }
1713  break;
1714  default:
1715  ASSERTL0(0, "Dimension not supported");
1716  break;
1717  }
1718 }
1719 
1721  const Array<OneD, const NekDouble> &direction,
1722  const Array<OneD, const NekDouble> &inarray,
1723  Array<OneD, NekDouble> &outarray)
1724 {
1725  int npts_e;
1726  int coordim = (*m_exp)[0]->GetGeom()->GetCoordim();
1727  int nq = direction.size() / coordim;
1728 
1729  Array<OneD, NekDouble> e_outarray;
1730  Array<OneD, NekDouble> e_MFdiv;
1731  Array<OneD, NekDouble> locdir;
1732 
1733  for (int i = 0; i < (*m_exp).size(); ++i)
1734  {
1735  npts_e = (*m_exp)[i]->GetTotPoints();
1736  locdir = Array<OneD, NekDouble>(npts_e * coordim);
1737 
1738  for (int k = 0; k < coordim; ++k)
1739  {
1740  Vmath::Vcopy(npts_e, &direction[k * nq + m_phys_offset[i]], 1,
1741  &locdir[k * npts_e], 1);
1742  }
1743 
1744  (*m_exp)[i]->PhysDirectionalDeriv(inarray + m_phys_offset[i], locdir,
1745  e_outarray =
1746  outarray + m_phys_offset[i]);
1747  }
1748 }
1749 
1751  const NekDouble alpha, const NekDouble exponent,
1752  const NekDouble cutoff)
1753 {
1754  Array<OneD, NekDouble> e_array;
1755 
1756  for (int i = 0; i < (*m_exp).size(); ++i)
1757  {
1758  (*m_exp)[i]->ExponentialFilter(e_array = array + m_phys_offset[i],
1759  alpha, exponent, cutoff);
1760  }
1761 }
1762 
1763 /**
1764  * The coefficients of the function to be acted upon
1765  * should be contained in the \param inarray. The
1766  * resulting coefficients are stored in \param outarray
1767  *
1768  * @param inarray An array of size \f$N_{\mathrm{eof}}\f$
1769  * containing the inner product.
1770  */
1772  Array<OneD, NekDouble> &outarray)
1773 {
1775  const DNekScalBlkMatSharedPtr &InvMass = GetBlockMatrix(mkey);
1776 
1777  // Inverse mass matrix
1778  NekVector<NekDouble> out(m_ncoeffs, outarray, eWrapper);
1779  if (inarray.get() == outarray.get())
1780  {
1781  NekVector<NekDouble> in(m_ncoeffs, inarray); // copy data
1782  out = (*InvMass) * in;
1783  }
1784  else
1785  {
1786  NekVector<NekDouble> in(m_ncoeffs, inarray, eWrapper);
1787  out = (*InvMass) * in;
1788  }
1789 }
1790 
1791 /**
1792  * Given a function \f$u(\boldsymbol{x})\f$ defined at the
1793  * quadrature points, this function determines the
1794  * transformed elemental coefficients \f$\hat{u}_n^e\f$
1795  * employing a discrete elemental Galerkin projection from
1796  * physical space to coefficient space. For each element,
1797  * the operation is evaluated locally by the function
1798  * StdRegions#StdExpansion#IproductWRTBase followed by a
1799  * call to #MultiRegions#MultiplyByElmtInvMass.
1800  *
1801  * @param inarray An array of size \f$Q_{\mathrm{tot}}\f$
1802  * containing the values of the function
1803  * \f$f(\boldsymbol{x})\f$ at the quadrature
1804  * points \f$\boldsymbol{x}_i\f$.
1805  * @param outarray The resulting coefficients
1806  * \f$\hat{u}_n^e\f$ will be stored in this
1807  * array of size \f$N_{\mathrm{eof}}\f$.
1808  */
1810  Array<OneD, NekDouble> &outarray)
1811 {
1813 
1814  IProductWRTBase(inarray, f);
1815  MultiplyByElmtInvMass(f, outarray);
1816 }
1817 
1819  const Array<OneD, const NekDouble> &inarray,
1820  Array<OneD, NekDouble> &outarray)
1821 {
1822  int i;
1823 
1824  Array<OneD, NekDouble> e_outarray;
1825 
1826  for (i = 0; i < (*m_exp).size(); ++i)
1827  {
1828  (*m_exp)[i]->FwdTransBndConstrained(inarray + m_phys_offset[i],
1829  e_outarray =
1830  outarray + m_coeff_offset[i]);
1831  }
1832 }
1833 
1834 /**
1835  * This function smooth a field after some calculaitons which have
1836  * been done elementally.
1837  *
1838  * @param field An array containing the field in physical space
1839  *
1840  */
1842 {
1843  boost::ignore_unused(field);
1844  // Do nothing unless the method is implemented in the appropriate
1845  // class, i.e. ContField1D,ContField2D, etc.
1846 
1847  // So far it has been implemented just for ContField2D and
1848  // ContField3DHomogeneous1D
1849 
1850  // Block in case users try the smoothing with a modal expansion.
1851  // Maybe a different techique for the smoothing require
1852  // implementation for modal basis.
1853 
1854  ASSERTL0((*m_exp)[0]->GetBasisType(0) == LibUtilities::eGLL_Lagrange ||
1855  (*m_exp)[0]->GetBasisType(0) == LibUtilities::eGauss_Lagrange,
1856  "Smoothing is currently not allowed unless you are using "
1857  "a nodal base for efficiency reasons. The implemented "
1858  "smoothing technique requires the mass matrix inversion "
1859  "which is trivial just for GLL_LAGRANGE_SEM and "
1860  "GAUSS_LAGRANGE_SEMexpansions.");
1861 }
1862 
1863 /**
1864  * This function assembles the block diagonal matrix
1865  * \f$\underline{\boldsymbol{M}}^e\f$, which is the
1866  * concatenation of the local matrices
1867  * \f$\boldsymbol{M}^e\f$ of the type \a mtype, that is
1868  *
1869  * \f[
1870  * \underline{\boldsymbol{M}}^e = \left[
1871  * \begin{array}{cccc}
1872  * \boldsymbol{M}^1 & 0 & \hspace{3mm}0 \hspace{3mm}& 0 \\
1873  * 0 & \boldsymbol{M}^2 & 0 & 0 \\
1874  * 0 & 0 & \ddots & 0 \\
1875  * 0 & 0 & 0 & \boldsymbol{M}^{N_{\mathrm{el}}} \end{array}\right].\f]
1876  *
1877  * @param mtype the type of matrix to be assembled
1878  * @param scalar an optional parameter
1879  * @param constant an optional parameter
1880  */
1882  const GlobalMatrixKey &gkey)
1883 {
1884  int i, cnt1;
1885  int n_exp = 0;
1886  DNekScalMatSharedPtr loc_mat;
1887  DNekScalBlkMatSharedPtr BlkMatrix;
1888  map<int, int> elmt_id;
1890 
1892  {
1893  for (i = 0; i < (*m_exp).size(); ++i)
1894  {
1895  if ((*m_exp)[i]->DetShapeType() == ShapeType)
1896  {
1897  elmt_id[n_exp++] = i;
1898  }
1899  }
1900  }
1901  else
1902  {
1903  n_exp = (*m_exp).size();
1904  for (i = 0; i < n_exp; ++i)
1905  {
1906  elmt_id[i] = i;
1907  }
1908  }
1909 
1910  Array<OneD, unsigned int> nrows(n_exp);
1911  Array<OneD, unsigned int> ncols(n_exp);
1912 
1913  switch (gkey.GetMatrixType())
1914  {
1915  case StdRegions::eBwdTrans:
1916  {
1917  // set up an array of integers for block matrix construction
1918  for (i = 0; i < n_exp; ++i)
1919  {
1920  nrows[i] = (*m_exp)[elmt_id.find(i)->second]->GetTotPoints();
1921  ncols[i] = (*m_exp)[elmt_id.find(i)->second]->GetNcoeffs();
1922  }
1923  }
1924  break;
1926  {
1927  // set up an array of integers for block matrix construction
1928  for (i = 0; i < n_exp; ++i)
1929  {
1930  nrows[i] = (*m_exp)[elmt_id.find(i)->second]->GetNcoeffs();
1931  ncols[i] = (*m_exp)[elmt_id.find(i)->second]->GetTotPoints();
1932  }
1933  }
1934  break;
1935  case StdRegions::eMass:
1936  case StdRegions::eInvMass:
1940  {
1941  // set up an array of integers for block matrix construction
1942  for (i = 0; i < n_exp; ++i)
1943  {
1944  nrows[i] = (*m_exp)[elmt_id.find(i)->second]->GetNcoeffs();
1945  ncols[i] = (*m_exp)[elmt_id.find(i)->second]->GetNcoeffs();
1946  }
1947  }
1948  break;
1949 
1951  {
1952  // set up an array of integers for block matrix construction
1953  for (i = 0; i < n_exp; ++i)
1954  {
1955  nrows[i] = (*m_exp)[elmt_id.find(i)->second]->GetNcoeffs();
1956  ncols[i] =
1957  (*m_exp)[elmt_id.find(i)->second]->NumDGBndryCoeffs();
1958  }
1959  }
1960  break;
1962  {
1963  // set up an array of integers for block matrix construction
1964  for (i = 0; i < n_exp; ++i)
1965  {
1966  nrows[i] =
1967  (*m_exp)[elmt_id.find(i)->second]->NumDGBndryCoeffs();
1968  ncols[i] =
1969  (*m_exp)[elmt_id.find(i)->second]->NumDGBndryCoeffs();
1970  }
1971  }
1972  break;
1973  default:
1974  {
1976  "Global Matrix creation not defined for this "
1977  "type of matrix");
1978  }
1979  }
1980 
1981  MatrixStorage blkmatStorage = eDIAGONAL;
1982  BlkMatrix = MemoryManager<DNekScalBlkMat>::AllocateSharedPtr(nrows, ncols,
1983  blkmatStorage);
1984 
1985  int nvarcoeffs = gkey.GetNVarCoeffs();
1986  int eid;
1987  Array<OneD, NekDouble> varcoeffs_wk;
1988 
1989  for (i = cnt1 = 0; i < n_exp; ++i)
1990  {
1991  // need to be initialised with zero size for non
1992  // variable coefficient case
1993  StdRegions::VarCoeffMap varcoeffs;
1994 
1995  eid = elmt_id[i];
1996  if (nvarcoeffs > 0)
1997  {
1998  varcoeffs = StdRegions::RestrictCoeffMap(
1999  gkey.GetVarCoeffs(), m_phys_offset[i],
2000  (*m_exp)[i]->GetTotPoints());
2001  }
2002 
2003  LocalRegions::MatrixKey matkey(
2004  gkey.GetMatrixType(), (*m_exp)[eid]->DetShapeType(), *(*m_exp)[eid],
2005  gkey.GetConstFactors(), varcoeffs);
2006 
2007  loc_mat = std::dynamic_pointer_cast<LocalRegions::Expansion>(
2008  (*m_exp)[elmt_id.find(i)->second])
2009  ->GetLocMatrix(matkey);
2010  BlkMatrix->SetBlock(i, i, loc_mat);
2011  }
2012 
2013  return BlkMatrix;
2014 }
2015 
2017  const GlobalMatrixKey &gkey)
2018 {
2019  auto matrixIter = m_blockMat->find(gkey);
2020 
2021  if (matrixIter == m_blockMat->end())
2022  {
2023  return ((*m_blockMat)[gkey] = GenBlockMatrix(gkey));
2024  }
2025  else
2026  {
2027  return matrixIter->second;
2028  }
2029 }
2030 
2031 // Routines for continous matrix solution
2032 /**
2033  * This operation is equivalent to the evaluation of
2034  * \f$\underline{\boldsymbol{M}}^e\boldsymbol{\hat{u}}_l\f$, that is,
2035  * \f[ \left[
2036  * \begin{array}{cccc}
2037  * \boldsymbol{M}^1 & 0 & \hspace{3mm}0 \hspace{3mm}& 0 \\
2038  * 0 & \boldsymbol{M}^2 & 0 & 0 \\
2039  * 0 & 0 & \ddots & 0 \\
2040  * 0 & 0 & 0 & \boldsymbol{M}^{N_{\mathrm{el}}} \end{array} \right]
2041  *\left [ \begin{array}{c}
2042  * \boldsymbol{\hat{u}}^{1} \\
2043  * \boldsymbol{\hat{u}}^{2} \\
2044  * \vdots \\
2045  * \boldsymbol{\hat{u}}^{{{N_{\mathrm{el}}}}} \end{array} \right ]\f]
2046  * where \f$\boldsymbol{M}^e\f$ are the local matrices of type
2047  * specified by the key \a mkey. The decoupling of the local matrices
2048  * allows for a local evaluation of the operation. However, rather than
2049  * a local matrix-vector multiplication, the local operations are
2050  * evaluated as implemented in the function
2051  * StdRegions#StdExpansion#GeneralMatrixOp.
2052  *
2053  * @param mkey This key uniquely defines the type matrix
2054  * required for the operation.
2055  * @param inarray The vector \f$\boldsymbol{\hat{u}}_l\f$ of
2056  * size \f$N_{\mathrm{eof}}\f$.
2057  * @param outarray The resulting vector of size
2058  * \f$N_{\mathrm{eof}}\f$.
2059  */
2061  const Array<OneD, const NekDouble> &inarray,
2062  Array<OneD, NekDouble> &outarray)
2063 {
2064  int nvarcoeffs = gkey.GetNVarCoeffs();
2065 
2066  if ((nvarcoeffs == 0) && (gkey.GetMatrixType() == StdRegions::eHelmholtz))
2067  {
2068  // initialise if required
2069  if (m_collections.size() &&
2071  {
2072  for (int i = 0; i < m_collections.size(); ++i)
2073  {
2074  m_collections[i].Initialise(Collections::eHelmholtz,
2075  gkey.GetConstFactors());
2076  }
2078  }
2079  else
2080  {
2081  for (int i = 0; i < m_collections.size(); ++i)
2082  {
2083  m_collections[i].CheckFactors(Collections::eHelmholtz,
2084  gkey.GetConstFactors(),
2085  m_coll_phys_offset[i]);
2086  }
2087  }
2088 
2090  for (int i = 0; i < m_collections.size(); ++i)
2091  {
2092  m_collections[i].ApplyOperator(
2094  tmp = outarray + m_coll_coeff_offset[i]);
2095  }
2096  }
2097  else
2098  {
2099  Array<OneD, NekDouble> tmp_outarray;
2100  for (int i = 0; i < (*m_exp).size(); ++i)
2101  {
2102  // need to be initialised with zero size for non
2103  // variable coefficient case
2104  StdRegions::VarCoeffMap varcoeffs;
2105 
2106  if (nvarcoeffs > 0)
2107  {
2108  varcoeffs = StdRegions::RestrictCoeffMap(
2109  gkey.GetVarCoeffs(), m_phys_offset[i],
2110  (*m_exp)[i]->GetTotPoints());
2111  }
2112 
2114  gkey.GetMatrixType(), (*m_exp)[i]->DetShapeType(),
2115  *((*m_exp)[i]), gkey.GetConstFactors(), varcoeffs);
2116 
2117  (*m_exp)[i]->GeneralMatrixOp(
2118  inarray + m_coeff_offset[i],
2119  tmp_outarray = outarray + m_coeff_offset[i], mkey);
2120  }
2121  }
2122 }
2123 
2124 /**
2125  * Retrieves local matrices from each expansion in the expansion list
2126  * and combines them together to generate a global matrix system.
2127  * @param mkey Matrix key for the matrix to be generated.
2128  * @param locToGloMap Local to global mapping.
2129  * @returns Shared pointer to the generated global matrix.
2130  */
2132  const GlobalMatrixKey &mkey, const AssemblyMapCGSharedPtr &locToGloMap)
2133 {
2134  int i, j, n, gid1, gid2, cntdim1, cntdim2;
2135  NekDouble sign1, sign2;
2136  DNekScalMatSharedPtr loc_mat;
2137 
2138  unsigned int glob_rows = 0;
2139  unsigned int glob_cols = 0;
2140  unsigned int loc_rows = 0;
2141  unsigned int loc_cols = 0;
2142 
2143  bool assembleFirstDim = false;
2144  bool assembleSecondDim = false;
2145 
2146  switch (mkey.GetMatrixType())
2147  {
2148  case StdRegions::eBwdTrans:
2149  {
2150  glob_rows = m_npoints;
2151  glob_cols = locToGloMap->GetNumGlobalCoeffs();
2152 
2153  assembleFirstDim = false;
2154  assembleSecondDim = true;
2155  }
2156  break;
2158  {
2159  glob_rows = locToGloMap->GetNumGlobalCoeffs();
2160  glob_cols = m_npoints;
2161 
2162  assembleFirstDim = true;
2163  assembleSecondDim = false;
2164  }
2165  break;
2166  case StdRegions::eMass:
2170  {
2171  glob_rows = locToGloMap->GetNumGlobalCoeffs();
2172  glob_cols = locToGloMap->GetNumGlobalCoeffs();
2173 
2174  assembleFirstDim = true;
2175  assembleSecondDim = true;
2176  }
2177  break;
2178  default:
2179  {
2181  "Global Matrix creation not defined for this "
2182  "type of matrix");
2183  }
2184  }
2185 
2186  COOMatType spcoomat;
2187  CoordType coord;
2188 
2189  int nvarcoeffs = mkey.GetNVarCoeffs();
2190  int eid;
2191 
2192  // fill global matrix
2193  for (n = cntdim1 = cntdim2 = 0; n < (*m_exp).size(); ++n)
2194  {
2195  // need to be initialised with zero size for non
2196  // variable coefficient case
2197  StdRegions::VarCoeffMap varcoeffs;
2198 
2199  eid = n;
2200  if (nvarcoeffs > 0)
2201  {
2202  varcoeffs = StdRegions::RestrictCoeffMap(
2203  mkey.GetVarCoeffs(), m_phys_offset[eid],
2204  (*m_exp)[eid]->GetTotPoints());
2205  }
2206 
2207  LocalRegions::MatrixKey matkey(
2208  mkey.GetMatrixType(), (*m_exp)[eid]->DetShapeType(),
2209  *((*m_exp)[eid]), mkey.GetConstFactors(), varcoeffs);
2210 
2211  loc_mat =
2212  std::dynamic_pointer_cast<LocalRegions::Expansion>((*m_exp)[n])
2213  ->GetLocMatrix(matkey);
2214 
2215  loc_rows = loc_mat->GetRows();
2216  loc_cols = loc_mat->GetColumns();
2217 
2218  for (i = 0; i < loc_rows; ++i)
2219  {
2220  if (assembleFirstDim)
2221  {
2222  gid1 = locToGloMap->GetLocalToGlobalMap(cntdim1 + i);
2223  sign1 = locToGloMap->GetLocalToGlobalSign(cntdim1 + i);
2224  }
2225  else
2226  {
2227  gid1 = cntdim1 + i;
2228  sign1 = 1.0;
2229  }
2230 
2231  for (j = 0; j < loc_cols; ++j)
2232  {
2233  if (assembleSecondDim)
2234  {
2235  gid2 = locToGloMap->GetLocalToGlobalMap(cntdim2 + j);
2236  sign2 = locToGloMap->GetLocalToGlobalSign(cntdim2 + j);
2237  }
2238  else
2239  {
2240  gid2 = cntdim2 + j;
2241  sign2 = 1.0;
2242  }
2243 
2244  // sparse matrix fill
2245  coord = make_pair(gid1, gid2);
2246  if (spcoomat.count(coord) == 0)
2247  {
2248  spcoomat[coord] = sign1 * sign2 * (*loc_mat)(i, j);
2249  }
2250  else
2251  {
2252  spcoomat[coord] += sign1 * sign2 * (*loc_mat)(i, j);
2253  }
2254  }
2255  }
2256  cntdim1 += loc_rows;
2257  cntdim2 += loc_cols;
2258  }
2259 
2261  glob_cols, spcoomat);
2262 }
2263 
2265  const GlobalLinSysKey &mkey, const AssemblyMapCGSharedPtr &locToGloMap)
2266 {
2267  int i, j, n, gid1, gid2, loc_lda, eid;
2268  NekDouble sign1, sign2, value;
2269  DNekScalMatSharedPtr loc_mat;
2270 
2271  int totDofs = locToGloMap->GetNumGlobalCoeffs();
2272  int NumDirBCs = locToGloMap->GetNumGlobalDirBndCoeffs();
2273 
2274  unsigned int rows = totDofs - NumDirBCs;
2275  unsigned int cols = totDofs - NumDirBCs;
2276  NekDouble zero = 0.0;
2277 
2278  DNekMatSharedPtr Gmat;
2279  int bwidth = locToGloMap->GetFullSystemBandWidth();
2280 
2281  int nvarcoeffs = mkey.GetNVarCoeffs();
2282  MatrixStorage matStorage;
2283 
2284  map<int, RobinBCInfoSharedPtr> RobinBCInfo = GetRobinBCInfo();
2285 
2286  switch (mkey.GetMatrixType())
2287  {
2288  // case for all symmetric matices
2291  if ((2 * (bwidth + 1)) < rows)
2292  {
2295  rows, cols, zero, matStorage, bwidth, bwidth);
2296  }
2297  else
2298  {
2299  matStorage = ePOSITIVE_DEFINITE_SYMMETRIC;
2301  rows, cols, zero, matStorage);
2302  }
2303 
2304  break;
2305  default: // Assume general matrix - currently only set up
2306  // for full invert
2307  {
2308  matStorage = eFULL;
2310  rows, cols, zero, matStorage);
2311  }
2312  }
2313 
2314  // fill global symmetric matrix
2315  for (n = 0; n < (*m_exp).size(); ++n)
2316  {
2317  // need to be initialised with zero size for non
2318  // variable coefficient case
2319  StdRegions::VarCoeffMap varcoeffs;
2320 
2321  eid = n;
2322  if (nvarcoeffs > 0)
2323  {
2324  varcoeffs = StdRegions::RestrictCoeffMap(
2325  mkey.GetVarCoeffs(), m_phys_offset[eid],
2326  (*m_exp)[eid]->GetTotPoints());
2327  }
2328 
2329  LocalRegions::MatrixKey matkey(
2330  mkey.GetMatrixType(), (*m_exp)[eid]->DetShapeType(),
2331  *((*m_exp)[eid]), mkey.GetConstFactors(), varcoeffs);
2332 
2333  loc_mat =
2334  std::dynamic_pointer_cast<LocalRegions::Expansion>((*m_exp)[n])
2335  ->GetLocMatrix(matkey);
2336 
2337  if (RobinBCInfo.count(n) != 0) // add robin mass matrix
2338  {
2340 
2341  // declare local matrix from scaled matrix.
2342  int rows = loc_mat->GetRows();
2343  int cols = loc_mat->GetColumns();
2344  const NekDouble *dat = loc_mat->GetRawPtr();
2345  DNekMatSharedPtr new_mat =
2347  Blas::Dscal(rows * cols, loc_mat->Scale(), new_mat->GetRawPtr(), 1);
2348 
2349  // add local matrix contribution
2350  for (rBC = RobinBCInfo.find(n)->second; rBC; rBC = rBC->next)
2351  {
2352  (*m_exp)[n]->AddRobinMassMatrix(
2353  rBC->m_robinID, rBC->m_robinPrimitiveCoeffs, new_mat);
2354  }
2355 
2356  NekDouble one = 1.0;
2357  // redeclare loc_mat to point to new_mat plus the scalar.
2358  loc_mat =
2360  }
2361 
2362  loc_lda = loc_mat->GetColumns();
2363 
2364  for (i = 0; i < loc_lda; ++i)
2365  {
2366  gid1 = locToGloMap->GetLocalToGlobalMap(m_coeff_offset[n] + i) -
2367  NumDirBCs;
2368  sign1 = locToGloMap->GetLocalToGlobalSign(m_coeff_offset[n] + i);
2369  if (gid1 >= 0)
2370  {
2371  for (j = 0; j < loc_lda; ++j)
2372  {
2373  gid2 = locToGloMap->GetLocalToGlobalMap(m_coeff_offset[n] +
2374  j) -
2375  NumDirBCs;
2376  sign2 = locToGloMap->GetLocalToGlobalSign(
2377  m_coeff_offset[n] + j);
2378  if (gid2 >= 0)
2379  {
2380  // When global matrix is symmetric,
2381  // only add the value for the upper
2382  // triangular part in order to avoid
2383  // entries to be entered twice
2384  if ((matStorage == eFULL) || (gid2 >= gid1))
2385  {
2386  value = Gmat->GetValue(gid1, gid2) +
2387  sign1 * sign2 * (*loc_mat)(i, j);
2388  Gmat->SetValue(gid1, gid2, value);
2389  }
2390  }
2391  }
2392  }
2393  }
2394  }
2395 
2396  return Gmat;
2397 }
2398 
2399 /**
2400  * Consider a linear system
2401  * \f$\boldsymbol{M\hat{u}}_g=\boldsymbol{f}\f$ to be solved. Dependent
2402  * on the solution method, this function constructs
2403  * - <b>The full linear system</b><BR>
2404  * A call to the function #GenGlobalLinSysFullDirect
2405  * - <b>The statically condensed linear system</b><BR>
2406  * A call to the function #GenGlobalLinSysStaticCond
2407  *
2408  * @param mkey A key which uniquely defines the global
2409  * matrix to be constructed.
2410  * @param locToGloMap Contains the mapping array and required
2411  * information for the transformation from
2412  * local to global degrees of freedom.
2413  * @return (A shared pointer to) the global linear system in
2414  * required format.
2415  */
2417  const GlobalLinSysKey &mkey, const AssemblyMapCGSharedPtr &locToGloMap)
2418 {
2419  GlobalLinSysSharedPtr returnlinsys;
2420  std::shared_ptr<ExpList> vExpList = GetSharedThisPtr();
2421 
2423 
2424  if (vType >= eSIZE_GlobalSysSolnType)
2425  {
2426  NEKERROR(ErrorUtil::efatal, "Matrix solution type not defined");
2427  }
2428  std::string vSolnType = MultiRegions::GlobalSysSolnTypeMap[vType];
2429 
2430  return GetGlobalLinSysFactory().CreateInstance(vSolnType, mkey, vExpList,
2431  locToGloMap);
2432 }
2433 
2435  const GlobalLinSysKey &mkey, const AssemblyMapSharedPtr &locToGloMap)
2436 {
2437  std::shared_ptr<ExpList> vExpList = GetSharedThisPtr();
2438  const map<int, RobinBCInfoSharedPtr> vRobinBCInfo = GetRobinBCInfo();
2439 
2441 
2442  if (vType >= eSIZE_GlobalSysSolnType)
2443  {
2444  NEKERROR(ErrorUtil::efatal, "Matrix solution type not defined");
2445  }
2446  std::string vSolnType = MultiRegions::GlobalSysSolnTypeMap[vType];
2447 
2448  return GetGlobalLinSysFactory().CreateInstance(vSolnType, mkey, vExpList,
2449  locToGloMap);
2450 }
2451 
2452 /**
2453  * Given the elemental coefficients \f$\hat{u}_n^e\f$ of
2454  * an expansion, this function evaluates the spectral/hp
2455  * expansion \f$u^{\delta}(\boldsymbol{x})\f$ at the
2456  * quadrature points \f$\boldsymbol{x}_i\f$. The operation
2457  * is evaluated locally by the elemental function
2458  * StdRegions#StdExpansion#BwdTrans.
2459  *
2460  * @param inarray An array of size \f$N_{\mathrm{eof}}\f$
2461  * containing the local coefficients
2462  * \f$\hat{u}_n^e\f$.
2463  * @param outarray The resulting physical values at the
2464  * quadrature points
2465  * \f$u^{\delta}(\boldsymbol{x}_i)\f$
2466  * will be stored in this array of size
2467  * \f$Q_{\mathrm{tot}}\f$.
2468  */
2469 
2471  Array<OneD, NekDouble> &outarray)
2472 {
2473  LibUtilities::Timer timer;
2474 
2475  if (m_expType == e0D)
2476  {
2477  Vmath::Vcopy(m_ncoeffs, inarray, 1, outarray, 1);
2478  }
2479  else
2480  {
2481  // initialise if required
2483  {
2484  for (int i = 0; i < m_collections.size(); ++i)
2485  {
2486  m_collections[i].Initialise(Collections::eBwdTrans);
2487  }
2489  }
2490 
2491  LIKWID_MARKER_START("v_BwdTrans");
2492  timer.Start();
2493 
2495  for (int i = 0; i < m_collections.size(); ++i)
2496  {
2497  m_collections[i].ApplyOperator(
2499  tmp = outarray + m_coll_phys_offset[i]);
2500  }
2501 
2502  timer.Stop();
2503  LIKWID_MARKER_STOP("v_BwdTrans");
2504  }
2505 
2506  // Elapsed time
2507  timer.AccumulateRegion("Collections:BwdTrans", 10);
2508 }
2509 
2511  const Array<OneD, const NekDouble> &gloCoord)
2512 {
2513  return GetExp(GetExpIndex(gloCoord));
2514 }
2515 
2516 /**
2517  * @todo need a smarter search here that first just looks at bounding
2518  * vertices - suggest first seeing if point is within 10% of
2519  * region defined by vertices. The do point search.
2520  */
2522  NekDouble tol, bool returnNearestElmt, int cachedId,
2523  NekDouble maxDistance)
2524 {
2525  Array<OneD, NekDouble> Lcoords(gloCoord.size());
2526 
2527  return GetExpIndex(gloCoord, Lcoords, tol, returnNearestElmt, cachedId,
2528  maxDistance);
2529 }
2530 
2532  Array<OneD, NekDouble> &locCoords, NekDouble tol,
2533  bool returnNearestElmt, int cachedId,
2534  NekDouble maxDistance)
2535 {
2536  if (GetNumElmts() == 0)
2537  {
2538  return -1;
2539  }
2540 
2541  if (m_elmtToExpId.size() == 0)
2542  {
2543  // Loop in reverse order so that in case where using a
2544  // Homogeneous expansion it sets geometry ids to first part of
2545  // m_exp list. Otherwise will set to second (complex) expansion
2546  for (int i = (*m_exp).size() - 1; i >= 0; --i)
2547  {
2548  m_elmtToExpId[(*m_exp)[i]->GetGeom()->GetGlobalID()] = i;
2549  }
2550  }
2551 
2552  NekDouble nearpt = 1e6;
2553  NekDouble nearpt_min = 1e6;
2554  int min_id = -1;
2555  Array<OneD, NekDouble> savLocCoords(locCoords.size());
2556 
2557  if (cachedId >= 0 && cachedId < (*m_exp).size())
2558  {
2559  nearpt = 1e12;
2560  if ((*m_exp)[cachedId]->GetGeom()->MinMaxCheck(gloCoords) &&
2561  (*m_exp)[cachedId]->GetGeom()->ContainsPoint(gloCoords, locCoords,
2562  tol, nearpt))
2563  {
2564  return cachedId;
2565  }
2566  else if (returnNearestElmt && (nearpt < nearpt_min))
2567  {
2568  // If it does not lie within, keep track of which element
2569  // is nearest.
2570  min_id = cachedId;
2571  nearpt_min = nearpt;
2572  Vmath::Vcopy(locCoords.size(), locCoords, 1, savLocCoords, 1);
2573  }
2574  }
2575 
2576  NekDouble x = (gloCoords.size() > 0 ? gloCoords[0] : 0.0);
2577  NekDouble y = (gloCoords.size() > 1 ? gloCoords[1] : 0.0);
2578  NekDouble z = (gloCoords.size() > 2 ? gloCoords[2] : 0.0);
2581  GetExp(0)->GetCoordim(), -1, x, y, z);
2582 
2583  // Get the list of elements whose bounding box contains the desired
2584  // point.
2585  std::vector<int> elmts = m_graph->GetElementsContainingPoint(p);
2586 
2587  // Check each element in turn to see if point lies within it.
2588  for (int i = 0; i < elmts.size(); ++i)
2589  {
2590  int id = m_elmtToExpId[elmts[i]];
2591  if (id == cachedId)
2592  {
2593  continue;
2594  }
2595  if ((*m_exp)[id]->GetGeom()->ContainsPoint(gloCoords, locCoords, tol,
2596  nearpt))
2597  {
2598  return id;
2599  }
2600  else if (returnNearestElmt && (nearpt < nearpt_min))
2601  {
2602  // If it does not lie within, keep track of which element
2603  // is nearest.
2604  min_id = id;
2605  nearpt_min = nearpt;
2606  Vmath::Vcopy(locCoords.size(), locCoords, 1, savLocCoords, 1);
2607  }
2608  }
2609 
2610  // If the calling function is with just the nearest element, return
2611  // that. Otherwise return -1 to indicate no matching elemenet found.
2612  if (returnNearestElmt && nearpt_min <= maxDistance)
2613  {
2614 
2615  std::string msg =
2616  "Failed to find point within element to "
2617  "tolerance of " +
2618  boost::lexical_cast<std::string>(tol) + " using local point (" +
2619  boost::lexical_cast<std::string>(locCoords[0]) + "," +
2620  boost::lexical_cast<std::string>(locCoords[1]) + "," +
2621  boost::lexical_cast<std::string>(locCoords[1]) +
2622  ") in element: " + boost::lexical_cast<std::string>(min_id);
2623  WARNINGL1(false, msg.c_str());
2624 
2625  Vmath::Vcopy(locCoords.size(), savLocCoords, 1, locCoords, 1);
2626  return min_id;
2627  }
2628  else
2629  {
2630  return -1;
2631  }
2632 }
2633 
2634 /**
2635  * Given some coordinates, output the expansion field value at that
2636  * point
2637  */
2639  const Array<OneD, const NekDouble> &phys)
2640 {
2641  int dim = GetCoordim(0);
2642  ASSERTL0(dim == coords.size(), "Invalid coordinate dimension.");
2643 
2644  // Grab the element index corresponding to coords.
2645  Array<OneD, NekDouble> xi(dim);
2646  int elmtIdx = GetExpIndex(coords, xi);
2647  ASSERTL0(elmtIdx > 0, "Unable to find element containing point.");
2648 
2649  // Grab that element's physical storage.
2650  Array<OneD, NekDouble> elmtPhys = phys + m_phys_offset[elmtIdx];
2651 
2652  // Evaluate the element at the appropriate point.
2653  return (*m_exp)[elmtIdx]->StdPhysEvaluate(xi, elmtPhys);
2654 }
2655 
2656 /**
2657  * Configures geometric info, such as tangent direction, on each
2658  * expansion.
2659  * @param graph2D Mesh
2660  */
2662 {
2663 }
2664 
2665 /**
2666  * @brief Reset geometry information, metrics, matrix managers and
2667  * geometry information.
2668  *
2669  * This routine clears all matrix managers and resets all geometry
2670  * information, which allows the geometry information to be dynamically
2671  * updated as the solver is run.
2672  */
2674 {
2675  // Reset matrix managers.
2677  LocalRegions::MatrixKey::opLess>::ClearManager();
2679  LocalRegions::MatrixKey::opLess>::ClearManager();
2680 
2681  // Loop over all elements and reset geometry information.
2682  for (int i = 0; i < m_exp->size(); ++i)
2683  {
2684  (*m_exp)[i]->GetGeom()->Reset(m_graph->GetCurvedEdges(),
2685  m_graph->GetCurvedFaces());
2686  }
2687 
2688  // Loop over all elements and rebuild geometric factors.
2689  for (int i = 0; i < m_exp->size(); ++i)
2690  {
2691  (*m_exp)[i]->Reset();
2692  }
2693 }
2694 
2695 /**
2696  * Write Tecplot Files Header
2697  * @param outfile Output file name.
2698  * @param var variables names
2699  */
2700 void ExpList::v_WriteTecplotHeader(std::ostream &outfile, std::string var)
2701 {
2702  if (GetNumElmts() == 0)
2703  {
2704  return;
2705  }
2706 
2707  int coordim = GetExp(0)->GetCoordim();
2708  char vars[3] = {'x', 'y', 'z'};
2709 
2710  if (m_expType == e3DH1D)
2711  {
2712  coordim += 1;
2713  }
2714  else if (m_expType == e3DH2D)
2715  {
2716  coordim += 2;
2717  }
2718 
2719  outfile << "Variables = x";
2720  for (int i = 1; i < coordim; ++i)
2721  {
2722  outfile << ", " << vars[i];
2723  }
2724 
2725  if (var.size() > 0)
2726  {
2727  outfile << ", " << var;
2728  }
2729 
2730  outfile << std::endl << std::endl;
2731 }
2732 
2733 /**
2734  * Write Tecplot Files Zone
2735  * @param outfile Output file name.
2736  * @param expansion Expansion that is considered
2737  */
2738 void ExpList::v_WriteTecplotZone(std::ostream &outfile, int expansion)
2739 {
2740  int i, j;
2741  int coordim = GetCoordim(0);
2742  int nPoints = GetTotPoints();
2743  int nBases = (*m_exp)[0]->GetNumBases();
2744  int numBlocks = 0;
2745 
2747 
2748  if (expansion == -1)
2749  {
2750  nPoints = GetTotPoints();
2751 
2752  coords[0] = Array<OneD, NekDouble>(nPoints);
2753  coords[1] = Array<OneD, NekDouble>(nPoints);
2754  coords[2] = Array<OneD, NekDouble>(nPoints);
2755 
2756  GetCoords(coords[0], coords[1], coords[2]);
2757 
2758  for (i = 0; i < m_exp->size(); ++i)
2759  {
2760  int numInt = 1;
2761 
2762  for (j = 0; j < nBases; ++j)
2763  {
2764  numInt *= (*m_exp)[i]->GetNumPoints(j) - 1;
2765  }
2766 
2767  numBlocks += numInt;
2768  }
2769  }
2770  else
2771  {
2772  nPoints = (*m_exp)[expansion]->GetTotPoints();
2773 
2774  coords[0] = Array<OneD, NekDouble>(nPoints);
2775  coords[1] = Array<OneD, NekDouble>(nPoints);
2776  coords[2] = Array<OneD, NekDouble>(nPoints);
2777 
2778  (*m_exp)[expansion]->GetCoords(coords[0], coords[1], coords[2]);
2779 
2780  numBlocks = 1;
2781  for (j = 0; j < nBases; ++j)
2782  {
2783  numBlocks *= (*m_exp)[expansion]->GetNumPoints(j) - 1;
2784  }
2785  }
2786 
2787  if (m_expType == e3DH1D)
2788  {
2789  nBases += 1;
2790  coordim += 1;
2791  int nPlanes = GetZIDs().size();
2792  NekDouble tmp = numBlocks * (nPlanes - 1.0) / nPlanes;
2793  numBlocks = (int)tmp;
2794  }
2795  else if (m_expType == e3DH2D)
2796  {
2797  nBases += 2;
2798  coordim += 1;
2799  }
2800 
2801  outfile << "Zone, N=" << nPoints << ", E=" << numBlocks << ", F=FEBlock";
2802 
2803  switch (nBases)
2804  {
2805  case 2:
2806  outfile << ", ET=QUADRILATERAL" << std::endl;
2807  break;
2808  case 3:
2809  outfile << ", ET=BRICK" << std::endl;
2810  break;
2811  default:
2812  NEKERROR(ErrorUtil::efatal, "Not set up for this type of output");
2813  break;
2814  }
2815 
2816  // Write out coordinates
2817  for (j = 0; j < coordim; ++j)
2818  {
2819  for (i = 0; i < nPoints; ++i)
2820  {
2821  outfile << coords[j][i] << " ";
2822  if (i % 1000 == 0 && i)
2823  {
2824  outfile << std::endl;
2825  }
2826  }
2827  outfile << std::endl;
2828  }
2829 }
2830 
2831 void ExpList::v_WriteTecplotConnectivity(std::ostream &outfile, int expansion)
2832 {
2833  int i, j, k, l;
2834  int nbase = (*m_exp)[0]->GetNumBases();
2835  int cnt = 0;
2836 
2837  std::shared_ptr<LocalRegions::ExpansionVector> exp = m_exp;
2838 
2839  if (expansion != -1)
2840  {
2841  exp = std::shared_ptr<LocalRegions::ExpansionVector>(
2843  (*exp)[0] = (*m_exp)[expansion];
2844  }
2845 
2846  if (nbase == 2)
2847  {
2848  for (i = 0; i < (*exp).size(); ++i)
2849  {
2850  const int np0 = (*exp)[i]->GetNumPoints(0);
2851  const int np1 = (*exp)[i]->GetNumPoints(1);
2852 
2853  for (j = 1; j < np1; ++j)
2854  {
2855  for (k = 1; k < np0; ++k)
2856  {
2857  outfile << cnt + (j - 1) * np0 + k << " ";
2858  outfile << cnt + (j - 1) * np0 + k + 1 << " ";
2859  outfile << cnt + j * np0 + k + 1 << " ";
2860  outfile << cnt + j * np0 + k << endl;
2861  }
2862  }
2863 
2864  cnt += np0 * np1;
2865  }
2866  }
2867  else if (nbase == 3)
2868  {
2869  for (i = 0; i < (*exp).size(); ++i)
2870  {
2871  const int np0 = (*exp)[i]->GetNumPoints(0);
2872  const int np1 = (*exp)[i]->GetNumPoints(1);
2873  const int np2 = (*exp)[i]->GetNumPoints(2);
2874  const int np01 = np0 * np1;
2875 
2876  for (j = 1; j < np2; ++j)
2877  {
2878  for (k = 1; k < np1; ++k)
2879  {
2880  for (l = 1; l < np0; ++l)
2881  {
2882  outfile << cnt + (j - 1) * np01 + (k - 1) * np0 + l
2883  << " ";
2884  outfile << cnt + (j - 1) * np01 + (k - 1) * np0 + l + 1
2885  << " ";
2886  outfile << cnt + (j - 1) * np01 + k * np0 + l + 1
2887  << " ";
2888  outfile << cnt + (j - 1) * np01 + k * np0 + l << " ";
2889  outfile << cnt + j * np01 + (k - 1) * np0 + l << " ";
2890  outfile << cnt + j * np01 + (k - 1) * np0 + l + 1
2891  << " ";
2892  outfile << cnt + j * np01 + k * np0 + l + 1 << " ";
2893  outfile << cnt + j * np01 + k * np0 + l << endl;
2894  }
2895  }
2896  }
2897  cnt += np0 * np1 * np2;
2898  }
2899  }
2900  else
2901  {
2902  NEKERROR(ErrorUtil::efatal, "Not set up for this dimension");
2903  }
2904 }
2905 
2906 /**
2907  * Write Tecplot Files Field
2908  * @param outfile Output file name.
2909  * @param expansion Expansion that is considered
2910  */
2911 void ExpList::v_WriteTecplotField(std::ostream &outfile, int expansion)
2912 {
2913  if (expansion == -1)
2914  {
2915  int totpoints = GetTotPoints();
2916  if (m_physState == false)
2917  {
2919  }
2920 
2921  for (int i = 0; i < totpoints; ++i)
2922  {
2923  outfile << m_phys[i] << " ";
2924  if (i % 1000 == 0 && i)
2925  {
2926  outfile << std::endl;
2927  }
2928  }
2929  outfile << std::endl;
2930  }
2931  else
2932  {
2933  int nPoints = (*m_exp)[expansion]->GetTotPoints();
2934 
2935  for (int i = 0; i < nPoints; ++i)
2936  {
2937  outfile << m_phys[i + m_phys_offset[expansion]] << " ";
2938  }
2939 
2940  outfile << std::endl;
2941  }
2942 }
2943 
2944 void ExpList::WriteVtkHeader(std::ostream &outfile)
2945 {
2946  outfile << "<?xml version=\"1.0\"?>" << endl;
2947  outfile << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" "
2948  << "byte_order=\"LittleEndian\">" << endl;
2949  outfile << " <UnstructuredGrid>" << endl;
2950 }
2951 
2952 void ExpList::WriteVtkFooter(std::ostream &outfile)
2953 {
2954  outfile << " </UnstructuredGrid>" << endl;
2955  outfile << "</VTKFile>" << endl;
2956 }
2957 
2958 void ExpList::v_WriteVtkPieceHeader(std::ostream &outfile, int expansion,
2959  int istrip)
2960 {
2961  boost::ignore_unused(istrip);
2962  int i, j, k;
2963  int nbase = (*m_exp)[expansion]->GetNumBases();
2964  int ntot = (*m_exp)[expansion]->GetTotPoints();
2965  int nquad[3];
2966 
2967  int ntotminus = 1;
2968  for (i = 0; i < nbase; ++i)
2969  {
2970  nquad[i] = (*m_exp)[expansion]->GetNumPoints(i);
2971  ntotminus *= (nquad[i] - 1);
2972  }
2973 
2974  Array<OneD, NekDouble> coords[3];
2975  coords[0] = Array<OneD, NekDouble>(ntot, 0.0);
2976  coords[1] = Array<OneD, NekDouble>(ntot, 0.0);
2977  coords[2] = Array<OneD, NekDouble>(ntot, 0.0);
2978  (*m_exp)[expansion]->GetCoords(coords[0], coords[1], coords[2]);
2979 
2980  outfile << " <Piece NumberOfPoints=\"" << ntot << "\" NumberOfCells=\""
2981  << ntotminus << "\">" << endl;
2982  outfile << " <Points>" << endl;
2983  outfile << " <DataArray type=\"Float64\" "
2984  << "NumberOfComponents=\"3\" format=\"ascii\">" << endl;
2985  outfile << " ";
2986  for (i = 0; i < ntot; ++i)
2987  {
2988  for (j = 0; j < 3; ++j)
2989  {
2990  outfile << setprecision(8) << scientific << (float)coords[j][i]
2991  << " ";
2992  }
2993  outfile << endl;
2994  }
2995  outfile << endl;
2996  outfile << " </DataArray>" << endl;
2997  outfile << " </Points>" << endl;
2998  outfile << " <Cells>" << endl;
2999  outfile << " <DataArray type=\"Int32\" "
3000  << "Name=\"connectivity\" format=\"ascii\">" << endl;
3001 
3002  int ns = 0; // pow(2,dim) for later usage
3003  string ostr;
3004  switch (m_expType)
3005  {
3006  case e1D:
3007  {
3008  ns = 2;
3009  ostr = "3 ";
3010  for (i = 0; i < nquad[0] - 1; ++i)
3011  {
3012  outfile << i << " " << i + 1 << endl;
3013  }
3014  }
3015  break;
3016  case e2D:
3017  {
3018  ns = 4;
3019  ostr = "9 ";
3020  for (i = 0; i < nquad[0] - 1; ++i)
3021  {
3022  for (j = 0; j < nquad[1] - 1; ++j)
3023  {
3024  outfile << j * nquad[0] + i << " " << j * nquad[0] + i + 1
3025  << " " << (j + 1) * nquad[0] + i + 1 << " "
3026  << (j + 1) * nquad[0] + i << endl;
3027  }
3028  }
3029  }
3030  break;
3031  case e3D:
3032  {
3033  ns = 8;
3034  ostr = "12 ";
3035  for (i = 0; i < nquad[0] - 1; ++i)
3036  {
3037  for (j = 0; j < nquad[1] - 1; ++j)
3038  {
3039  for (k = 0; k < nquad[2] - 1; ++k)
3040  {
3041  outfile
3042  << k * nquad[0] * nquad[1] + j * nquad[0] + i << " "
3043  << k * nquad[0] * nquad[1] + j * nquad[0] + i + 1
3044  << " "
3045  << k * nquad[0] * nquad[1] + (j + 1) * nquad[0] +
3046  i + 1
3047  << " "
3048  << k * nquad[0] * nquad[1] + (j + 1) * nquad[0] + i
3049  << " "
3050  << (k + 1) * nquad[0] * nquad[1] + j * nquad[0] + i
3051  << " "
3052  << (k + 1) * nquad[0] * nquad[1] + j * nquad[0] +
3053  i + 1
3054  << " "
3055  << (k + 1) * nquad[0] * nquad[1] +
3056  (j + 1) * nquad[0] + i + 1
3057  << " "
3058  << (k + 1) * nquad[0] * nquad[1] +
3059  (j + 1) * nquad[0] + i
3060  << " " << endl;
3061  }
3062  }
3063  }
3064  }
3065  break;
3066  default:
3067  break;
3068  }
3069 
3070  outfile << endl;
3071  outfile << " </DataArray>" << endl;
3072  outfile << " <DataArray type=\"Int32\" "
3073  << "Name=\"offsets\" format=\"ascii\">" << endl;
3074  for (i = 0; i < ntotminus; ++i)
3075  {
3076  outfile << i * ns + ns << " ";
3077  }
3078  outfile << endl;
3079  outfile << " </DataArray>" << endl;
3080  outfile << " <DataArray type=\"UInt8\" "
3081  << "Name=\"types\" format=\"ascii\">" << endl;
3082  for (i = 0; i < ntotminus; ++i)
3083  {
3084  outfile << ostr;
3085  }
3086  outfile << endl;
3087  outfile << " </DataArray>" << endl;
3088  outfile << " </Cells>" << endl;
3089  outfile << " <PointData>" << endl;
3090 }
3091 
3092 void ExpList::WriteVtkPieceFooter(std::ostream &outfile, int expansion)
3093 {
3094  boost::ignore_unused(expansion);
3095  outfile << " </PointData>" << endl;
3096  outfile << " </Piece>" << endl;
3097 }
3098 
3099 void ExpList::v_WriteVtkPieceData(std::ostream &outfile, int expansion,
3100  std::string var)
3101 {
3102  int i;
3103  int nq = (*m_exp)[expansion]->GetTotPoints();
3104 
3105  // printing the fields of that zone
3106  outfile << " <DataArray type=\"Float64\" Name=\"" << var << "\">"
3107  << endl;
3108  outfile << " ";
3109 
3110  const Array<OneD, NekDouble> phys = m_phys + m_phys_offset[expansion];
3111 
3112  for (i = 0; i < nq; ++i)
3113  {
3114  outfile << (fabs(phys[i]) < NekConstants::kNekZeroTol ? 0 : phys[i])
3115  << " ";
3116  }
3117  outfile << endl;
3118  outfile << " </DataArray>" << endl;
3119 }
3120 
3121 /**
3122  * Given a spectral/hp approximation
3123  * \f$u^{\delta}(\boldsymbol{x})\f$ evaluated at the quadrature points
3124  * (which should be contained in #m_phys), this function calculates the
3125  * \f$L_\infty\f$ error of this approximation with respect to an exact
3126  * solution. The local distribution of the quadrature points allows an
3127  * elemental evaluation of this operation through the functions
3128  * StdRegions#StdExpansion#Linf.
3129  *
3130  * The exact solution, also evaluated at the quadrature
3131  * points, should be contained in the variable #m_phys of
3132  * the ExpList object \a Sol.
3133  *
3134  * @param soln A 1D array, containing the discrete
3135  * evaluation of the exact solution at the
3136  * quadrature points in its array #m_phys.
3137  * @return The \f$L_\infty\f$ error of the approximation.
3138  */
3140  const Array<OneD, const NekDouble> &soln)
3141 {
3142  NekDouble err = 0.0;
3143 
3144  if (soln == NullNekDouble1DArray)
3145  {
3146  err = Vmath::Vmax(m_npoints, inarray, 1);
3147  }
3148  else
3149  {
3150  for (int i = 0; i < m_npoints; ++i)
3151  {
3152  err = max(err, abs(inarray[i] - soln[i]));
3153  }
3154  }
3155 
3156  m_comm->GetRowComm()->AllReduce(err, LibUtilities::ReduceMax);
3157 
3158  return err;
3159 }
3160 
3161 /**
3162  * Given a spectral/hp approximation \f$u^{\delta}(\boldsymbol{x})\f$
3163  * evaluated at the quadrature points (which should be contained in
3164  * #m_phys), this function calculates the \f$L_2\f$ error of this
3165  * approximation with respect to an exact solution. The local
3166  * distribution of the quadrature points allows an elemental evaluation
3167  * of this operation through the functions StdRegions#StdExpansion#L2.
3168  *
3169  * The exact solution, also evaluated at the quadrature points, should
3170  * be contained in the variable #m_phys of the ExpList object \a Sol.
3171  *
3172  * @param Sol An ExpList, containing the discrete
3173  * evaluation of the exact solution at the
3174  * quadrature points in its array #m_phys.
3175  * @return The \f$L_2\f$ error of the approximation.
3176  */
3178  const Array<OneD, const NekDouble> &soln)
3179 {
3180  NekDouble err = 0.0, errl2;
3181  int i;
3182 
3183  if (soln == NullNekDouble1DArray)
3184  {
3185  for (i = 0; i < (*m_exp).size(); ++i)
3186  {
3187  errl2 = (*m_exp)[i]->L2(inarray + m_phys_offset[i]);
3188  err += errl2 * errl2;
3189  }
3190  }
3191  else
3192  {
3193  for (i = 0; i < (*m_exp).size(); ++i)
3194  {
3195  errl2 = (*m_exp)[i]->L2(inarray + m_phys_offset[i],
3196  soln + m_phys_offset[i]);
3197  err += errl2 * errl2;
3198  }
3199  }
3200 
3201  m_comm->GetRowComm()->AllReduce(err, LibUtilities::ReduceSum);
3202 
3203  return sqrt(err);
3204 }
3205 
3206 /**
3207  * The integration is evaluated locally, that is
3208  * \f[\int
3209  * f(\boldsymbol{x})d\boldsymbol{x}=\sum_{e=1}^{{N_{\mathrm{el}}}}
3210  * \left\{\int_{\Omega_e}f(\boldsymbol{x})d\boldsymbol{x}\right\}, \f]
3211  * where the integration over the separate elements is done by the
3212  * function StdRegions#StdExpansion#Integral, which discretely
3213  * evaluates the integral using Gaussian quadrature.
3214  *
3215  * @param inarray An array of size \f$Q_{\mathrm{tot}}\f$
3216  * containing the values of the function
3217  * \f$f(\boldsymbol{x})\f$ at the quadrature
3218  * points \f$\boldsymbol{x}_i\f$.
3219  * @return The value of the discretely evaluated integral
3220  * \f$\int f(\boldsymbol{x})d\boldsymbol{x}\f$.
3221  */
3223 {
3224  NekDouble sum = 0.0;
3225  int i = 0;
3226 
3227  for (i = 0; i < (*m_exp).size(); ++i)
3228  {
3229  sum += (*m_exp)[i]->Integral(inarray + m_phys_offset[i]);
3230  }
3231  m_comm->GetRowComm()->AllReduce(sum, LibUtilities::ReduceSum);
3232 
3233  return sum;
3234 }
3235 
3237  const Array<OneD, Array<OneD, NekDouble>> &inarray)
3238 {
3239  NekDouble flux = 0.0;
3240  int i = 0;
3241  int j;
3242 
3243  for (i = 0; i < (*m_exp).size(); ++i)
3244  {
3245  Array<OneD, Array<OneD, NekDouble>> tmp(inarray.size());
3246  for (j = 0; j < inarray.size(); ++j)
3247  {
3248  tmp[j] = Array<OneD, NekDouble>(inarray[j] + m_phys_offset[i]);
3249  }
3250  flux += (*m_exp)[i]->VectorFlux(tmp);
3251  }
3252 
3253  return flux;
3254 }
3255 
3257 {
3259  "This method is not defined or valid for this class type");
3260  Array<OneD, NekDouble> NoEnergy(1, 0.0);
3261  return NoEnergy;
3262 }
3263 
3265 {
3267  "This method is not defined or valid for this class type");
3269  return trans;
3270 }
3271 
3273 {
3275  "This method is not defined or valid for this class type");
3276  NekDouble len = 0.0;
3277  return len;
3278 }
3279 
3281 {
3282  boost::ignore_unused(lhom);
3284  "This method is not defined or valid for this class type");
3285 }
3286 
3288 {
3290  "This method is not defined or valid for this class type");
3291  Array<OneD, unsigned int> NoModes(1);
3292  return NoModes;
3293 }
3294 
3296 {
3298  "This method is not defined or valid for this class type");
3299  Array<OneD, unsigned int> NoModes(1);
3300  return NoModes;
3301 }
3302 
3304 {
3306  "ClearGlobalLinSysManager not implemented for ExpList.");
3307 }
3308 
3309 int ExpList::v_GetPoolCount(std::string poolName)
3310 {
3311  boost::ignore_unused(poolName);
3312  NEKERROR(ErrorUtil::efatal, "GetPoolCount not implemented for ExpList.");
3313  return -1;
3314 }
3315 
3316 void ExpList::v_UnsetGlobalLinSys(GlobalLinSysKey key, bool clearLocalMatrices)
3317 {
3318  boost::ignore_unused(key, clearLocalMatrices);
3320  "UnsetGlobalLinSys not implemented for ExpList.");
3321 }
3322 
3325 {
3327  "GetGlobalLinSysManager not implemented for ExpList.");
3328  return NullGlobalLinSysManager;
3329 }
3330 
3331 void ExpList::ExtractCoeffsFromFile(const std::string &fileName,
3333  const std::string &varName,
3334  Array<OneD, NekDouble> &coeffs)
3335 {
3336  string varString = fileName.substr(0, fileName.find_last_of("."));
3337  int j, k, len = varString.length();
3338  varString = varString.substr(len - 1, len);
3339 
3340  std::vector<LibUtilities::FieldDefinitionsSharedPtr> FieldDef;
3341  std::vector<std::vector<NekDouble>> FieldData;
3342 
3343  std::string ft = LibUtilities::FieldIO::GetFileType(fileName, comm);
3346  ft, comm, m_session->GetSharedFilesystem());
3347 
3348  f->Import(fileName, FieldDef, FieldData);
3349 
3350  bool found = false;
3351  for (j = 0; j < FieldDef.size(); ++j)
3352  {
3353  for (k = 0; k < FieldDef[j]->m_fields.size(); ++k)
3354  {
3355  if (FieldDef[j]->m_fields[k] == varName)
3356  {
3357  // Copy FieldData into locExpList
3358  ExtractDataToCoeffs(FieldDef[j], FieldData[j],
3359  FieldDef[j]->m_fields[k], coeffs);
3360  found = true;
3361  }
3362  }
3363  }
3364 
3365  ASSERTL0(found, "Could not find variable '" + varName +
3366  "' in file boundary condition " + fileName);
3367 }
3368 
3369 /**
3370  * Given a spectral/hp approximation
3371  * \f$u^{\delta}(\boldsymbol{x})\f$ evaluated at the quadrature points
3372  * (which should be contained in #m_phys), this function calculates the
3373  * \f$H^1_2\f$ error of this approximation with respect to an exact
3374  * solution. The local distribution of the quadrature points allows an
3375  * elemental evaluation of this operation through the functions
3376  * StdRegions#StdExpansion#H1.
3377  *
3378  * The exact solution, also evaluated at the quadrature points, should
3379  * be contained in the variable #m_phys of the ExpList object \a Sol.
3380  *
3381  * @param soln An 1D array, containing the discrete evaluation
3382  * of the exact solution at the quadrature points.
3383  *
3384  * @return The \f$H^1_2\f$ error of the approximation.
3385  */
3387  const Array<OneD, const NekDouble> &soln)
3388 {
3389  NekDouble err = 0.0, errh1;
3390  int i;
3391 
3392  for (i = 0; i < (*m_exp).size(); ++i)
3393  {
3394  errh1 = (*m_exp)[i]->H1(inarray + m_phys_offset[i],
3395  soln + m_phys_offset[i]);
3396  err += errh1 * errh1;
3397  }
3398 
3399  m_comm->GetRowComm()->AllReduce(err, LibUtilities::ReduceSum);
3400 
3401  return sqrt(err);
3402 }
3403 
3405  std::vector<LibUtilities::FieldDefinitionsSharedPtr> &fielddef,
3406  int NumHomoDir, Array<OneD, LibUtilities::BasisSharedPtr> &HomoBasis,
3407  std::vector<NekDouble> &HomoLen, bool homoStrips,
3408  std::vector<unsigned int> &HomoSIDs, std::vector<unsigned int> &HomoZIDs,
3409  std::vector<unsigned int> &HomoYIDs)
3410 {
3411  int startenum = (int)LibUtilities::eSegment;
3412  int endenum = (int)LibUtilities::eHexahedron;
3413  int s = 0;
3415 
3416  ASSERTL1(NumHomoDir == HomoBasis.size(),
3417  "Homogeneous basis is not the same length as NumHomoDir");
3418  ASSERTL1(NumHomoDir == HomoLen.size(),
3419  "Homogeneous length vector is not the same length as NumHomDir");
3420 
3421  // count number of shapes
3422  switch ((*m_exp)[0]->GetShapeDimension())
3423  {
3424  case 1:
3425  startenum = (int)LibUtilities::eSegment;
3426  endenum = (int)LibUtilities::eSegment;
3427  break;
3428  case 2:
3429  startenum = (int)LibUtilities::eTriangle;
3430  endenum = (int)LibUtilities::eQuadrilateral;
3431  break;
3432  case 3:
3433  startenum = (int)LibUtilities::eTetrahedron;
3434  endenum = (int)LibUtilities::eHexahedron;
3435  break;
3436  }
3437 
3438  for (s = startenum; s <= endenum; ++s)
3439  {
3440  std::vector<unsigned int> elementIDs;
3441  std::vector<LibUtilities::BasisType> basis;
3442  std::vector<unsigned int> numModes;
3443  std::vector<std::string> fields;
3444 
3445  bool first = true;
3446  bool UniOrder = true;
3447  int n;
3448 
3449  shape = (LibUtilities::ShapeType)s;
3450 
3451  for (int i = 0; i < (*m_exp).size(); ++i)
3452  {
3453  if ((*m_exp)[i]->GetGeom()->GetShapeType() == shape)
3454  {
3455  elementIDs.push_back((*m_exp)[i]->GetGeom()->GetGlobalID());
3456  if (first)
3457  {
3458  for (int j = 0; j < (*m_exp)[i]->GetNumBases(); ++j)
3459  {
3460  basis.push_back(
3461  (*m_exp)[i]->GetBasis(j)->GetBasisType());
3462  numModes.push_back(
3463  (*m_exp)[i]->GetBasis(j)->GetNumModes());
3464  }
3465 
3466  // add homogeneous direction details if defined
3467  for (n = 0; n < NumHomoDir; ++n)
3468  {
3469  basis.push_back(HomoBasis[n]->GetBasisType());
3470  numModes.push_back(HomoBasis[n]->GetNumModes());
3471  }
3472 
3473  first = false;
3474  }
3475  else
3476  {
3477  ASSERTL0(
3478  (*m_exp)[i]->GetBasis(0)->GetBasisType() == basis[0],
3479  "Routine is not set up for multiple bases definitions");
3480 
3481  for (int j = 0; j < (*m_exp)[i]->GetNumBases(); ++j)
3482  {
3483  numModes.push_back(
3484  (*m_exp)[i]->GetBasis(j)->GetNumModes());
3485  if (numModes[j] !=
3486  (*m_exp)[i]->GetBasis(j)->GetNumModes())
3487  {
3488  UniOrder = false;
3489  }
3490  }
3491  // add homogeneous direction details if defined
3492  for (n = 0; n < NumHomoDir; ++n)
3493  {
3494  numModes.push_back(HomoBasis[n]->GetNumModes());
3495  }
3496  }
3497  }
3498  }
3499 
3500  if (elementIDs.size() > 0)
3501  {
3504  AllocateSharedPtr(shape, elementIDs, basis, UniOrder,
3505  numModes, fields, NumHomoDir, HomoLen,
3506  homoStrips, HomoSIDs, HomoZIDs, HomoYIDs);
3507  fielddef.push_back(fdef);
3508  }
3509  }
3510 }
3511 
3512 //
3513 // Virtual functions
3514 //
3515 std::vector<LibUtilities::FieldDefinitionsSharedPtr> ExpList::
3517 {
3518  std::vector<LibUtilities::FieldDefinitionsSharedPtr> returnval;
3519  v_GetFieldDefinitions(returnval);
3520  return returnval;
3521 }
3522 
3524  std::vector<LibUtilities::FieldDefinitionsSharedPtr> &fielddef)
3525 {
3526  GeneralGetFieldDefinitions(fielddef);
3527 }
3528 
3529 // Append the element data listed in elements
3530 // fielddef->m_ElementIDs onto fielddata
3533  std::vector<NekDouble> &fielddata)
3534 {
3535  v_AppendFieldData(fielddef, fielddata, m_coeffs);
3536 }
3537 
3540  std::vector<NekDouble> &fielddata, Array<OneD, NekDouble> &coeffs)
3541 {
3542  int i;
3543  // Determine mapping from element ids to location in
3544  // expansion list
3545  // Determine mapping from element ids to location in
3546  // expansion list
3547  map<int, int> ElmtID_to_ExpID;
3548  for (i = 0; i < (*m_exp).size(); ++i)
3549  {
3550  ElmtID_to_ExpID[(*m_exp)[i]->GetGeom()->GetGlobalID()] = i;
3551  }
3552 
3553  for (i = 0; i < fielddef->m_elementIDs.size(); ++i)
3554  {
3555  int eid = ElmtID_to_ExpID[fielddef->m_elementIDs[i]];
3556  int datalen = (*m_exp)[eid]->GetNcoeffs();
3557  fielddata.insert(fielddata.end(), &coeffs[m_coeff_offset[eid]],
3558  &coeffs[m_coeff_offset[eid]] + datalen);
3559  }
3560 }
3561 
3562 /// Extract the data in fielddata into the coeffs
3565  std::vector<NekDouble> &fielddata, std::string &field,
3566  Array<OneD, NekDouble> &coeffs, std::unordered_map<int, int> zIdToPlane)
3567 {
3568  v_ExtractDataToCoeffs(fielddef, fielddata, field, coeffs, zIdToPlane);
3569 }
3570 
3572  const std::shared_ptr<ExpList> &fromExpList,
3573  const Array<OneD, const NekDouble> &fromCoeffs,
3574  Array<OneD, NekDouble> &toCoeffs)
3575 {
3576  v_ExtractCoeffsToCoeffs(fromExpList, fromCoeffs, toCoeffs);
3577 }
3578 
3579 /**
3580  * @brief Extract data from raw field data into expansion list.
3581  *
3582  * @param fielddef Field definitions.
3583  * @param fielddata Data for associated field.
3584  * @param field Field variable name.
3585  * @param coeffs Resulting coefficient array.
3586  */
3589  std::vector<NekDouble> &fielddata, std::string &field,
3590  Array<OneD, NekDouble> &coeffs, std::unordered_map<int, int> zIdToPlane)
3591 {
3592  boost::ignore_unused(zIdToPlane);
3593  int i, expId;
3594  int offset = 0;
3595  int modes_offset = 0;
3596  int datalen = fielddata.size() / fielddef->m_fields.size();
3597 
3598  // Find data location according to field definition
3599  for (i = 0; i < fielddef->m_fields.size(); ++i)
3600  {
3601  if (fielddef->m_fields[i] == field)
3602  {
3603  break;
3604  }
3605  offset += datalen;
3606  }
3607 
3608  ASSERTL0(i != fielddef->m_fields.size(),
3609  "Field (" + field + ") not found in file.");
3610 
3611  if (m_elmtToExpId.size() == 0)
3612  {
3613  // Loop in reverse order so that in case where using a
3614  // Homogeneous expansion it sets geometry ids to first part of
3615  // m_exp list. Otherwise will set to second (complex) expansion
3616  for (i = (*m_exp).size() - 1; i >= 0; --i)
3617  {
3618  m_elmtToExpId[(*m_exp)[i]->GetGeom()->GetGlobalID()] = i;
3619  }
3620  }
3621 
3622  for (i = 0; i < fielddef->m_elementIDs.size(); ++i)
3623  {
3624  // Reset modes_offset in the case where all expansions of
3625  // the same order.
3626  if (fielddef->m_uniOrder == true)
3627  {
3628  modes_offset = 0;
3629  }
3630 
3632  fielddef->m_shapeType, fielddef->m_numModes, modes_offset);
3633 
3634  const int elmtId = fielddef->m_elementIDs[i];
3635  auto eIt = m_elmtToExpId.find(elmtId);
3636 
3637  if (eIt == m_elmtToExpId.end())
3638  {
3639  offset += datalen;
3640  modes_offset += (*m_exp)[0]->GetNumBases();
3641  continue;
3642  }
3643 
3644  expId = eIt->second;
3645 
3646  bool sameBasis = true;
3647  for (int j = 0; j < fielddef->m_basis.size(); ++j)
3648  {
3649  if (fielddef->m_basis[j] != (*m_exp)[expId]->GetBasisType(j))
3650  {
3651  sameBasis = false;
3652  break;
3653  }
3654  }
3655 
3656  if (datalen == (*m_exp)[expId]->GetNcoeffs() && sameBasis)
3657  {
3658  Vmath::Vcopy(datalen, &fielddata[offset], 1,
3659  &coeffs[m_coeff_offset[expId]], 1);
3660  }
3661  else
3662  {
3663  (*m_exp)[expId]->ExtractDataToCoeffs(
3664  &fielddata[offset], fielddef->m_numModes, modes_offset,
3665  &coeffs[m_coeff_offset[expId]], fielddef->m_basis);
3666  }
3667 
3668  offset += datalen;
3669  modes_offset += (*m_exp)[0]->GetNumBases();
3670  }
3671 
3672  return;
3673 }
3674 
3676  const std::shared_ptr<ExpList> &fromExpList,
3677  const Array<OneD, const NekDouble> &fromCoeffs,
3678  Array<OneD, NekDouble> &toCoeffs)
3679 {
3680  int i;
3681  int offset = 0;
3682 
3683  for (i = 0; i < (*m_exp).size(); ++i)
3684  {
3685  std::vector<unsigned int> nummodes;
3686  vector<LibUtilities::BasisType> basisTypes;
3687  for (int j = 0; j < fromExpList->GetExp(i)->GetNumBases(); ++j)
3688  {
3689  nummodes.push_back(fromExpList->GetExp(i)->GetBasisNumModes(j));
3690  basisTypes.push_back(fromExpList->GetExp(i)->GetBasisType(j));
3691  }
3692 
3693  (*m_exp)[i]->ExtractDataToCoeffs(&fromCoeffs[offset], nummodes, 0,
3694  &toCoeffs[m_coeff_offset[i]],
3695  basisTypes);
3696 
3697  offset += fromExpList->GetExp(i)->GetNcoeffs();
3698  }
3699 }
3700 
3701 /**
3702  * Get the weight value on boundaries
3703  */
3705  Array<OneD, NekDouble> &weightJump)
3706 {
3707  size_t nTracePts = weightAver.size();
3708  // average for interior traces
3709  for (int i = 0; i < nTracePts; ++i)
3710  {
3711  weightAver[i] = 0.5;
3712  weightJump[i] = 1.0;
3713  }
3714  FillBwdWithBwdWeight(weightAver, weightJump);
3715 }
3716 
3718  const Array<OneD, const NekDouble> &CircCentre,
3719  Array<OneD, Array<OneD, NekDouble>> &outarray)
3720 {
3721  int npts;
3722 
3723  int MFdim = 3;
3724  int nq = outarray[0].size() / MFdim;
3725 
3726  // Assume whole array is of same coordinate dimension
3727  int coordim = (*m_exp)[0]->GetGeom()->GetCoordim();
3728 
3729  Array<OneD, Array<OneD, NekDouble>> MFloc(MFdim * coordim);
3730  // Process each expansion.
3731  for (int i = 0; i < m_exp->size(); ++i)
3732  {
3733  npts = (*m_exp)[i]->GetTotPoints();
3734 
3735  for (int j = 0; j < MFdim * coordim; ++j)
3736  {
3737  MFloc[j] = Array<OneD, NekDouble>(npts, 0.0);
3738  }
3739 
3740  // MF from LOCALREGIONS
3741  (*m_exp)[i]->GetMetricInfo()->GetMovingFrames(
3742  (*m_exp)[i]->GetPointsKeys(), MMFdir, CircCentre, MFloc);
3743 
3744  // Get the physical data offset for this expansion.
3745  for (int j = 0; j < MFdim; ++j)
3746  {
3747  for (int k = 0; k < coordim; ++k)
3748  {
3749  Vmath::Vcopy(npts, &MFloc[j * coordim + k][0], 1,
3750  &outarray[j][k * nq + m_phys_offset[i]], 1);
3751  }
3752  }
3753  }
3754 }
3755 
3756 /**
3757  * @brief Generate vector v such that v[i] = scalar1 if i is in the
3758  * element < ElementID. Otherwise, v[i] = scalar2.
3759  *
3760  */
3761 void ExpList::GenerateElementVector(const int ElementID,
3762  const NekDouble scalar1,
3763  const NekDouble scalar2,
3764  Array<OneD, NekDouble> &outarray)
3765 {
3766  int npoints_e;
3767  NekDouble coeff;
3768 
3769  Array<OneD, NekDouble> outarray_e;
3770 
3771  for (int i = 0; i < (*m_exp).size(); ++i)
3772  {
3773  npoints_e = (*m_exp)[i]->GetTotPoints();
3774 
3775  if (i <= ElementID)
3776  {
3777  coeff = scalar1;
3778  }
3779  else
3780  {
3781  coeff = scalar2;
3782  }
3783 
3784  outarray_e = Array<OneD, NekDouble>(npoints_e, coeff);
3785  Vmath::Vcopy(npoints_e, &outarray_e[0], 1, &outarray[m_phys_offset[i]],
3786  1);
3787  }
3788 }
3789 
3792 {
3794  "This method is not defined or valid for this class type");
3796  return result;
3797 }
3798 
3799 std::shared_ptr<ExpList> &ExpList::v_UpdateBndCondExpansion(int i)
3800 {
3801  boost::ignore_unused(i);
3803  "This method is not defined or valid for this class type");
3804  static std::shared_ptr<ExpList> result;
3805  return result;
3806 }
3807 
3808 /**
3809  * Upwind the left and right states given by the Arrays Fwd and Bwd
3810  * using the vector quantity Vec and ouput the upwinded value in the
3811  * array upwind.
3812  *
3813  * @param Vec Velocity field.
3814  * @param Fwd Left state.
3815  * @param Bwd Right state.
3816  * @param Upwind Output vector.
3817  */
3819  const Array<OneD, const NekDouble> &Fwd,
3820  const Array<OneD, const NekDouble> &Bwd,
3821  Array<OneD, NekDouble> &Upwind)
3822 {
3823  switch (m_expType)
3824  {
3825  case e1D:
3826  {
3827  int i, j, k, e_npoints, offset;
3828  Array<OneD, NekDouble> normals;
3829  NekDouble Vn;
3830 
3831  // Assume whole array is of same coordimate dimension
3832  int coordim = GetCoordim(0);
3833 
3834  ASSERTL1(Vec.size() >= coordim,
3835  "Input vector does not have sufficient dimensions to "
3836  "match coordim");
3837 
3838  // Process each expansion
3839  for (i = 0; i < m_exp->size(); ++i)
3840  {
3841  // Get the number of points in the expansion and the normals.
3842  e_npoints = (*m_exp)[i]->GetNumPoints(0);
3843  normals = (*m_exp)[i]->GetPhysNormals();
3844 
3845  // Get the physical data offset of the expansion in m_phys.
3846  offset = m_phys_offset[i];
3847 
3848  // Compute each data point.
3849  for (j = 0; j < e_npoints; ++j)
3850  {
3851  // Calculate normal velocity.
3852  Vn = 0.0;
3853  for (k = 0; k < coordim; ++k)
3854  {
3855  Vn += Vec[k][offset + j] * normals[k * e_npoints + j];
3856  }
3857 
3858  // Upwind based on direction of normal velocity.
3859  if (Vn > 0.0)
3860  {
3861  Upwind[offset + j] = Fwd[offset + j];
3862  }
3863  else
3864  {
3865  Upwind[offset + j] = Bwd[offset + j];
3866  }
3867  }
3868  }
3869  }
3870  break;
3871  default:
3873  "This method is not defined or valid for this class type");
3874  break;
3875  }
3876 }
3877 
3878 /**
3879  * One-dimensional upwind.
3880  * \see ExpList::Upwind(
3881  * const Array<OneD, const Array<OneD, NekDouble> >,
3882  * const Array<OneD, const NekDouble>,
3883  * const Array<OneD, const NekDouble>,
3884  * Array<OneD, NekDouble>, int)
3885  *
3886  * @param Vn Velocity field.
3887  * @param Fwd Left state.
3888  * @param Bwd Right state.
3889  * @param Upwind Output vector.
3890  */
3892  const Array<OneD, const NekDouble> &Fwd,
3893  const Array<OneD, const NekDouble> &Bwd,
3894  Array<OneD, NekDouble> &Upwind)
3895 {
3896  ASSERTL1(Vn.size() >= m_npoints, "Vn is not of sufficient length");
3897  ASSERTL1(Fwd.size() >= m_npoints, "Fwd is not of sufficient length");
3898  ASSERTL1(Bwd.size() >= m_npoints, "Bwd is not of sufficient length");
3899  ASSERTL1(Upwind.size() >= m_npoints, "Upwind is not of sufficient length");
3900 
3901  // Process each point in the expansion.
3902  for (int j = 0; j < m_npoints; ++j)
3903  {
3904  // Upwind based on one-dimensional velocity.
3905  if (Vn[j] > 0.0)
3906  {
3907  Upwind[j] = Fwd[j];
3908  }
3909  else
3910  {
3911  Upwind[j] = Bwd[j];
3912  }
3913  }
3914 }
3915 
3916 std::shared_ptr<ExpList> &ExpList::v_GetTrace()
3917 {
3919  "This method is not defined or valid for this class type");
3920  static std::shared_ptr<ExpList> returnVal;
3921  return returnVal;
3922 }
3923 
3924 std::shared_ptr<AssemblyMapDG> &ExpList::v_GetTraceMap()
3925 {
3927  "This method is not defined or valid for this class type");
3928  static std::shared_ptr<AssemblyMapDG> result;
3929  return result;
3930 }
3931 
3933 {
3934  return GetTraceMap()->GetBndCondIDToGlobalTraceID();
3935 }
3936 
3938 {
3940  "This method is not defined or valid for this class type");
3941  static std::vector<bool> result;
3942  return result;
3943 }
3944 
3945 /**
3946  * @brief Helper function to re-align face to a given orientation.
3947  */
3948 void AlignFace(const StdRegions::Orientation orient, const int nquad1,
3949  const int nquad2, const Array<OneD, const NekDouble> &in,
3951 {
3952  // Copy transpose.
3953  if (orient == StdRegions::eDir1FwdDir2_Dir2FwdDir1 ||
3957  {
3958  for (int i = 0; i < nquad2; ++i)
3959  {
3960  for (int j = 0; j < nquad1; ++j)
3961  {
3962  out[i * nquad1 + j] = in[j * nquad2 + i];
3963  }
3964  }
3965  }
3966  else
3967  {
3968  for (int i = 0; i < nquad2; ++i)
3969  {
3970  for (int j = 0; j < nquad1; ++j)
3971  {
3972  out[i * nquad1 + j] = in[i * nquad1 + j];
3973  }
3974  }
3975  }
3976 
3977  if (orient == StdRegions::eDir1BwdDir1_Dir2FwdDir2 ||
3981  {
3982  // Reverse x direction
3983  for (int i = 0; i < nquad2; ++i)
3984  {
3985  for (int j = 0; j < nquad1 / 2; ++j)
3986  {
3987  swap(out[i * nquad1 + j], out[i * nquad1 + nquad1 - j - 1]);
3988  }
3989  }
3990  }
3991 
3992  if (orient == StdRegions::eDir1FwdDir1_Dir2BwdDir2 ||
3996  {
3997  // Reverse y direction
3998  for (int j = 0; j < nquad1; ++j)
3999  {
4000  for (int i = 0; i < nquad2 / 2; ++i)
4001  {
4002  swap(out[i * nquad1 + j], out[(nquad2 - i - 1) * nquad1 + j]);
4003  }
4004  }
4005  }
4006 }
4007 
4008 /**
4009  * For each local element, copy the normals stored in the element list
4010  * into the array \a normals.
4011  * @param normals Multidimensional array in which to copy normals
4012  * to. Must have dimension equal to or larger than
4013  * the spatial dimension of the elements.
4014  */
4016 {
4017  int i, j, k, e_npoints, offset;
4019 
4020  // Assume whole array is of same coordinate dimension
4021  int coordim = GetCoordim(0);
4022 
4023  ASSERTL1(normals.size() >= coordim,
4024  "Output vector does not have sufficient dimensions to "
4025  "match coordim");
4026 
4027  switch (m_expType)
4028  {
4029  case e0D:
4030  {
4031  // Process each expansion.
4032  for (i = 0; i < m_exp->size(); ++i)
4033  {
4034  LocalRegions::ExpansionSharedPtr loc_exp = (*m_exp)[i];
4035 
4037  loc_exp->GetLeftAdjacentElementExp();
4038 
4039  // Get the number of points and normals for this expansion.
4040  e_npoints = 1;
4041  locnormals = loc_elmt->GetTraceNormal(
4042  loc_exp->GetLeftAdjacentElementTrace());
4043 
4044  // Get the physical data offset for this expansion.
4045  offset = m_phys_offset[i];
4046 
4047  // Process each point in the expansion.
4048  for (j = 0; j < e_npoints; ++j)
4049  {
4050  // Process each spatial dimension and copy the
4051  // values into the output array.
4052  for (k = 0; k < coordim; ++k)
4053  {
4054  normals[k][offset] = locnormals[k][0];
4055  }
4056  }
4057  }
4058  }
4059  break;
4060  case e1D:
4061  {
4065 
4066  for (i = 0; i < m_exp->size(); ++i)
4067  {
4068  LocalRegions::ExpansionSharedPtr loc_exp = (*m_exp)[i];
4069 
4071  loc_exp->GetLeftAdjacentElementExp();
4072 
4073  int edgeNumber = loc_exp->GetLeftAdjacentElementTrace();
4074 
4075  // Get the number of points and normals for this expansion.
4076  e_npoints = (*m_exp)[i]->GetNumPoints(0);
4077 
4078  locnormals = loc_elmt->GetTraceNormal(edgeNumber);
4079  int e_nmodes = loc_exp->GetBasis(0)->GetNumModes();
4080  int loc_nmodes = loc_elmt->GetBasis(0)->GetNumModes();
4081 
4082  if (e_nmodes != loc_nmodes)
4083  {
4084  if (loc_exp->GetRightAdjacentElementTrace() >= 0)
4085  {
4087  loc_exp->GetRightAdjacentElementExp();
4088 
4089  int EdgeNumber =
4090  loc_exp->GetRightAdjacentElementTrace();
4091 
4092  // Serial case: right element is connected so we can
4093  // just grab that normal.
4094  locnormals = loc_elmt->GetTraceNormal(EdgeNumber);
4095 
4096  offset = m_phys_offset[i];
4097 
4098  // Process each point in the expansion.
4099  for (j = 0; j < e_npoints; ++j)
4100  {
4101  // Process each spatial dimension and
4102  // copy the values into the output
4103  // array.
4104  for (k = 0; k < coordim; ++k)
4105  {
4106  normals[k][offset + j] = -locnormals[k][j];
4107  }
4108  }
4109  }
4110  else
4111  {
4112  // Parallel case: need to interpolate normal.
4113  Array<OneD, Array<OneD, NekDouble>> normal(coordim);
4114 
4115  for (int p = 0; p < coordim; ++p)
4116  {
4117  normal[p] = Array<OneD, NekDouble>(e_npoints, 0.0);
4118  LibUtilities::PointsKey to_key =
4119  loc_exp->GetBasis(0)->GetPointsKey();
4120  LibUtilities::PointsKey from_key =
4121  loc_elmt->GetBasis(0)->GetPointsKey();
4122  LibUtilities::Interp1D(from_key, locnormals[p],
4123  to_key, normal[p]);
4124  }
4125 
4126  offset = m_phys_offset[i];
4127 
4128  // Process each point in the expansion.
4129  for (j = 0; j < e_npoints; ++j)
4130  {
4131  // Process each spatial dimension and copy the
4132  // values into the output array.
4133  for (k = 0; k < coordim; ++k)
4134  {
4135  normals[k][offset + j] = normal[k][j];
4136  }
4137  }
4138  }
4139  }
4140  else
4141  {
4142  // Get the physical data offset for this expansion.
4143  offset = m_phys_offset[i];
4144 
4145  // Process each point in the expansion.
4146  for (j = 0; j < e_npoints; ++j)
4147  {
4148  // Process each spatial dimension and copy the values
4149  // into the output array.
4150  for (k = 0; k < coordim; ++k)
4151  {
4152  normals[k][offset + j] = locnormals[k][j];
4153  }
4154  }
4155  }
4156  }
4157  }
4158  break;
4159  case e2D:
4160  {
4162 
4163  // Process each expansion.
4164  for (i = 0; i < m_exp->size(); ++i)
4165  {
4166  LocalRegions::ExpansionSharedPtr traceExp = (*m_exp)[i];
4168  traceExp->GetLeftAdjacentElementExp();
4169 
4170  // Get the number of points and normals for this expansion.
4171  int faceNum = traceExp->GetLeftAdjacentElementTrace();
4172  int offset = m_phys_offset[i];
4173 
4174  const Array<OneD, const Array<OneD, NekDouble>> &locNormals =
4175  exp3D->GetTraceNormal(faceNum);
4176 
4177  // Project normals from 3D element onto the same
4178  // orientation as the trace expansion.
4179  StdRegions::Orientation orient = exp3D->GetTraceOrient(faceNum);
4180 
4181  int fromid0, fromid1;
4182 
4184  {
4185  fromid0 = 0;
4186  fromid1 = 1;
4187  }
4188  else
4189  {
4190  fromid0 = 1;
4191  fromid1 = 0;
4192  }
4193 
4194  LibUtilities::BasisKey faceBasis0 =
4195  exp3D->GetTraceBasisKey(faceNum, fromid0);
4196  LibUtilities::BasisKey faceBasis1 =
4197  exp3D->GetTraceBasisKey(faceNum, fromid1);
4198  LibUtilities::BasisKey traceBasis0 =
4199  traceExp->GetBasis(0)->GetBasisKey();
4200  LibUtilities::BasisKey traceBasis1 =
4201  traceExp->GetBasis(1)->GetBasisKey();
4202 
4203  const int faceNq0 = faceBasis0.GetNumPoints();
4204  const int faceNq1 = faceBasis1.GetNumPoints();
4205 
4206  Array<OneD, int> faceids;
4207  exp3D->ReOrientTracePhysMap(orient, faceids, faceNq0, faceNq1);
4208 
4209  Array<OneD, NekDouble> traceNormals(faceNq0 * faceNq1);
4210 
4211  for (j = 0; j < coordim; ++j)
4212  {
4213  Vmath::Scatr(faceNq0 * faceNq1, locNormals[j], faceids,
4214  traceNormals);
4215 
4217  faceBasis0.GetPointsKey(), faceBasis1.GetPointsKey(),
4218  traceNormals, traceBasis0.GetPointsKey(),
4219  traceBasis1.GetPointsKey(), tmp = normals[j] + offset);
4220  }
4221  }
4222  }
4223  break;
4224  default:
4225  {
4227  "This method is not defined or valid for this class type");
4228  }
4229  }
4230 }
4231 
4233  Array<OneD, NekDouble> &lengthsBwd)
4234 {
4235  int e_npoints;
4236 
4237  Array<OneD, NekDouble> locLeng;
4240  Array<OneD, int> LRbndnumbs(2);
4242  lengLR[0] = lengthsFwd;
4243  lengLR[1] = lengthsBwd;
4247  int e_npoints0 = -1;
4248  if (m_expType == e1D)
4249  {
4250  for (int i = 0; i < m_exp->size(); ++i)
4251  {
4252  loc_exp = (*m_exp)[i];
4253  int offset = m_phys_offset[i];
4254 
4255  int e_nmodes = loc_exp->GetBasis(0)->GetNumModes();
4256  e_npoints = (*m_exp)[i]->GetNumPoints(0);
4257  if (e_npoints0 < e_npoints)
4258  {
4259  for (int nlr = 0; nlr < 2; nlr++)
4260  {
4261  lengintp[nlr] = Array<OneD, NekDouble>(e_npoints, 0.0);
4262  }
4263  e_npoints0 = e_npoints;
4264  }
4265 
4266  LRelmts[0] = loc_exp->GetLeftAdjacentElementExp();
4267  LRelmts[1] = loc_exp->GetRightAdjacentElementExp();
4268 
4269  LRbndnumbs[0] = loc_exp->GetLeftAdjacentElementTrace();
4270  LRbndnumbs[1] = loc_exp->GetRightAdjacentElementTrace();
4271  for (int nlr = 0; nlr < 2; ++nlr)
4272  {
4273  Vmath::Zero(e_npoints0, lengintp[nlr], 1);
4274  lengAdd[nlr] = lengintp[nlr];
4275  int bndNumber = LRbndnumbs[nlr];
4276  loc_elmt = LRelmts[nlr];
4277  if (bndNumber >= 0)
4278  {
4279  locLeng = loc_elmt->GetElmtBndNormDirElmtLen(bndNumber);
4280  lengAdd[nlr] = locLeng;
4281 
4282  int loc_nmodes = loc_elmt->GetBasis(0)->GetNumModes();
4283  if (e_nmodes != loc_nmodes)
4284  {
4285  // Parallel case: need to interpolate.
4286  LibUtilities::PointsKey to_key =
4287  loc_exp->GetBasis(0)->GetPointsKey();
4288  LibUtilities::PointsKey from_key =
4289  loc_elmt->GetBasis(0)->GetPointsKey();
4290  LibUtilities::Interp1D(from_key, locLeng, to_key,
4291  lengintp[nlr]);
4292  lengAdd[nlr] = lengintp[nlr];
4293  }
4294  }
4295 
4296  for (int j = 0; j < e_npoints; ++j)
4297  {
4298  lengLR[nlr][offset + j] = lengAdd[nlr][j];
4299  }
4300  }
4301  }
4302  }
4303  else if (m_expType == e2D)
4304  {
4305  for (int i = 0; i < m_exp->size(); ++i)
4306  {
4307  loc_exp = (*m_exp)[i];
4308  int offset = m_phys_offset[i];
4309 
4310  LibUtilities::BasisKey traceBasis0 =
4311  loc_exp->GetBasis(0)->GetBasisKey();
4312  LibUtilities::BasisKey traceBasis1 =
4313  loc_exp->GetBasis(1)->GetBasisKey();
4314  const int TraceNq0 = traceBasis0.GetNumPoints();
4315  const int TraceNq1 = traceBasis1.GetNumPoints();
4316  e_npoints = TraceNq0 * TraceNq1;
4317  if (e_npoints0 < e_npoints)
4318  {
4319  for (int nlr = 0; nlr < 2; nlr++)
4320  {
4321  lengintp[nlr] = Array<OneD, NekDouble>(e_npoints, 0.0);
4322  }
4323  e_npoints0 = e_npoints;
4324  }
4325 
4326  LRelmts[0] = loc_exp->GetLeftAdjacentElementExp();
4327  LRelmts[1] = loc_exp->GetRightAdjacentElementExp();
4328 
4329  LRbndnumbs[0] = loc_exp->GetLeftAdjacentElementTrace();
4330  LRbndnumbs[1] = loc_exp->GetRightAdjacentElementTrace();
4331  for (int nlr = 0; nlr < 2; ++nlr)
4332  {
4333  Vmath::Zero(e_npoints0, lengintp[nlr], 1);
4334  int bndNumber = LRbndnumbs[nlr];
4335  loc_elmt = LRelmts[nlr];
4336  if (bndNumber >= 0)
4337  {
4338  locLeng = loc_elmt->GetElmtBndNormDirElmtLen(bndNumber);
4339  // Project normals from 3D element onto the
4340  // same orientation as the trace expansion.
4341  StdRegions::Orientation orient =
4342  loc_elmt->GetTraceOrient(bndNumber);
4343 
4344  int fromid0, fromid1;
4346  {
4347  fromid0 = 0;
4348  fromid1 = 1;
4349  }
4350  else
4351  {
4352  fromid0 = 1;
4353  fromid1 = 0;
4354  }
4355 
4356  LibUtilities::BasisKey faceBasis0 =
4357  loc_elmt->GetTraceBasisKey(bndNumber, fromid0);
4358  LibUtilities::BasisKey faceBasis1 =
4359  loc_elmt->GetTraceBasisKey(bndNumber, fromid1);
4360  const int faceNq0 = faceBasis0.GetNumPoints();
4361  const int faceNq1 = faceBasis1.GetNumPoints();
4362  Array<OneD, NekDouble> alignedLeng(faceNq0 * faceNq1);
4363 
4364  AlignFace(orient, faceNq0, faceNq1, locLeng, alignedLeng);
4366  faceBasis0.GetPointsKey(), faceBasis1.GetPointsKey(),
4367  alignedLeng, traceBasis0.GetPointsKey(),
4368  traceBasis1.GetPointsKey(), lengintp[nlr]);
4369  }
4370 
4371  for (int j = 0; j < e_npoints; ++j)
4372  {
4373  lengLR[nlr][offset + j] = lengintp[nlr][j];
4374  }
4375  }
4376  }
4377  }
4378 }
4379 
4381  const Array<OneD, const NekDouble> &Fy,
4382  Array<OneD, NekDouble> &outarray)
4383 {
4384  boost::ignore_unused(Fx, Fy, outarray);
4386  "This method is not defined or valid for this class type");
4387 }
4388 
4390  Array<OneD, NekDouble> &outarray)
4391 {
4392  boost::ignore_unused(Fn, outarray);
4394  "This method is not defined or valid for this class type");
4395 }
4396 
4398  const Array<OneD, const NekDouble> &Bwd,
4399  Array<OneD, NekDouble> &outarray)
4400 {
4401  boost::ignore_unused(Fwd, Bwd, outarray);
4403  "This method is not defined or valid for this class type");
4404 }
4405 
4408 {
4409  boost::ignore_unused(Fwd, Bwd);
4411  "This method is not defined or valid for this class type");
4412 }
4413 
4416  Array<OneD, NekDouble> &Bwd, bool FillBnd,
4417  bool PutFwdInBwdOnBCs, bool DoExchange)
4418 {
4419  boost::ignore_unused(field, Fwd, Bwd, FillBnd, PutFwdInBwdOnBCs,
4420  DoExchange);
4422  "This method is not defined or valid for this class type");
4423 }
4424 
4427  bool PutFwdInBwdOnBCs)
4428 {
4429  boost::ignore_unused(Fwd, Bwd, PutFwdInBwdOnBCs);
4431  "This method is not defined or valid for this class type");
4432 }
4433 
4435  const Array<OneD, const NekDouble> &Bwd,
4436  Array<OneD, NekDouble> &field)
4437 {
4438  boost::ignore_unused(field, Fwd, Bwd);
4440  "v_AddTraceQuadPhysToField is not defined for this class type");
4441 }
4442 
4444  const Array<OneD, const NekDouble> &Fwd,
4446 {
4447  boost::ignore_unused(field, Fwd, Bwd);
4449  "v_AddTraceQuadPhysToOffDiag is not defined for this class");
4450 }
4451 
4453  const Array<OneD, const NekDouble> &Bwd,
4454  Array<OneD, NekDouble> &locTraceFwd,
4455  Array<OneD, NekDouble> &locTraceBwd)
4456 {
4457  boost::ignore_unused(Fwd, Bwd, locTraceFwd, locTraceBwd);
4459  "v_GetLocTraceFromTracePts is not defined for this class");
4460 }
4461 
4463 {
4465  "v_GetBndCondBwdWeight is not defined for this class type");
4466  static Array<OneD, NekDouble> tmp;
4467  return tmp;
4468 }
4469 
4470 void ExpList::v_SetBndCondBwdWeight(const int index, const NekDouble value)
4471 {
4472  boost::ignore_unused(index, value);
4474  "v_setBndCondBwdWeight is not defined for this class type");
4475 }
4476 
4477 const vector<bool> &ExpList::v_GetLeftAdjacentFaces(void) const
4478 {
4480  "This method is not defined or valid for this class type");
4481  static vector<bool> tmp;
4482  return tmp;
4483 }
4484 
4486 {
4487  boost::ignore_unused(outarray);
4489  "This method is not defined or valid for this class type");
4490 }
4491 
4493  Array<OneD, NekDouble> &outarray)
4494 {
4495  boost::ignore_unused(inarray, outarray);
4497  "This method is not defined or valid for this class type");
4498 }
4499 
4501  const Array<OneD, const NekDouble> &inarray,
4502  Array<OneD, NekDouble> &outarray)
4503 {
4504  boost::ignore_unused(inarray, outarray);
4506  "This method is not defined or valid for this class type");
4507 }
4508 
4510  const Array<OneD, const NekDouble> &inarray,
4511  Array<OneD, NekDouble> &outarray, const StdRegions::ConstFactorMap &factors,
4512  const StdRegions::VarCoeffMap &varcoeff,
4513  const MultiRegions::VarFactorsMap &varfactors,
4514  const Array<OneD, const NekDouble> &dirForcing, const bool PhysSpaceForcing)
4515 {
4516  boost::ignore_unused(inarray, outarray, factors, varcoeff, varfactors,
4517  dirForcing, PhysSpaceForcing);
4518  NEKERROR(ErrorUtil::efatal, "HelmSolve not implemented.");
4519  return NullGlobalLinSysKey;
4520 }
4521 
4523  const Array<OneD, Array<OneD, NekDouble>> &velocity,
4524  const Array<OneD, const NekDouble> &inarray,
4525  Array<OneD, NekDouble> &outarray, const NekDouble lambda,
4526  const Array<OneD, const NekDouble> &dirForcing)
4527 {
4528  boost::ignore_unused(velocity, inarray, outarray, lambda, dirForcing);
4530  "LinearAdvectionDiffusionReactionSolve not implemented.");
4531  return NullGlobalLinSysKey;
4532 }
4533 
4535  const Array<OneD, Array<OneD, NekDouble>> &velocity,
4536  const Array<OneD, const NekDouble> &inarray,
4537  Array<OneD, NekDouble> &outarray, const NekDouble lambda,
4538  const Array<OneD, const NekDouble> &dirForcing)
4539 {
4540  boost::ignore_unused(velocity, inarray, outarray, lambda, dirForcing);
4542  "This method is not defined or valid for this class type");
4543 }
4544 
4546  const Array<OneD, const NekDouble> &inarray,
4547  Array<OneD, NekDouble> &outarray,
4548  bool Shuff, bool UnShuff)
4549 {
4550  boost::ignore_unused(npts, inarray, outarray, Shuff, UnShuff);
4552  "This method is not defined or valid for this class type");
4553 }
4554 
4556  const Array<OneD, const NekDouble> &inarray,
4557  Array<OneD, NekDouble> &outarray,
4558  bool Shuff, bool UnShuff)
4559 {
4560  boost::ignore_unused(npts, inarray, outarray, Shuff, UnShuff);
4562  "This method is not defined or valid for this class type");
4563 }
4564 
4565 void ExpList::v_DealiasedProd(const int npts,
4566  const Array<OneD, NekDouble> &inarray1,
4567  const Array<OneD, NekDouble> &inarray2,
4568  Array<OneD, NekDouble> &outarray)
4569 {
4570  boost::ignore_unused(npts, inarray1, inarray2, outarray);
4572  "This method is not defined or valid for this class type");
4573 }
4574 
4576  const int npts, const Array<OneD, Array<OneD, NekDouble>> &inarray1,
4577  const Array<OneD, Array<OneD, NekDouble>> &inarray2,
4578  Array<OneD, Array<OneD, NekDouble>> &outarray)
4579 {
4580  boost::ignore_unused(npts, inarray1, inarray2, outarray);
4582  "This method is not defined or valid for this class type");
4583 }
4584 
4586  const Array<OneD, NekDouble> &TotField, int BndID)
4587 {
4588  boost::ignore_unused(BndVals, TotField, BndID);
4590  "This method is not defined or valid for this class type");
4591 }
4592 
4595  Array<OneD, NekDouble> &outarray,
4596  int BndID)
4597 {
4598  boost::ignore_unused(V1, V2, outarray, BndID);
4600  "This method is not defined or valid for this class type");
4601 }
4602 
4605 {
4607  switch (GetCoordim(0))
4608  {
4609  case 1:
4610  {
4611  for (int i = 0; i < GetExpSize(); ++i)
4612  {
4613  (*m_exp)[i]->NormVectorIProductWRTBase(
4614  V[0] + GetPhys_Offset(i),
4615  tmp = outarray + GetCoeff_Offset(i));
4616  }
4617  }
4618  break;
4619  case 2:
4620  {
4621  for (int i = 0; i < GetExpSize(); ++i)
4622  {
4623  (*m_exp)[i]->NormVectorIProductWRTBase(
4624  V[0] + GetPhys_Offset(i), V[1] + GetPhys_Offset(i),
4625  tmp = outarray + GetCoeff_Offset(i));
4626  }
4627  }
4628  break;
4629  case 3:
4630  {
4631  for (int i = 0; i < GetExpSize(); ++i)
4632  {
4633  (*m_exp)[i]->NormVectorIProductWRTBase(
4634  V[0] + GetPhys_Offset(i), V[1] + GetPhys_Offset(i),
4635  V[2] + GetPhys_Offset(i),
4636  tmp = outarray + GetCoeff_Offset(i));
4637  }
4638  }
4639  break;
4640  default:
4641  NEKERROR(ErrorUtil::efatal, "Dimension not supported");
4642  break;
4643  }
4644 }
4645 
4647 {
4648  boost::ignore_unused(outarray);
4650  "This method is not defined or valid for this class type");
4651 }
4652 
4653 /**
4654  */
4656 {
4657  boost::ignore_unused(coeffs);
4659  "This method is not defined or valid for this class type");
4660 }
4661 
4662 /**
4663  */
4665  const Array<OneD, NekDouble> coeffs)
4666 {
4667  boost::ignore_unused(nreg, coeffs);
4669  "This method is not defined or valid for this class type");
4670 }
4671 
4672 void ExpList::v_LocalToGlobal(bool useComm)
4673 {
4674  boost::ignore_unused(useComm);
4676  "This method is not defined or valid for this class type");
4677 }
4678 
4680  Array<OneD, NekDouble> &outarray, bool useComm)
4681 {
4682  boost::ignore_unused(inarray, outarray, useComm);
4684  "This method is not defined or valid for this class type");
4685 }
4686 
4688 {
4690  "This method is not defined or valid for this class type");
4691 }
4692 
4694  Array<OneD, NekDouble> &outarray)
4695 {
4696  boost::ignore_unused(inarray, outarray);
4698  "This method is not defined or valid for this class type");
4699 }
4700 
4702  Array<OneD, NekDouble> &outarray)
4703 {
4704  v_FwdTransLocalElmt(inarray, outarray);
4705 }
4706 
4707 /**
4708  * The operation is evaluated locally for every element by the function
4709  * StdRegions#StdExpansion#IProductWRTBase.
4710  *
4711  * @param inarray An array of size \f$Q_{\mathrm{tot}}\f$
4712  * containing the values of the function
4713  * \f$f(\boldsymbol{x})\f$ at the quadrature
4714  * points \f$\boldsymbol{x}_i\f$.
4715  * @param outarray An array of size \f$N_{\mathrm{eof}}\f$
4716  * used to store the result.
4717  */
4719  Array<OneD, NekDouble> &outarray)
4720 {
4721  // initialise if required
4723  {
4724  for (int i = 0; i < m_collections.size(); ++i)
4725  {
4727  }
4729  }
4730 
4732  for (int i = 0; i < m_collections.size(); ++i)
4733  {
4734 
4736  inarray + m_coll_phys_offset[i],
4737  tmp = outarray + m_coll_coeff_offset[i]);
4738  }
4739 }
4740 
4741 /**
4742  * The operation is evaluated locally by the elemental
4743  * function StdRegions#StdExpansion#GetCoords.
4744  *
4745  * @param coord_0 After calculation, the \f$x_1\f$ coordinate
4746  * will be stored in this array.
4747  * @param coord_1 After calculation, the \f$x_2\f$ coordinate
4748  * will be stored in this array.
4749  * @param coord_2 After calculation, the \f$x_3\f$ coordinate
4750  * will be stored in this array.
4751  */
4753  Array<OneD, NekDouble> &coord_1,
4754  Array<OneD, NekDouble> &coord_2)
4755 {
4756  if (GetNumElmts() == 0)
4757  {
4758  return;
4759  }
4760 
4761  int i;
4762  Array<OneD, NekDouble> e_coord_0;
4763  Array<OneD, NekDouble> e_coord_1;
4764  Array<OneD, NekDouble> e_coord_2;
4765 
4766  switch (GetExp(0)->GetCoordim())
4767  {
4768  case 1:
4769  for (i = 0; i < (*m_exp).size(); ++i)
4770  {
4771  e_coord_0 = coord_0 + m_phys_offset[i];
4772  (*m_exp)[i]->GetCoords(e_coord_0);
4773  }
4774  break;
4775  case 2:
4776  ASSERTL0(coord_1.size() != 0, "output coord_1 is not defined");
4777 
4778  for (i = 0; i < (*m_exp).size(); ++i)
4779  {
4780  e_coord_0 = coord_0 + m_phys_offset[i];
4781  e_coord_1 = coord_1 + m_phys_offset[i];
4782  (*m_exp)[i]->GetCoords(e_coord_0, e_coord_1);
4783  }
4784  break;
4785  case 3:
4786  ASSERTL0(coord_1.size() != 0, "output coord_1 is not defined");
4787  ASSERTL0(coord_2.size() != 0, "output coord_2 is not defined");
4788 
4789  for (i = 0; i < (*m_exp).size(); ++i)
4790  {
4791  e_coord_0 = coord_0 + m_phys_offset[i];
4792  e_coord_1 = coord_1 + m_phys_offset[i];
4793  e_coord_2 = coord_2 + m_phys_offset[i];
4794  (*m_exp)[i]->GetCoords(e_coord_0, e_coord_1, e_coord_2);
4795  }
4796  break;
4797  }
4798 }
4799 
4803 {
4804  (*m_exp)[eid]->GetCoords(xc0, xc1, xc2);
4805 }
4806 
4807 /**
4808  * @brief: Set up a normal along the trace elements between
4809  * two elements at elemental level
4810  *
4811  */
4813 {
4814  for (int i = 0; i < m_exp->size(); ++i)
4815  {
4816  for (int j = 0; j < (*m_exp)[i]->GetNtraces(); ++j)
4817  {
4818  (*m_exp)[i]->ComputeTraceNormal(j);
4819  }
4820  }
4821 }
4822 
4823 /**
4824  */
4825 void ExpList::v_GetBndElmtExpansion(int i, std::shared_ptr<ExpList> &result,
4826  const bool DeclareCoeffPhysArrays)
4827 {
4828  boost::ignore_unused(i, result, DeclareCoeffPhysArrays);
4830  "This method is not defined or valid for this class type");
4831 }
4832 
4833 /**
4834  */
4836  const Array<OneD, NekDouble> &element,
4837  Array<OneD, NekDouble> &boundary)
4838 {
4839  int n, cnt;
4840  Array<OneD, NekDouble> tmp1, tmp2;
4842 
4843  Array<OneD, int> ElmtID, EdgeID;
4844  GetBoundaryToElmtMap(ElmtID, EdgeID);
4845 
4846  // Initialise result
4847  boundary =
4849 
4850  // Skip other boundary regions
4851  for (cnt = n = 0; n < i; ++n)
4852  {
4853  cnt += GetBndCondExpansions()[n]->GetExpSize();
4854  }
4855 
4856  int offsetBnd;
4857  int offsetElmt = 0;
4858  for (n = 0; n < GetBndCondExpansions()[i]->GetExpSize(); ++n)
4859  {
4860  offsetBnd = GetBndCondExpansions()[i]->GetPhys_Offset(n);
4861 
4862  elmt = GetExp(ElmtID[cnt + n]);
4863  elmt->GetTracePhysVals(
4864  EdgeID[cnt + n], GetBndCondExpansions()[i]->GetExp(n),
4865  tmp1 = element + offsetElmt, tmp2 = boundary + offsetBnd);
4866 
4867  offsetElmt += elmt->GetTotPoints();
4868  }
4869 }
4870 
4871 /**
4872  */
4874  const Array<OneD, const NekDouble> &phys,
4875  Array<OneD, NekDouble> &bndElmt)
4876 {
4877  int n, cnt, nq;
4878 
4879  Array<OneD, int> ElmtID, EdgeID;
4880  GetBoundaryToElmtMap(ElmtID, EdgeID);
4881 
4882  // Skip other boundary regions
4883  for (cnt = n = 0; n < i; ++n)
4884  {
4885  cnt += GetBndCondExpansions()[n]->GetExpSize();
4886  }
4887 
4888  // Count number of points
4889  int npoints = 0;
4890  for (n = 0; n < GetBndCondExpansions()[i]->GetExpSize(); ++n)
4891  {
4892  npoints += GetExp(ElmtID[cnt + n])->GetTotPoints();
4893  }
4894 
4895  // Initialise result
4896  bndElmt = Array<OneD, NekDouble>(npoints, 0.0);
4897 
4898  // Extract data
4899  int offsetPhys;
4900  int offsetElmt = 0;
4901  for (n = 0; n < GetBndCondExpansions()[i]->GetExpSize(); ++n)
4902  {
4903  nq = GetExp(ElmtID[cnt + n])->GetTotPoints();
4904  offsetPhys = GetPhys_Offset(ElmtID[cnt + n]);
4905  Vmath::Vcopy(nq, &phys[offsetPhys], 1, &bndElmt[offsetElmt], 1);
4906  offsetElmt += nq;
4907  }
4908 }
4909 
4910 /**
4911  */
4913  const Array<OneD, const NekDouble> &phys,
4915 {
4916  int n, cnt;
4919 
4920  Array<OneD, int> ElmtID, EdgeID;
4921  GetBoundaryToElmtMap(ElmtID, EdgeID);
4922 
4923  // Initialise result
4924  bnd =
4926 
4927  // Skip other boundary regions
4928  for (cnt = n = 0; n < i; ++n)
4929  {
4930  cnt += GetBndCondExpansions()[n]->GetExpSize();
4931  }
4932 
4933  int offsetBnd;
4934  int offsetPhys;
4935  for (n = 0; n < GetBndCondExpansions()[i]->GetExpSize(); ++n)
4936  {
4937  offsetPhys = GetPhys_Offset(ElmtID[cnt + n]);
4938  offsetBnd = GetBndCondExpansions()[i]->GetPhys_Offset(n);
4939 
4940  elmt = GetExp(ElmtID[cnt + n]);
4941  elmt->GetTracePhysVals(EdgeID[cnt + n],
4942  GetBndCondExpansions()[i]->GetExp(n),
4943  phys + offsetPhys, tmp1 = bnd + offsetBnd);
4944  }
4945 }
4946 
4947 /**
4948  */
4950  Array<OneD, Array<OneD, NekDouble>> &normals)
4951 {
4952  int j, n, cnt, nq;
4953  int coordim = GetCoordim(0);
4956 
4957  Array<OneD, int> ElmtID, EdgeID;
4958  GetBoundaryToElmtMap(ElmtID, EdgeID);
4959 
4960  // Initialise result
4961  normals = Array<OneD, Array<OneD, NekDouble>>(coordim);
4962  for (j = 0; j < coordim; ++j)
4963  {
4964  normals[j] = Array<OneD, NekDouble>(
4965  GetBndCondExpansions()[i]->GetTotPoints(), 0.0);
4966  }
4967 
4968  // Skip other boundary regions
4969  for (cnt = n = 0; n < i; ++n)
4970  {
4971  cnt += GetBndCondExpansions()[n]->GetExpSize();
4972  }
4973 
4974  int offset;
4975  for (n = 0; n < GetBndCondExpansions()[i]->GetExpSize(); ++n)
4976  {
4977  offset = GetBndCondExpansions()[i]->GetPhys_Offset(n);
4978  nq = GetBndCondExpansions()[i]->GetExp(n)->GetTotPoints();
4979 
4980  elmt = GetExp(ElmtID[cnt + n]);
4981  const Array<OneD, const Array<OneD, NekDouble>> normalsElmt =
4982  elmt->GetTraceNormal(EdgeID[cnt + n]);
4983  // Copy to result
4984  for (j = 0; j < coordim; ++j)
4985  {
4986  Vmath::Vcopy(nq, normalsElmt[j], 1, tmp = normals[j] + offset, 1);
4987  }
4988  }
4989 }
4990 
4991 /**
4992  */
4994  Array<OneD, int> &EdgeID)
4995 {
4996  boost::ignore_unused(ElmtID, EdgeID);
4998  "This method is not defined or valid for this class type");
4999 }
5000 
5002  Array<OneD, NekDouble> &weightjmp)
5003 {
5004  boost::ignore_unused(weightave, weightjmp);
5005  NEKERROR(ErrorUtil::efatal, "v_FillBwdWithBwdWeight not defined");
5006 }
5007 
5010 {
5011  boost::ignore_unused(Fwd, Bwd);
5012  NEKERROR(ErrorUtil::efatal, "v_PeriodicBwdCopy not defined");
5013 }
5014 
5015 /**
5016  */
5019 {
5021  "This method is not defined or valid for this class type");
5023  return result;
5024 }
5025 
5026 /**
5027  */
5030 {
5032  "This method is not defined or valid for this class type");
5034  return result;
5035 }
5036 
5037 /**
5038  */
5040  const std::string varName,
5041  const NekDouble x2_in,
5042  const NekDouble x3_in)
5043 {
5044  boost::ignore_unused(time, varName, x2_in, x3_in);
5046  "This method is not defined or valid for this class type");
5047 }
5048 
5049 /**
5050  */
5051 map<int, RobinBCInfoSharedPtr> ExpList::v_GetRobinBCInfo(void)
5052 {
5054  "This method is not defined or valid for this class type");
5055  static map<int, RobinBCInfoSharedPtr> result;
5056  return result;
5057 }
5058 
5059 /**
5060  */
5062  PeriodicMap &periodicEdges,
5063  PeriodicMap &periodicFaces)
5064 {
5065  boost::ignore_unused(periodicVerts, periodicEdges, periodicFaces);
5067  "This method is not defined or valid for this class type");
5068 }
5069 
5072  unsigned int regionId, const std::string &variable)
5073 {
5074  auto collectionIter = collection.find(regionId);
5075  ASSERTL1(collectionIter != collection.end(),
5076  "Unable to locate collection " +
5077  boost::lexical_cast<string>(regionId));
5078 
5080  (*collectionIter).second;
5081  auto conditionMapIter = bndCondMap->find(variable);
5082  ASSERTL1(conditionMapIter != bndCondMap->end(),
5083  "Unable to locate condition map.");
5084 
5085  const SpatialDomains::BoundaryConditionShPtr boundaryCondition =
5086  (*conditionMapIter).second;
5087 
5088  return boundaryCondition;
5089 }
5090 
5092 {
5093  boost::ignore_unused(n);
5095  "This method is not defined or valid for this class type");
5096  return NullExpListSharedPtr;
5097 }
5098 
5099 /**
5100  * @brief Construct collections of elements containing a single element
5101  * type and polynomial order from the list of expansions.
5102  */
5104 {
5106  vector<std::pair<LocalRegions::ExpansionSharedPtr, int>>>
5107  collections;
5108 
5109  // Set up initialisation flags
5111  std::vector<bool>(Collections::SIZE_OperatorType, true);
5112 
5113  // Figure out optimisation parameters if provided in
5114  // session file or default given
5116  m_session, (*m_exp)[0]->GetShapeDimension(), ImpType);
5117  // ImpType = colOpt.GetDefaultImplementationType();
5118 
5119  // turn on autotuning if explicitly specified in xml file
5120  // or command line option is set but only do optimisation
5121  // for volumetric elements (not boundary condition)
5122  bool autotuning = colOpt.IsUsingAutotuning();
5123  if ((autotuning == false) && (ImpType == Collections::eNoImpType))
5124  {
5125  // turn on autotuning if writeoptfile specified
5126  // if m_graph available
5127  if (m_session->GetUpdateOptFile() && m_graph)
5128  {
5129  // only turn on autotuning for volumetric elements
5130  // where Mesh Dimension is equal to the Shape
5131  // Dimension of element.
5132  if (m_graph->GetMeshDimension() == (*m_exp)[0]->GetShapeDimension())
5133  {
5134  autotuning = true;
5135  }
5136  }
5137  }
5138  bool verbose = (m_session->DefinesCmdLineArgument("verbose")) &&
5139  (m_session->GetComm()->GetRank() == 0);
5140  int collmax =
5141  (colOpt.GetMaxCollectionSize() > 0 ? colOpt.GetMaxCollectionSize()
5142  : 2 * m_exp->size());
5143 
5144  // clear vectors in case previously called
5145  m_collections.clear();
5146  m_coll_coeff_offset.clear();
5147  m_coll_phys_offset.clear();
5148 
5149  // Loop over expansions, and create collections for each element type
5150  for (int i = 0; i < m_exp->size(); ++i)
5151  {
5152  collections[(*m_exp)[i]->DetShapeType()].push_back(
5153  std::pair<LocalRegions::ExpansionSharedPtr, int>((*m_exp)[i], i));
5154  }
5155 
5156  for (auto &it : collections)
5157  {
5158  LocalRegions::ExpansionSharedPtr exp = it.second[0].first;
5159 
5160  Collections::OperatorImpMap impTypes = colOpt.GetOperatorImpMap(exp);
5161 
5162  vector<StdRegions::StdExpansionSharedPtr> collExp;
5163 
5164  int prevCoeffOffset = m_coeff_offset[it.second[0].second];
5165  int prevPhysOffset = m_phys_offset[it.second[0].second];
5166  int collcnt;
5167 
5168  m_coll_coeff_offset.push_back(prevCoeffOffset);
5169  m_coll_phys_offset.push_back(prevPhysOffset);
5170 
5171  int collsize = 0;
5172 
5173  if (it.second.size() == 1) // single element case
5174  {
5175  collExp.push_back(it.second[0].first);
5176 
5177  // if no Imp Type provided and No
5178  // setting in xml file. reset
5179  // impTypes using timings
5180  if (autotuning)
5181  {
5182  if (collExp.size() > collsize)
5183  {
5184  impTypes =
5185  colOpt.SetWithTimings(collExp, impTypes, verbose);
5186  collsize = collExp.size();
5187  }
5188  }
5189 
5190  Collections::Collection tmp(collExp, impTypes);
5191  m_collections.push_back(tmp);
5192  }
5193  else
5194  {
5195  // set up first geometry
5196  collExp.push_back(it.second[0].first);
5197  int prevnCoeff = it.second[0].first->GetNcoeffs();
5198  int prevnPhys = it.second[0].first->GetTotPoints();
5199  bool prevDeformed =
5200  it.second[0].first->GetMetricInfo()->GetGtype() ==
5202  collcnt = 1;
5203 
5204  for (int i = 1; i < it.second.size(); ++i)
5205  {
5206  int nCoeffs = it.second[i].first->GetNcoeffs();
5207  int nPhys = it.second[i].first->GetTotPoints();
5208  bool Deformed =
5209  it.second[i].first->GetMetricInfo()->GetGtype() ==
5211  int coeffOffset = m_coeff_offset[it.second[i].second];
5212  int physOffset = m_phys_offset[it.second[i].second];
5213 
5214  // check to see if next elmt is different or
5215  // collmax reached and if so end collection
5216  // and start new one
5217  if (prevCoeffOffset + nCoeffs != coeffOffset ||
5218  prevnCoeff != nCoeffs ||
5219  prevPhysOffset + nPhys != physOffset ||
5220  prevDeformed != Deformed || prevnPhys != nPhys ||
5221  collcnt >= collmax)
5222  {
5223 
5224  // if no Imp Type provided and No
5225  // settign in xml file. reset
5226  // impTypes using timings
5227  if (autotuning)
5228  {
5229  if (collExp.size() > collsize)
5230  {
5231  impTypes = colOpt.SetWithTimings(collExp, impTypes,
5232  verbose);
5233  collsize = collExp.size();
5234  }
5235  }
5236 
5237  Collections::Collection tmp(collExp, impTypes);
5238  m_collections.push_back(tmp);
5239 
5240  // start new geom list
5241  collExp.clear();
5242 
5243  m_coll_coeff_offset.push_back(coeffOffset);
5244  m_coll_phys_offset.push_back(physOffset);
5245  collExp.push_back(it.second[i].first);
5246  collcnt = 1;
5247  }
5248  else // add to list of collections
5249  {
5250  collExp.push_back(it.second[i].first);
5251  collcnt++;
5252  }
5253 
5254  // if end of list finish up collection
5255  if (i == it.second.size() - 1)
5256  {
5257  // if no Imp Type provided and No
5258  // settign in xml file.
5259  if (autotuning)
5260  {
5261  if (collExp.size() > collsize)
5262  {
5263  impTypes = colOpt.SetWithTimings(collExp, impTypes,
5264  verbose);
5265  collsize = collExp.size();
5266  }
5267  }
5268 
5269  Collections::Collection tmp(collExp, impTypes);
5270  m_collections.push_back(tmp);
5271 
5272  collExp.clear();
5273  collcnt = 0;
5274  }
5275 
5276  prevCoeffOffset = coeffOffset;
5277  prevPhysOffset = physOffset;
5278  prevDeformed = Deformed;
5279  prevnCoeff = nCoeffs;
5280  prevnPhys = nPhys;
5281  }
5282  }
5283  }
5284 
5285  // update optimisation file
5286  if ((m_session->GetUpdateOptFile()) && (ImpType == Collections::eNoImpType))
5287  {
5288  colOpt.UpdateOptFile(m_session->GetSessionName(), m_comm);
5289  // turn off writeoptfile option so only first
5290  // instance is timed
5291  m_session->SetUpdateOptFile(false);
5292  }
5293 }
5294 
5296 {
5298 }
5299 
5300 /**
5301  * Added for access to the pool count by external code (e.g. UnitTests)
5302  * which can't access the static pool across compilation units on
5303  * Windows builds.
5304  */
5305 int ExpList::GetPoolCount(std::string poolName)
5306 {
5307  return v_GetPoolCount(poolName);
5308 }
5309 
5310 void ExpList::UnsetGlobalLinSys(GlobalLinSysKey key, bool clearLocalMatrices)
5311 {
5312  v_UnsetGlobalLinSys(key, clearLocalMatrices);
5313 }
5314 
5317 {
5318  return v_GetGlobalLinSysManager();
5319 }
5320 
5322  const Array<OneD, NekDouble> &inarray,
5323  Array<OneD, NekDouble> &outarray)
5324 {
5325  int cnt, cnt1;
5326 
5327  cnt = cnt1 = 0;
5328 
5329  switch (m_expType)
5330  {
5331  case e2D:
5332  {
5333  for (int i = 0; i < GetExpSize(); ++i)
5334  {
5335  // get new points key
5336  int pt0 = (*m_exp)[i]->GetNumPoints(0);
5337  int pt1 = (*m_exp)[i]->GetNumPoints(1);
5338  int npt0 = (int)pt0 * scale;
5339  int npt1 = (int)pt1 * scale;
5340 
5341  LibUtilities::PointsKey newPointsKey0(
5342  npt0, (*m_exp)[i]->GetPointsType(0));
5343  LibUtilities::PointsKey newPointsKey1(
5344  npt1, (*m_exp)[i]->GetPointsType(1));
5345 
5346  // Interpolate points;
5347  LibUtilities::Interp2D((*m_exp)[i]->GetBasis(0)->GetPointsKey(),
5348  (*m_exp)[i]->GetBasis(1)->GetPointsKey(),
5349  &inarray[cnt], newPointsKey0,
5350  newPointsKey1, &outarray[cnt1]);
5351 
5352  cnt += pt0 * pt1;
5353  cnt1 += npt0 * npt1;
5354  }
5355  }
5356  break;
5357  case e3D:
5358  {
5359  for (int i = 0; i < GetExpSize(); ++i)
5360  {
5361  // get new points key
5362  int pt0 = (*m_exp)[i]->GetNumPoints(0);
5363  int pt1 = (*m_exp)[i]->GetNumPoints(1);
5364  int pt2 = (*m_exp)[i]->GetNumPoints(2);
5365  int npt0 = (int)pt0 * scale;
5366  int npt1 = (int)pt1 * scale;
5367  int npt2 = (int)pt2 * scale;
5368 
5369  LibUtilities::PointsKey newPointsKey0(
5370  npt0, (*m_exp)[i]->GetPointsType(0));
5371  LibUtilities::PointsKey newPointsKey1(
5372  npt1, (*m_exp)[i]->GetPointsType(1));
5373  LibUtilities::PointsKey newPointsKey2(
5374  npt2, (*m_exp)[i]->GetPointsType(2));
5375 
5376  // Interpolate points;
5377  LibUtilities::Interp3D((*m_exp)[i]->GetBasis(0)->GetPointsKey(),
5378  (*m_exp)[i]->GetBasis(1)->GetPointsKey(),
5379  (*m_exp)[i]->GetBasis(2)->GetPointsKey(),
5380  &inarray[cnt], newPointsKey0,
5381  newPointsKey1, newPointsKey2,
5382  &outarray[cnt1]);
5383 
5384  cnt += pt0 * pt1 * pt2;
5385  cnt1 += npt0 * npt1 * npt2;
5386  }
5387  }
5388  break;
5389  default:
5390  {
5391  NEKERROR(ErrorUtil::efatal, "This expansion is not set");
5392  }
5393  break;
5394  }
5395 }
5396 
5398  const Array<OneD, const NekDouble> &FwdFlux,
5399  const Array<OneD, const NekDouble> &BwdFlux,
5400  Array<OneD, NekDouble> &outarray)
5401 {
5402  boost::ignore_unused(FwdFlux, BwdFlux, outarray);
5403  NEKERROR(ErrorUtil::efatal, "AddTraceIntegralToOffDiag not defined");
5404 }
5405 
5407  const Array<OneD, const Array<OneD, NekDouble>> &inarray, const int nDirctn,
5408  Array<OneD, DNekMatSharedPtr> &mtxPerVar)
5409 {
5410  int nTotElmt = (*m_exp).size();
5411  int nElmtPnt = (*m_exp)[0]->GetTotPoints();
5412  int nElmtCoef = (*m_exp)[0]->GetNcoeffs();
5413 
5414  Array<OneD, NekDouble> tmpCoef(nElmtCoef, 0.0);
5415  Array<OneD, NekDouble> tmpPhys(nElmtPnt, 0.0);
5416 
5417  for (int nelmt = 0; nelmt < nTotElmt; nelmt++)
5418  {
5419  nElmtCoef = (*m_exp)[nelmt]->GetNcoeffs();
5420  nElmtPnt = (*m_exp)[nelmt]->GetTotPoints();
5421 
5422  if (tmpPhys.size() != nElmtPnt || tmpCoef.size() != nElmtCoef)
5423  {
5424  tmpPhys = Array<OneD, NekDouble>(nElmtPnt, 0.0);
5425  tmpCoef = Array<OneD, NekDouble>(nElmtCoef, 0.0);
5426  }
5427 
5428  for (int ncl = 0; ncl < nElmtPnt; ncl++)
5429  {
5430  tmpPhys[ncl] = inarray[nelmt][ncl];
5431 
5432  (*m_exp)[nelmt]->IProductWRTDerivBase(nDirctn, tmpPhys, tmpCoef);
5433 
5434  for (int nrw = 0; nrw < nElmtCoef; nrw++)
5435  {
5436  (*mtxPerVar[nelmt])(nrw, ncl) = tmpCoef[nrw];
5437  }
5438  // to maintain all the other columes are zero.
5439  tmpPhys[ncl] = 0.0;
5440  }
5441  }
5442 }
5443 
5445  Array<OneD, DNekMatSharedPtr> &mtxPerVar)
5446 {
5447  int nTotElmt = (*m_exp).size();
5448 
5449  int nspacedim = m_graph->GetSpaceDimension();
5450  Array<OneD, Array<OneD, NekDouble>> projectedpnts(nspacedim);
5451  Array<OneD, Array<OneD, NekDouble>> tmppnts(nspacedim);
5452  Array<OneD, DNekMatSharedPtr> ArrayStdMat(nspacedim);
5453  Array<OneD, Array<OneD, NekDouble>> ArrayStdMat_data(nspacedim);
5454 
5455  Array<OneD, NekDouble> clmnArray, clmnStdMatArray;
5456 
5458  int nElmtPntPrevious = 0;
5459  int nElmtCoefPrevious = 0;
5460 
5461  int nElmtPnt, nElmtCoef;
5462  for (int nelmt = 0; nelmt < nTotElmt; nelmt++)
5463  {
5464  nElmtCoef = (*m_exp)[nelmt]->GetNcoeffs();
5465  nElmtPnt = (*m_exp)[nelmt]->GetTotPoints();
5466  LibUtilities::ShapeType ElmtTypeNow = (*m_exp)[nelmt]->DetShapeType();
5467 
5468  if (nElmtPntPrevious != nElmtPnt || nElmtCoefPrevious != nElmtCoef ||
5469  (ElmtTypeNow != ElmtTypePrevious))
5470  {
5471  if (nElmtPntPrevious != nElmtPnt)
5472  {
5473  for (int ndir = 0; ndir < nspacedim; ndir++)
5474  {
5475  projectedpnts[ndir] = Array<OneD, NekDouble>(nElmtPnt, 0.0);
5476  tmppnts[ndir] = Array<OneD, NekDouble>(nElmtPnt, 0.0);
5477  }
5478  }
5480  stdExp = (*m_exp)[nelmt]->GetStdExp();
5482  stdExp->DetShapeType(), *stdExp);
5483 
5484  ArrayStdMat[0] = stdExp->GetStdMatrix(matkey);
5485  ArrayStdMat_data[0] = ArrayStdMat[0]->GetPtr();
5486 
5487  if (nspacedim > 1)
5488  {
5489  StdRegions::StdMatrixKey matkey(
5490  StdRegions::eDerivBase1, stdExp->DetShapeType(), *stdExp);
5491 
5492  ArrayStdMat[1] = stdExp->GetStdMatrix(matkey);
5493  ArrayStdMat_data[1] = ArrayStdMat[1]->GetPtr();
5494 
5495  if (nspacedim > 2)
5496  {
5498  stdExp->DetShapeType(),
5499  *stdExp);
5500 
5501  ArrayStdMat[2] = stdExp->GetStdMatrix(matkey);
5502  ArrayStdMat_data[2] = ArrayStdMat[2]->GetPtr();
5503  }
5504  }
5505 
5506  ElmtTypePrevious = ElmtTypeNow;
5507  nElmtPntPrevious = nElmtPnt;
5508  nElmtCoefPrevious = nElmtCoef;
5509  }
5510  else
5511  {
5512  for (int ndir = 0; ndir < nspacedim; ndir++)
5513  {
5514  Vmath::Zero(nElmtPnt, projectedpnts[ndir], 1);
5515  }
5516  }
5517 
5518  for (int ndir = 0; ndir < nspacedim; ndir++)
5519  {
5520  (*m_exp)[nelmt]->AlignVectorToCollapsedDir(
5521  ndir, inarray[ndir][nelmt], tmppnts);
5522  for (int n = 0; n < nspacedim; n++)
5523  {
5524  Vmath::Vadd(nElmtPnt, tmppnts[n], 1, projectedpnts[n], 1,
5525  projectedpnts[n], 1);
5526  }
5527  }
5528 
5529  for (int ndir = 0; ndir < nspacedim; ndir++)
5530  {
5531  // weight with metric
5532  (*m_exp)[nelmt]->MultiplyByQuadratureMetric(projectedpnts[ndir],
5533  projectedpnts[ndir]);
5534  Array<OneD, NekDouble> MatDataArray = mtxPerVar[nelmt]->GetPtr();
5535 
5536  for (int np = 0; np < nElmtPnt; np++)
5537  {
5538  NekDouble factor = projectedpnts[ndir][np];
5539  clmnArray = MatDataArray + np * nElmtCoef;
5540  clmnStdMatArray = ArrayStdMat_data[ndir] + np * nElmtCoef;
5541  Vmath::Svtvp(nElmtCoef, factor, clmnStdMatArray, 1, clmnArray,
5542  1, clmnArray, 1);
5543  }
5544  }
5545  }
5546 }
5547 
5548 // TODO: Reduce cost by getting Bwd Matrix directly
5550  const Array<OneD, const Array<OneD, NekDouble>> &inarray,
5551  Array<OneD, DNekMatSharedPtr> &mtxPerVar)
5552 {
5554  int nElmtPntPrevious = 0;
5555  int nElmtCoefPrevious = 0;
5556  int nTotElmt = (*m_exp).size();
5557  int nElmtPnt = (*m_exp)[0]->GetTotPoints();
5558  int nElmtCoef = (*m_exp)[0]->GetNcoeffs();
5559 
5560  Array<OneD, NekDouble> tmpPhys;
5561  Array<OneD, NekDouble> clmnArray, clmnStdMatArray;
5562  Array<OneD, NekDouble> stdMat_data;
5563 
5564  for (int nelmt = 0; nelmt < nTotElmt; nelmt++)
5565  {
5566  nElmtCoef = (*m_exp)[nelmt]->GetNcoeffs();
5567  nElmtPnt = (*m_exp)[nelmt]->GetTotPoints();
5568  LibUtilities::ShapeType ElmtTypeNow = (*m_exp)[nelmt]->DetShapeType();
5569 
5570  if (nElmtPntPrevious != nElmtPnt || nElmtCoefPrevious != nElmtCoef ||
5571  (ElmtTypeNow != ElmtTypePrevious))
5572  {
5574  stdExp = (*m_exp)[nelmt]->GetStdExp();
5576  stdExp->DetShapeType(), *stdExp);
5577 
5578  DNekMatSharedPtr BwdMat = stdExp->GetStdMatrix(matkey);
5579  stdMat_data = BwdMat->GetPtr();
5580 
5581  if (nElmtPntPrevious != nElmtPnt)
5582  {
5583  tmpPhys = Array<OneD, NekDouble>(nElmtPnt, 0.0);
5584  }
5585 
5586  ElmtTypePrevious = ElmtTypeNow;
5587  nElmtPntPrevious = nElmtPnt;
5588  nElmtCoefPrevious = nElmtCoef;
5589  }
5590 
5591  (*m_exp)[nelmt]->MultiplyByQuadratureMetric(
5592  inarray[nelmt],
5593  tmpPhys); // weight with metric
5594 
5595  Array<OneD, NekDouble> MatDataArray = mtxPerVar[nelmt]->GetPtr();
5596 
5597  for (int np = 0; np < nElmtPnt; np++)
5598  {
5599  NekDouble factor = tmpPhys[np];
5600  clmnArray = MatDataArray + np * nElmtCoef;
5601  clmnStdMatArray = stdMat_data + np * nElmtCoef;
5602  Vmath::Smul(nElmtCoef, factor, clmnStdMatArray, 1, clmnArray, 1);
5603  }
5604  }
5605 }
5606 
5607 /**
5608  * @brief inverse process of v_GetFwdBwdTracePhys. Given Trace integration of
5609  * Fwd and Bwd Jacobian, with dimension NtotalTrace*TraceCoef*TracePhys. return
5610  * Elemental Jacobian matrix with dimension
5611  * NtotalElement*ElementCoef*ElementPhys.
5612  *
5613  *
5614  * @param field is a NekDouble array which contains the 2D data
5615  * from which we wish to extract the backward and
5616  * forward orientated trace/edge arrays.
5617  * @param Fwd The resulting forwards space.
5618  * @param Bwd The resulting backwards space.
5619  */
5624 {
5626  std::shared_ptr<LocalRegions::ExpansionVector> traceExp =
5627  tracelist->GetExp();
5628  int ntotTrace = (*traceExp).size();
5629  int nTracePnt, nTraceCoef;
5630 
5631  std::shared_ptr<LocalRegions::ExpansionVector> fieldExp = GetExp();
5632  int nElmtCoef;
5633 
5634  const MultiRegions::LocTraceToTraceMapSharedPtr locTraceToTraceMap =
5636  const Array<OneD, const Array<OneD, int>> LRAdjExpid =
5637  locTraceToTraceMap->GetLeftRightAdjacentExpId();
5638  const Array<OneD, const Array<OneD, bool>> LRAdjflag =
5639  locTraceToTraceMap->GetLeftRightAdjacentExpFlag();
5640 
5642  locTraceToTraceMap->GetTraceCoeffToLeftRightExpCoeffMap();
5644  locTraceToTraceMap->GetTraceCoeffToLeftRightExpCoeffSign();
5645  DNekMatSharedPtr ElmtMat;
5646  Array<OneD, NekDouble> ElmtMat_data;
5647  // int nclAdjExp;
5648  int nrwAdjExp;
5649  int MatIndex, nPnts;
5650  NekDouble sign = 1.0;
5651 
5652  int nTracePntsTtl = tracelist->GetTotPoints();
5653  int nlocTracePts = locTraceToTraceMap->GetNLocTracePts();
5654  int nlocTracePtsFwd = locTraceToTraceMap->GetNFwdLocTracePts();
5655  int nlocTracePtsBwd = nlocTracePts - nlocTracePtsFwd;
5656 
5657  Array<OneD, int> nlocTracePtsLR(2);
5658  nlocTracePtsLR[0] = nlocTracePtsFwd;
5659  nlocTracePtsLR[1] = nlocTracePtsBwd;
5660 
5661  size_t nFwdBwdNonZero = 0;
5662  Array<OneD, int> tmpIndex{2, -1};
5663  for (int i = 0; i < 2; ++i)
5664  {
5665  if (nlocTracePtsLR[i] > 0)
5666  {
5667  tmpIndex[nFwdBwdNonZero] = i;
5668  nFwdBwdNonZero++;
5669  }
5670  }
5671 
5672  Array<OneD, int> nlocTracePtsNonZeroIndex{nFwdBwdNonZero};
5673  for (int i = 0; i < nFwdBwdNonZero; ++i)
5674  {
5675  nlocTracePtsNonZeroIndex[i] = tmpIndex[i];
5676  }
5677 
5678  Array<OneD, NekDouble> TraceFwdPhy(nTracePntsTtl);
5679  Array<OneD, NekDouble> TraceBwdPhy(nTracePntsTtl);
5680  Array<OneD, Array<OneD, NekDouble>> tmplocTrace(2);
5681  for (int k = 0; k < 2; ++k)
5682  {
5683  tmplocTrace[k] = NullNekDouble1DArray;
5684  }
5685 
5686  for (int k = 0; k < nFwdBwdNonZero; ++k)
5687  {
5688  size_t i = nlocTracePtsNonZeroIndex[k];
5689  tmplocTrace[i] = Array<OneD, NekDouble>(nlocTracePtsLR[i]);
5690  }
5691 
5692  int nNumbElmt = fieldMat.size();
5693  Array<OneD, Array<OneD, NekDouble>> ElmtMatDataArray(nNumbElmt);
5694  Array<OneD, int> ElmtCoefArray(nNumbElmt);
5695  for (int i = 0; i < nNumbElmt; i++)
5696  {
5697  ElmtMatDataArray[i] = fieldMat[i]->GetPtr();
5698  ElmtCoefArray[i] = GetNcoeffs(i);
5699  }
5700 
5701  int nTraceCoefMax = 0;
5702  int nTraceCoefMin = std::numeric_limits<int>::max();
5703  Array<OneD, int> TraceCoefArray(ntotTrace);
5704  Array<OneD, int> TracePntArray(ntotTrace);
5705  Array<OneD, int> TraceOffArray(ntotTrace);
5706  Array<OneD, Array<OneD, NekDouble>> FwdMatData(ntotTrace);
5707  Array<OneD, Array<OneD, NekDouble>> BwdMatData(ntotTrace);
5708  for (int nt = 0; nt < ntotTrace; nt++)
5709  {
5710  nTraceCoef = (*traceExp)[nt]->GetNcoeffs();
5711  nTracePnt = tracelist->GetTotPoints(nt);
5712  int noffset = tracelist->GetPhys_Offset(nt);
5713  TraceCoefArray[nt] = nTraceCoef;
5714  TracePntArray[nt] = nTracePnt;
5715  TraceOffArray[nt] = noffset;
5716  FwdMatData[nt] = FwdMat[nt]->GetPtr();
5717  BwdMatData[nt] = BwdMat[nt]->GetPtr();
5718  if (nTraceCoef > nTraceCoefMax)
5719  {
5720  nTraceCoefMax = nTraceCoef;
5721  }
5722  if (nTraceCoef < nTraceCoefMin)
5723  {
5724  nTraceCoefMin = nTraceCoef;
5725  }
5726  }
5727  WARNINGL1(nTraceCoefMax == nTraceCoefMin,
5728  "nTraceCoefMax!=nTraceCoefMin: Effeciency may be low ");
5729 
5730  int traceID, nfieldPnts, ElmtId, noffset;
5731  const Array<OneD, const Array<OneD, int>> LocTracephysToTraceIDMap =
5732  locTraceToTraceMap->GetLocTracephysToTraceIDMap();
5733  const Array<OneD, const int> fieldToLocTraceMap =
5734  locTraceToTraceMap->GetLocTraceToFieldMap();
5735  Array<OneD, Array<OneD, int>> fieldToLocTraceMapLR(2);
5736  noffset = 0;
5737  for (int k = 0; k < nFwdBwdNonZero; ++k)
5738  {
5739  size_t i = nlocTracePtsNonZeroIndex[k];
5740  fieldToLocTraceMapLR[i] = Array<OneD, int>(nlocTracePtsLR[i]);
5741  Vmath::Vcopy(nlocTracePtsLR[i], &fieldToLocTraceMap[0] + noffset, 1,
5742  &fieldToLocTraceMapLR[i][0], 1);
5743  noffset += nlocTracePtsLR[i];
5744  }
5745 
5746  Array<OneD, Array<OneD, int>> MatIndexArray(2);
5747  for (int k = 0; k < nFwdBwdNonZero; ++k)
5748  {
5749  size_t nlr = nlocTracePtsNonZeroIndex[k];
5750  MatIndexArray[nlr] = Array<OneD, int>(nlocTracePtsLR[nlr]);
5751  for (int nloc = 0; nloc < nlocTracePtsLR[nlr]; nloc++)
5752  {
5753  traceID = LocTracephysToTraceIDMap[nlr][nloc];
5754  nTraceCoef = TraceCoefArray[traceID];
5755  ElmtId = LRAdjExpid[nlr][traceID];
5756  noffset = GetPhys_Offset(ElmtId);
5757  nElmtCoef = ElmtCoefArray[ElmtId];
5758  nfieldPnts = fieldToLocTraceMapLR[nlr][nloc];
5759  nPnts = nfieldPnts - noffset;
5760 
5761  MatIndexArray[nlr][nloc] = nPnts * nElmtCoef;
5762  }
5763  }
5764 
5765  for (int nc = 0; nc < nTraceCoefMin; nc++)
5766  {
5767  for (int nt = 0; nt < ntotTrace; nt++)
5768  {
5769  nTraceCoef = TraceCoefArray[nt];
5770  nTracePnt = TracePntArray[nt];
5771  noffset = TraceOffArray[nt];
5772  Vmath::Vcopy(nTracePnt, &FwdMatData[nt][nc], nTraceCoef,
5773  &TraceFwdPhy[noffset], 1);
5774  Vmath::Vcopy(nTracePnt, &BwdMatData[nt][nc], nTraceCoef,
5775  &TraceBwdPhy[noffset], 1);
5776  }
5777 
5778  for (int k = 0; k < nFwdBwdNonZero; ++k)
5779  {
5780  size_t i = nlocTracePtsNonZeroIndex[k];
5781  Vmath::Zero(nlocTracePtsLR[i], tmplocTrace[i], 1);
5782  }
5783 
5784  GetLocTraceFromTracePts(TraceFwdPhy, TraceBwdPhy, tmplocTrace[0],
5785  tmplocTrace[1]);
5786 
5787  for (int k = 0; k < nFwdBwdNonZero; ++k)
5788  {
5789  size_t nlr = nlocTracePtsNonZeroIndex[k];
5790  for (int nloc = 0; nloc < nlocTracePtsLR[nlr]; nloc++)
5791  {
5792  traceID = LocTracephysToTraceIDMap[nlr][nloc];
5793  nTraceCoef = TraceCoefArray[traceID];
5794  ElmtId = LRAdjExpid[nlr][traceID];
5795  nrwAdjExp = elmtLRMap[nlr][traceID][nc];
5796  sign = elmtLRSign[nlr][traceID][nc];
5797  MatIndex = MatIndexArray[nlr][nloc] + nrwAdjExp;
5798 
5799  ElmtMatDataArray[ElmtId][MatIndex] -=
5800  sign * tmplocTrace[nlr][nloc];
5801  }
5802  }
5803  }
5804 
5805  for (int nc = nTraceCoefMin; nc < nTraceCoefMax; nc++)
5806  {
5807  for (int nt = 0; nt < ntotTrace; nt++)
5808  {
5809  nTraceCoef = TraceCoefArray[nt];
5810  nTracePnt = TracePntArray[nt];
5811  noffset = TraceOffArray[nt];
5812  if (nc < nTraceCoef)
5813  {
5814  Vmath::Vcopy(nTracePnt, &FwdMatData[nt][nc], nTraceCoef,
5815  &TraceFwdPhy[noffset], 1);
5816  Vmath::Vcopy(nTracePnt, &BwdMatData[nt][nc], nTraceCoef,
5817  &TraceBwdPhy[noffset], 1);
5818  }
5819  else
5820  {
5821  Vmath::Zero(nTracePnt, &TraceFwdPhy[noffset], 1);
5822  Vmath::Zero(nTracePnt, &TraceBwdPhy[noffset], 1);
5823  }
5824  }
5825 
5826  for (int k = 0; k < nFwdBwdNonZero; ++k)
5827  {
5828  size_t i = nlocTracePtsNonZeroIndex[k];
5829  Vmath::Zero(nlocTracePtsLR[i], tmplocTrace[i], 1);
5830  }
5831  GetLocTraceFromTracePts(TraceFwdPhy, TraceBwdPhy, tmplocTrace[0],
5832  tmplocTrace[1]);
5833 
5834  for (int k = 0; k < nFwdBwdNonZero; ++k)
5835  {
5836  size_t nlr = nlocTracePtsNonZeroIndex[k];
5837  for (int nloc = 0; nloc < nlocTracePtsLR[nlr]; nloc++)
5838  {
5839  traceID = LocTracephysToTraceIDMap[nlr][nloc];
5840  nTraceCoef = TraceCoefArray[traceID];
5841  if (nc < nTraceCoef)
5842  {
5843  ElmtId = LRAdjExpid[nlr][traceID];
5844  nrwAdjExp = elmtLRMap[nlr][traceID][nc];
5845  sign = -elmtLRSign[nlr][traceID][nc];
5846  MatIndex = MatIndexArray[nlr][nloc] + nrwAdjExp;
5847 
5848  ElmtMatDataArray[ElmtId][MatIndex] +=
5849  sign * tmplocTrace[nlr][nloc];
5850  }
5851  }
5852  }
5853  }
5854 }
5855 
5857  const int dir, const Array<OneD, const DNekMatSharedPtr> ElmtJacQuad,
5858  Array<OneD, DNekMatSharedPtr> ElmtJacCoef)
5859 {
5860  int nelmt;
5861  int nelmtcoef, nelmtpnts, nelmtcoef0, nelmtpnts0;
5862 
5863  nelmtcoef = GetNcoeffs(0);
5864  nelmtpnts = GetTotPoints(0);
5865 
5866  Array<OneD, NekDouble> innarray(nelmtpnts, 0.0);
5867  Array<OneD, NekDouble> outarray(nelmtcoef, 0.0);
5868 
5869  Array<OneD, NekDouble> MatQ_data;
5870  Array<OneD, NekDouble> MatC_data;
5871 
5872  DNekMatSharedPtr tmpMatQ, tmpMatC;
5873 
5874  nelmtcoef0 = nelmtcoef;
5875  nelmtpnts0 = nelmtpnts;
5876 
5877  for (nelmt = 0; nelmt < (*m_exp).size(); ++nelmt)
5878  {
5879  nelmtcoef = GetNcoeffs(nelmt);
5880  nelmtpnts = GetTotPoints(nelmt);
5881 
5882  tmpMatQ = ElmtJacQuad[nelmt];
5883  tmpMatC = ElmtJacCoef[nelmt];
5884 
5885  MatQ_data = tmpMatQ->GetPtr();
5886  MatC_data = tmpMatC->GetPtr();
5887 
5888  if (nelmtcoef != nelmtcoef0)
5889  {
5890  outarray = Array<OneD, NekDouble>(nelmtcoef, 0.0);
5891  nelmtcoef0 = nelmtcoef;
5892  }
5893 
5894  if (nelmtpnts != nelmtpnts0)
5895  {
5896  innarray = Array<OneD, NekDouble>(nelmtpnts, 0.0);
5897  nelmtpnts0 = nelmtpnts;
5898  }
5899 
5900  for (int np = 0; np < nelmtcoef; np++)
5901  {
5902  Vmath::Vcopy(nelmtpnts, &MatQ_data[0] + np, nelmtcoef, &innarray[0],
5903  1);
5904  (*m_exp)[nelmt]->DivideByQuadratureMetric(innarray, innarray);
5905  (*m_exp)[nelmt]->IProductWRTDerivBase(dir, innarray, outarray);
5906 
5907  Vmath::Vadd(nelmtcoef, &outarray[0], 1, &MatC_data[0] + np,
5908  nelmtcoef, &MatC_data[0] + np, nelmtcoef);
5909  }
5910  }
5911 }
5912 
5914  const Array<OneD, const DNekMatSharedPtr> ElmtJacQuad,
5915  Array<OneD, DNekMatSharedPtr> ElmtJacCoef)
5916 {
5917  int nelmt;
5918  int nelmtcoef, nelmtpnts, nelmtcoef0, nelmtpnts0;
5919 
5920  nelmtcoef = GetNcoeffs(0);
5921  nelmtpnts = GetTotPoints(0);
5922 
5923  Array<OneD, NekDouble> innarray(nelmtpnts, 0.0);
5924  Array<OneD, NekDouble> outarray(nelmtcoef, 0.0);
5925 
5926  Array<OneD, NekDouble> MatQ_data;
5927  Array<OneD, NekDouble> MatC_data;
5928 
5929  DNekMatSharedPtr tmpMatQ, tmpMatC;
5930 
5931  nelmtcoef0 = nelmtcoef;
5932  nelmtpnts0 = nelmtpnts;
5933 
5934  for (nelmt = 0; nelmt < (*m_exp).size(); ++nelmt)
5935  {
5936  nelmtcoef = GetNcoeffs(nelmt);
5937  nelmtpnts = GetTotPoints(nelmt);
5938 
5939  tmpMatQ = ElmtJacQuad[nelmt];
5940  tmpMatC = ElmtJacCoef[nelmt];
5941 
5942  MatQ_data = tmpMatQ->GetPtr();
5943  MatC_data = tmpMatC->GetPtr();
5944 
5945  if (nelmtcoef != nelmtcoef0)
5946  {
5947  outarray = Array<OneD, NekDouble>(nelmtcoef, 0.0);
5948  nelmtcoef0 = nelmtcoef;
5949  }
5950 
5951  if (nelmtpnts != nelmtpnts0)
5952  {
5953  innarray = Array<OneD, NekDouble>(nelmtpnts, 0.0);
5954  nelmtpnts0 = nelmtpnts;
5955  }
5956 
5957  for (int np = 0; np < nelmtcoef; np++)
5958  {
5959  Vmath::Vcopy(nelmtpnts, &MatQ_data[0] + np, nelmtcoef, &innarray[0],
5960  1);
5961  (*m_exp)[nelmt]->DivideByQuadratureMetric(innarray, innarray);
5962  (*m_exp)[nelmt]->IProductWRTBase(innarray, outarray);
5963 
5964  Vmath::Vadd(nelmtcoef, &outarray[0], 1, &MatC_data[0] + np,
5965  nelmtcoef, &MatC_data[0] + np, nelmtcoef);
5966  }
5967  }
5968 }
5969 
5971  const NekDouble scale, const Array<OneD, NekDouble> &inarray,
5972  Array<OneD, NekDouble> &outarray)
5973 {
5974  int cnt, cnt1;
5975 
5976  cnt = cnt1 = 0;
5977 
5978  switch (m_expType)
5979  {
5980  case e2D:
5981  {
5982  for (int i = 0; i < GetExpSize(); ++i)
5983  {
5984  // get new points key
5985  int pt0 = (*m_exp)[i]->GetNumPoints(0);
5986  int pt1 = (*m_exp)[i]->GetNumPoints(1);
5987  int npt0 = (int)pt0 * scale;
5988  int npt1 = (int)pt1 * scale;
5989 
5990  LibUtilities::PointsKey newPointsKey0(
5991  npt0, (*m_exp)[i]->GetPointsType(0));
5992  LibUtilities::PointsKey newPointsKey1(
5993  npt1, (*m_exp)[i]->GetPointsType(1));
5994 
5995  // Project points;
5997  newPointsKey0, newPointsKey1, &inarray[cnt],
5998  (*m_exp)[i]->GetBasis(0)->GetPointsKey(),
5999  (*m_exp)[i]->GetBasis(1)->GetPointsKey(), &outarray[cnt1]);
6000 
6001  cnt += npt0 * npt1;
6002  cnt1 += pt0 * pt1;
6003  }
6004  }
6005  break;
6006  case e3D:
6007  {
6008  for (int i = 0; i < GetExpSize(); ++i)
6009  {
6010  // get new points key
6011  int pt0 = (*m_exp)[i]->GetNumPoints(0);
6012  int pt1 = (*m_exp)[i]->GetNumPoints(1);
6013  int pt2 = (*m_exp)[i]->GetNumPoints(2);
6014  int npt0 = (int)pt0 * scale;
6015  int npt1 = (int)pt1 * scale;
6016  int npt2 = (int)pt2 * scale;
6017 
6018  LibUtilities::PointsKey newPointsKey0(
6019  npt0, (*m_exp)[i]->GetPointsType(0));
6020  LibUtilities::PointsKey newPointsKey1(
6021  npt1, (*m_exp)[i]->GetPointsType(1));
6022  LibUtilities::PointsKey newPointsKey2(
6023  npt2, (*m_exp)[i]->GetPointsType(2));
6024 
6025  // Project points;
6027  newPointsKey0, newPointsKey1, newPointsKey2, &inarray[cnt],
6028  (*m_exp)[i]->GetBasis(0)->GetPointsKey(),
6029  (*m_exp)[i]->GetBasis(1)->GetPointsKey(),
6030  (*m_exp)[i]->GetBasis(2)->GetPointsKey(), &outarray[cnt1]);
6031 
6032  cnt += npt0 * npt1 * npt2;
6033  cnt1 += pt0 * pt1 * pt2;
6034  }
6035  }
6036  break;
6037  default:
6038  {
6039  NEKERROR(ErrorUtil::efatal, "not setup for this expansion");
6040  }
6041  break;
6042  }
6043 }
6044 
6046 {
6047  NEKERROR(ErrorUtil::efatal, "v_GetLocTraceToTraceMap not coded");
6049 }
6050 
6051 } // namespace MultiRegions
6052 } // namespace Nektar
#define WARNINGL1(condition, msg)
Definition: ErrorUtil.hpp:250
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:209
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:249
#define LIKWID_MARKER_START(regionTag)
Definition: Likwid.hpp:46
#define LIKWID_MARKER_STOP(regionTag)
Definition: Likwid.hpp:47
#define sign(a, b)
return the sign(b)*a
Definition: Polylib.cpp:49
COLLECTIONS_EXPORT OperatorImpMap SetWithTimings(std::vector< StdRegions::StdExpansionSharedPtr > pGeom, OperatorImpMap &impTypes, bool verbose=true)
COLLECTIONS_EXPORT void UpdateOptFile(std::string sessName, LibUtilities::CommSharedPtr &comm)
COLLECTIONS_EXPORT OperatorImpMap GetOperatorImpMap(StdRegions::StdExpansionSharedPtr pExp)
Get Operator Implementation Map from XMl or using default;.
Describes the specification for a Basis.
Definition: Basis.h:50
int GetNumPoints() const
Return points order at which basis is defined.
Definition: Basis.h:130
BasisType GetBasisType() const
Return type of expansion basis.
Definition: Basis.h:141
PointsKey GetPointsKey() const
Return distribution of points.
Definition: Basis.h:147
int GetNumModes() const
Returns the order of the basis.
Definition: Basis.h:83
static const std::string GetFileType(const std::string &filename, CommSharedPtr comm)
Determine file type of given input file.
Definition: FieldIO.cpp:97
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
Defines a specification for a set of points.
Definition: Points.h:59
void AccumulateRegion(std::string, int iolevel=0)
Accumulate elapsed time for a region.
Definition: Timer.cpp:73
General purpose memory allocation routines with the ability to allocate from thread specific memory p...
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
Base class for all multi-elemental spectral/hp expansions.
Definition: ExpList.h:103
virtual void v_Reset()
Reset geometry information, metrics, matrix managers and geometry information.
Definition: ExpList.cpp:2673
Array< OneD, NekDouble > m_coeffs
Concatenation of all local expansion coefficients.
Definition: ExpList.h:1076
void AddTraceJacToElmtJac(const Array< OneD, const DNekMatSharedPtr > &FwdMat, const Array< OneD, const DNekMatSharedPtr > &BwdMat, Array< OneD, DNekMatSharedPtr > &fieldMat)
inverse process of v_GetFwdBwdTracePhys. Given Trace integration of Fwd and Bwd Jacobian,...
Definition: ExpList.cpp:5620
void IProductWRTBase(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
This function calculates the inner product of a function with respect to all local expansion modes .
Definition: ExpList.h:1630
const Array< OneD, const std::shared_ptr< ExpList > > & GetBndCondExpansions()
Definition: ExpList.h:2071
std::shared_ptr< ExpList > & GetTrace()
Definition: ExpList.h:2112
int GetNcoeffs(void) const
Returns the total number of local degrees of freedom .
Definition: ExpList.h:1492
virtual void v_ExtractCoeffsToCoeffs(const std::shared_ptr< ExpList > &fromExpList, const Array< OneD, const NekDouble > &fromCoeffs, Array< OneD, NekDouble > &toCoeffs)
Definition: ExpList.cpp:3675
virtual void v_Upwind(const Array< OneD, const Array< OneD, NekDouble >> &Vec, const Array< OneD, const NekDouble > &Fwd, const Array< OneD, const NekDouble > &Bwd, Array< OneD, NekDouble > &Upwind)
Definition: ExpList.cpp:3818
const DNekScalBlkMatSharedPtr & GetBlockMatrix(const GlobalMatrixKey &gkey)
Definition: ExpList.cpp:2016
virtual void v_AddFwdBwdTraceIntegral(const Array< OneD, const NekDouble > &Fwd, const Array< OneD, const NekDouble > &Bwd, Array< OneD, NekDouble > &outarray)
Definition: ExpList.cpp:4397
LibUtilities::NekManager< GlobalLinSysKey, GlobalLinSys > & GetGlobalLinSysManager(void)
Definition: ExpList.cpp:5316
ExpList(const ExpansionType Type=eNoType)
The default constructor using a type.
Definition: ExpList.cpp:102
void CreateCollections(Collections::ImplementationType ImpType=Collections::eNoImpType)
Construct collections of elements containing a single element type and polynomial order from the list...
Definition: ExpList.cpp:5103
virtual void v_GetBoundaryToElmtMap(Array< OneD, int > &ElmtID, Array< OneD, int > &EdgeID)
Definition: ExpList.cpp:4993
void ExponentialFilter(Array< OneD, NekDouble > &array, const NekDouble alpha, const NekDouble exponent, const NekDouble cutoff)
Definition: ExpList.cpp:1750
std::shared_ptr< GlobalMatrix > GenGlobalMatrix(const GlobalMatrixKey &mkey, const std::shared_ptr< AssemblyMapCG > &locToGloMap)
Generates a global matrix from the given key and map.
Definition: ExpList.cpp:2131
virtual void v_IProductWRTBase(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: ExpList.cpp:4718
void AddRightIPTPhysDerivBase(const int dir, const Array< OneD, const DNekMatSharedPtr > ElmtJacQuad, Array< OneD, DNekMatSharedPtr > ElmtJacCoef)
Definition: ExpList.cpp:5856
virtual void v_ExtractTracePhys(Array< OneD, NekDouble > &outarray)
Definition: ExpList.cpp:4485
int GetExpIndex(const Array< OneD, const NekDouble > &gloCoord, NekDouble tol=0.0, bool returnNearestElmt=false, int cachedId=-1, NekDouble maxDistance=1e6)
This function returns the index of the local elemental expansion containing the arbitrary point given...
Definition: ExpList.cpp:2521
virtual GlobalLinSysKey v_HelmSolve(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::ConstFactorMap &factors, const StdRegions::VarCoeffMap &varcoeff, const MultiRegions::VarFactorsMap &varfactors, const Array< OneD, const NekDouble > &dirForcing, const bool PhysSpaceForcing)
Definition: ExpList.cpp:4509
virtual void v_WriteTecplotConnectivity(std::ostream &outfile, int expansion)
Definition: ExpList.cpp:2831
BlockMatrixMapShPtr m_blockMat
Definition: ExpList.h:1125
virtual Array< OneD, const unsigned int > v_GetYIDs(void)
Definition: ExpList.cpp:3295
void MultiplyByQuadratureMetric(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
multiply the metric jacobi and quadrature weights
Definition: ExpList.cpp:1347
void GetBoundaryToElmtMap(Array< OneD, int > &ElmtID, Array< OneD, int > &EdgeID)
Definition: ExpList.h:2222
void WriteVtkPieceFooter(std::ostream &outfile, int expansion)
Definition: ExpList.cpp:3092
virtual void v_ExtractPhysToBnd(const int i, const Array< OneD, const NekDouble > &phys, Array< OneD, NekDouble > &bnd)
Definition: ExpList.cpp:4912
void GetBwdWeight(Array< OneD, NekDouble > &weightAver, Array< OneD, NekDouble > &weightJump)
Get the weight value for boundary conditions for boundary average and jump calculations.
Definition: ExpList.cpp:3704
virtual void v_AddTraceIntegralToOffDiag(const Array< OneD, const NekDouble > &FwdFlux, const Array< OneD, const NekDouble > &BwdFlux, Array< OneD, NekDouble > &outarray)
Definition: ExpList.cpp:5397
virtual std::vector< bool > & v_GetLeftAdjacentTraces(void)
Definition: ExpList.cpp:3937
void InitialiseExpVector(const SpatialDomains::ExpansionInfoMap &expmap)
Define a list of elements using the geometry and basis key information in expmap;.
Definition: ExpList.cpp:1142
void SetupCoeffPhys(bool DeclareCoeffPhysArrays=true, bool SetupOffsets=true)
Definition of the total number of degrees of freedom and quadrature points and offsets to access data...
Definition: ExpList.cpp:1099
static SpatialDomains::BoundaryConditionShPtr GetBoundaryCondition(const SpatialDomains::BoundaryConditionCollection &collection, unsigned int index, const std::string &variable)
Definition: ExpList.cpp:5070
virtual void v_CurlCurl(Array< OneD, Array< OneD, NekDouble >> &Vel, Array< OneD, Array< OneD, NekDouble >> &Q)
Definition: ExpList.cpp:1652
virtual void v_PhysDirectionalDeriv(const Array< OneD, const NekDouble > &direction, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: ExpList.cpp:1720
virtual void v_GetBCValues(Array< OneD, NekDouble > &BndVals, const Array< OneD, NekDouble > &TotField, int BndID)
Definition: ExpList.cpp:4585
virtual void v_GetLocTraceFromTracePts(const Array< OneD, const NekDouble > &Fwd, const Array< OneD, const NekDouble > &Bwd, Array< OneD, NekDouble > &locTraceFwd, Array< OneD, NekDouble > &locTraceBwd)
Definition: ExpList.cpp:4452
virtual void v_WriteTecplotHeader(std::ostream &outfile, std::string var="")
Definition: ExpList.cpp:2700
virtual std::shared_ptr< ExpList > & v_GetPlane(int n)
Definition: ExpList.cpp:5091
int GetCoeff_Offset(int n) const
Get the start offset position for a local contiguous list of coeffs correspoinding to element n.
Definition: ExpList.h:2037
int GetExpSize(void)
This function returns the number of elements in the expansion.
Definition: ExpList.h:1996
virtual void v_AddTraceQuadPhysToOffDiag(const Array< OneD, const NekDouble > &Fwd, const Array< OneD, const NekDouble > &Bwd, Array< OneD, NekDouble > &field)
Definition: ExpList.cpp:4443
virtual void v_ClearGlobalLinSysManager(void)
Definition: ExpList.cpp:3303
virtual void v_UnsetGlobalLinSys(GlobalLinSysKey, bool)
Definition: ExpList.cpp:3316
void GeneralGetFieldDefinitions(std::vector< LibUtilities::FieldDefinitionsSharedPtr > &fielddef, int NumHomoDir=0, Array< OneD, LibUtilities::BasisSharedPtr > &HomoBasis=LibUtilities::NullBasisSharedPtr1DArray, std::vector< NekDouble > &HomoLen=LibUtilities::NullNekDoubleVector, bool homoStrips=false, std::vector< unsigned int > &HomoSIDs=LibUtilities::NullUnsignedIntVector, std::vector< unsigned int > &HomoZIDs=LibUtilities::NullUnsignedIntVector, std::vector< unsigned int > &HomoYIDs=LibUtilities::NullUnsignedIntVector)
Definition: ExpList.cpp:3404
virtual void v_GetPeriodicEntities(PeriodicMap &periodicVerts, PeriodicMap &periodicEdges, PeriodicMap &periodicFaces)
Definition: ExpList.cpp:5061
void IProductWRTDerivBase(const int dir, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
This function calculates the inner product of a function with respect to the derivative (in directio...
Definition: ExpList.cpp:1391
virtual void v_LocalToGlobal(bool UseComm)
Definition: ExpList.cpp:4672
virtual const Array< OneD, const SpatialDomains::BoundaryConditionShPtr > & v_GetBndConditions()
Definition: ExpList.cpp:5018
virtual LibUtilities::NekManager< GlobalLinSysKey, GlobalLinSys > & v_GetGlobalLinSysManager(void)
Definition: ExpList.cpp:3324
virtual ~ExpList()
The default destructor.
Definition: ExpList.cpp:1315
virtual void v_FwdTransLocalElmt(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: ExpList.cpp:1809
int GetPoolCount(std::string)
Definition: ExpList.cpp:5305
virtual void v_ImposeDirichletConditions(Array< OneD, NekDouble > &outarray)
Definition: ExpList.cpp:4646
virtual void v_EvaluateBoundaryConditions(const NekDouble time=0.0, const std::string varName="", const NekDouble x2_in=NekConstants::kNekUnsetDouble, const NekDouble x3_in=NekConstants::kNekUnsetDouble)
Definition: ExpList.cpp:5039
virtual const std::vector< bool > & v_GetLeftAdjacentFaces(void) const
Definition: ExpList.cpp:4477
virtual void v_GetNormals(Array< OneD, Array< OneD, NekDouble >> &normals)
Populate normals with the normals of all expansions.
Definition: ExpList.cpp:4015
Array< OneD, int > m_coeff_offset
Offset of elemental data into the array m_coeffs.
Definition: ExpList.h:1120
virtual NekDouble v_VectorFlux(const Array< OneD, Array< OneD, NekDouble >> &inarray)
Definition: ExpList.cpp:3236
std::shared_ptr< AssemblyMapDG > & GetTraceMap(void)
Definition: ExpList.h:2116
size_t GetNumElmts(void)
This function returns the number of elements in the expansion which may be different for a homogeoeno...
Definition: ExpList.h:645
virtual std::shared_ptr< AssemblyMapDG > & v_GetTraceMap()
Definition: ExpList.cpp:3924
Array< OneD, std::pair< int, int > > m_coeffsToElmt
m_coeffs to elemental value map
Definition: ExpList.h:1124
virtual void v_GetFwdBwdTracePhys(Array< OneD, NekDouble > &Fwd, Array< OneD, NekDouble > &Bwd)
Definition: ExpList.cpp:4406
NekDouble PhysEvaluate(const Array< OneD, const NekDouble > &coords, const Array< OneD, const NekDouble > &phys)
Definition: ExpList.cpp:2638
virtual NekDouble v_Integral(const Array< OneD, const NekDouble > &inarray)
Definition: ExpList.cpp:3222
virtual void v_ExtractDataToCoeffs(LibUtilities::FieldDefinitionsSharedPtr &fielddef, std::vector< NekDouble > &fielddata, std::string &field, Array< OneD, NekDouble > &coeffs, std::unordered_map< int, int > zIdToPlane)
Extract data from raw field data into expansion list.
Definition: ExpList.cpp:3587
virtual std::map< int, RobinBCInfoSharedPtr > v_GetRobinBCInfo(void)
Definition: ExpList.cpp:5051
virtual const Array< OneD, const int > & v_GetTraceBndMap()
Definition: ExpList.cpp:3932
virtual GlobalLinSysKey v_LinearAdvectionDiffusionReactionSolve(const Array< OneD, Array< OneD, NekDouble >> &velocity, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const NekDouble lambda, const Array< OneD, const NekDouble > &dirForcing=NullNekDouble1DArray)
Definition: ExpList.cpp:4522
virtual Array< OneD, const NekDouble > v_HomogeneousEnergy(void)
Definition: ExpList.cpp:3256
virtual NekDouble v_GetHomoLen(void)
Definition: ExpList.cpp:3272
const LocTraceToTraceMapSharedPtr & GetLocTraceToTraceMap() const
Definition: ExpList.h:2082
virtual void v_LinearAdvectionReactionSolve(const Array< OneD, Array< OneD, NekDouble >> &velocity, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const NekDouble lambda, const Array< OneD, const NekDouble > &dirForcing=NullNekDouble1DArray)
Definition: ExpList.cpp:4534
virtual Array< OneD, const unsigned int > v_GetZIDs(void)
Definition: ExpList.cpp:3287
void ExtractCoeffsToCoeffs(const std::shared_ptr< ExpList > &fromExpList, const Array< OneD, const NekDouble > &fromCoeffs, Array< OneD, NekDouble > &toCoeffs)
Extract the data from fromField using fromExpList the coeffs using the basic ExpList Elemental expans...
Definition: ExpList.cpp:3571
void GetCoords(Array< OneD, NekDouble > &coord_0, Array< OneD, NekDouble > &coord_1=NullNekDouble1DArray, Array< OneD, NekDouble > &coord_2=NullNekDouble1DArray)
This function calculates the coordinates of all the elemental quadrature points .
Definition: ExpList.h:1728
std::shared_ptr< GlobalLinSys > GenGlobalBndLinSys(const GlobalLinSysKey &mkey, const AssemblyMapSharedPtr &locToGloMap)
Generate a GlobalLinSys from information provided by the key "mkey" and the mapping provided in LocTo...
Definition: ExpList.cpp:2434
virtual void v_SetBndCondBwdWeight(const int index, const NekDouble value)
Definition: ExpList.cpp:4470
void GetMatIpwrtDeriveBase(const Array< OneD, const Array< OneD, NekDouble >> &inarray, const int nDirctn, Array< OneD, DNekMatSharedPtr > &mtxPerVar)
Definition: ExpList.cpp:5406
void UnsetGlobalLinSys(GlobalLinSysKey, bool)
Definition: ExpList.cpp:5310
virtual void v_SmoothField(Array< OneD, NekDouble > &field)
Definition: ExpList.cpp:1841
virtual void v_AppendFieldData(LibUtilities::FieldDefinitionsSharedPtr &fielddef, std::vector< NekDouble > &fielddata)
Definition: ExpList.cpp:3531
std::vector< bool > m_collectionsDoInit
Vector of bools to act as an initialise on first call flag.
Definition: ExpList.h:1114
bool m_physState
The state of the array m_phys.
Definition: ExpList.h:1100
virtual void v_HomogeneousFwdTrans(const int npts, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool Shuff=true, bool UnShuff=true)
Definition: ExpList.cpp:4545
virtual void v_DealiasedDotProd(const int num_dofs, const Array< OneD, Array< OneD, NekDouble >> &inarray1, const Array< OneD, Array< OneD, NekDouble >> &inarray2, Array< OneD, Array< OneD, NekDouble >> &outarray)
Definition: ExpList.cpp:4575
void ExtractCoeffsFromFile(const std::string &fileName, LibUtilities::CommSharedPtr comm, const std::string &varName, Array< OneD, NekDouble > &coeffs)
Definition: ExpList.cpp:3331
virtual void v_DealiasedProd(const int num_dofs, const Array< OneD, NekDouble > &inarray1, const Array< OneD, NekDouble > &inarray2, Array< OneD, NekDouble > &outarray)
Definition: ExpList.cpp:4565
void AddRightIPTBaseMatrix(const Array< OneD, const DNekMatSharedPtr > ElmtJacQuad, Array< OneD, DNekMatSharedPtr > ElmtJacCoef)
Definition: ExpList.cpp:5913
void GetLocTraceFromTracePts(const Array< OneD, const NekDouble > &Fwd, const Array< OneD, const NekDouble > &Bwd, Array< OneD, NekDouble > &locTraceFwd, Array< OneD, NekDouble > &locTraceBwd)
Definition: ExpList.h:2170
virtual void v_WriteVtkPieceData(std::ostream &outfile, int expansion, std::string var)
Definition: ExpList.cpp:3099
virtual void v_WriteVtkPieceHeader(std::ostream &outfile, int expansion, int istrip)
Definition: ExpList.cpp:2958
int GetShapeDimension()
This function returns the dimension of the shape of the element eid.
Definition: ExpList.h:1870
NekDouble H1(const Array< OneD, const NekDouble > &inarray, const Array< OneD, const NekDouble > &soln=NullNekDouble1DArray)
Calculates the error of the global spectral/hp element approximation.
Definition: ExpList.cpp:3386
std::vector< int > m_coll_phys_offset
Offset of elemental data into the array m_phys.
Definition: ExpList.h:1118
LibUtilities::CommSharedPtr m_comm
Communicator.
Definition: ExpList.h:1049
std::shared_ptr< GlobalLinSys > GenGlobalLinSys(const GlobalLinSysKey &mkey, const std::shared_ptr< AssemblyMapCG > &locToGloMap)
This operation constructs the global linear system of type mkey.
Definition: ExpList.cpp:2416
void WriteVtkHeader(std::ostream &outfile)
Definition: ExpList.cpp:2944
std::shared_ptr< LocalRegions::ExpansionVector > m_exp
The list of local expansions.
Definition: ExpList.h:1111
int m_ncoeffs
The total number of local degrees of freedom. m_ncoeffs .
Definition: ExpList.h:1056
void GenerateElementVector(const int ElementID, const NekDouble scalar1, const NekDouble scalar2, Array< OneD, NekDouble > &outarray)
Generate vector v such that v[i] = scalar1 if i is in the element < ElementID. Otherwise,...
Definition: ExpList.cpp:3761
std::shared_ptr< DNekMat > GenGlobalMatrixFull(const GlobalLinSysKey &mkey, const std::shared_ptr< AssemblyMapCG > &locToGloMap)
Definition: ExpList.cpp:2264
virtual void v_NormVectorIProductWRTBase(Array< OneD, const NekDouble > &V1, Array< OneD, const NekDouble > &V2, Array< OneD, NekDouble > &outarray, int BndID)
Definition: ExpList.cpp:4593
virtual void v_ExtractElmtToBndPhys(const int i, const Array< OneD, NekDouble > &elmt, Array< OneD, NekDouble > &boundary)
Definition: ExpList.cpp:4835
virtual void v_ExtractPhysToBndElmt(const int i, const Array< OneD, const NekDouble > &phys, Array< OneD, NekDouble > &bndElmt)
Definition: ExpList.cpp:4873
virtual void v_AddTraceIntegral(const Array< OneD, const NekDouble > &Fx, const Array< OneD, const NekDouble > &Fy, Array< OneD, NekDouble > &outarray)
Definition: ExpList.cpp:4380
virtual void v_FillBwdWithBwdWeight(Array< OneD, NekDouble > &weightave, Array< OneD, NekDouble > &weightjmp)
Definition: ExpList.cpp:5001
virtual void v_PhysGalerkinProjection1DScaled(const NekDouble scale, const Array< OneD, NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: ExpList.cpp:5970
void GeneralMatrixOp(const GlobalMatrixKey &gkey, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
This function calculates the result of the multiplication of a matrix of type specified by mkey with ...
Definition: ExpList.cpp:2060
virtual void v_SetUpPhysNormals()
: Set up a normal along the trace elements between two elements at elemental level
Definition: ExpList.cpp:4812
virtual void v_GlobalToLocal(void)
Definition: ExpList.cpp:4687
virtual LibUtilities::TranspositionSharedPtr v_GetTransposition(void)
Definition: ExpList.cpp:3264
const std::shared_ptr< LocalRegions::ExpansionVector > GetExp() const
This function returns the vector of elements in the expansion.
Definition: ExpList.h:2029
SpatialDomains::MeshGraphSharedPtr m_graph
Mesh associated with this expansion list.
Definition: ExpList.h:1053
virtual void v_MultiplyByInvMassMatrix(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: ExpList.cpp:4500
virtual void v_AddTraceQuadPhysToField(const Array< OneD, const NekDouble > &Fwd, const Array< OneD, const NekDouble > &Bwd, Array< OneD, NekDouble > &field)
Definition: ExpList.cpp:4434
virtual const Array< OneD, const NekDouble > & v_GetBndCondBwdWeight()
Definition: ExpList.cpp:4462
virtual void v_GetMovingFrames(const SpatialDomains::GeomMMF MMFdir, const Array< OneD, const NekDouble > &CircCentre, Array< OneD, Array< OneD, NekDouble >> &outarray)
Definition: ExpList.cpp:3717
virtual NekDouble v_L2(const Array< OneD, const NekDouble > &phys, const Array< OneD, const NekDouble > &soln=NullNekDouble1DArray)
Definition: ExpList.cpp:3177
void WriteVtkFooter(std::ostream &outfile)
Definition: ExpList.cpp:2952
void MultiplyByBlockMatrix(const GlobalMatrixKey &gkey, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: ExpList.cpp:1327
virtual std::shared_ptr< ExpList > & v_GetTrace()
Definition: ExpList.cpp:3916
void GetElmtNormalLength(Array< OneD, NekDouble > &lengthsFwd, Array< OneD, NekDouble > &lengthsBwd)
Get the length of elements in boundary normal direction.
Definition: ExpList.cpp:4232
virtual std::vector< LibUtilities::FieldDefinitionsSharedPtr > v_GetFieldDefinitions(void)
Definition: ExpList.cpp:3516
std::vector< int > m_coll_coeff_offset
Offset of elemental data into the array m_coeffs.
Definition: ExpList.h:1116
void IProductWRTDirectionalDerivBase(const Array< OneD, const NekDouble > &direction, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Directional derivative along a given direction.
Definition: ExpList.cpp:1411
void FillBwdWithBwdWeight(Array< OneD, NekDouble > &weightave, Array< OneD, NekDouble > &weightjmp)
Fill Bwd with boundary conditions.
Definition: ExpList.h:2177
virtual void v_BwdTrans(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: ExpList.cpp:2470
virtual Array< OneD, SpatialDomains::BoundaryConditionShPtr > & v_UpdateBndConditions()
Definition: ExpList.cpp:5029
virtual void v_GetCoords(Array< OneD, NekDouble > &coord_0, Array< OneD, NekDouble > &coord_1=NullNekDouble1DArray, Array< OneD, NekDouble > &coord_2=NullNekDouble1DArray)
Definition: ExpList.cpp:4752
virtual void v_WriteTecplotField(std::ostream &outfile, int expansion)
Definition: ExpList.cpp:2911
virtual void v_FillBndCondFromField(const Array< OneD, NekDouble > coeffs)
Definition: ExpList.cpp:4655
std::shared_ptr< ExpList > GetSharedThisPtr()
Returns a shared pointer to the current object.
Definition: ExpList.h:950
Collections::CollectionVector m_collections
Definition: ExpList.h:1112
virtual int v_GetPoolCount(std::string)
Definition: ExpList.cpp:3309
virtual void v_PhysInterp1DScaled(const NekDouble scale, const Array< OneD, NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: ExpList.cpp:5321
virtual void v_HomogeneousBwdTrans(const int npts, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool Shuff=true, bool UnShuff=true)
Definition: ExpList.cpp:4555
virtual void v_GetBoundaryNormals(int i, Array< OneD, Array< OneD, NekDouble >> &normals)
Definition: ExpList.cpp:4949
void ApplyGeomInfo()
Apply geometry information to each expansion.
Definition: ExpList.cpp:2661
Array< OneD, const unsigned int > GetZIDs(void)
This function returns a vector containing the wave numbers in z-direction associated with the 3D homo...
Definition: ExpList.h:582
virtual void v_PhysDeriv(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &out_d0, Array< OneD, NekDouble > &out_d1, Array< OneD, NekDouble > &out_d2)
Definition: ExpList.cpp:1555
virtual void v_FwdTransBndConstrained(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: ExpList.cpp:1818
std::unordered_map< int, int > m_elmtToExpId
Mapping from geometry ID of element to index inside m_exp.
Definition: ExpList.h:1132
void GetDiagMatIpwrtBase(const Array< OneD, const Array< OneD, NekDouble >> &inarray, Array< OneD, DNekMatSharedPtr > &mtxPerVar)
Definition: ExpList.cpp:5549
virtual void v_WriteTecplotZone(std::ostream &outfile, int expansion)
Definition: ExpList.cpp:2738
LibUtilities::SessionReaderSharedPtr m_session
Session.
Definition: ExpList.h:1051
virtual void v_PeriodicBwdCopy(const Array< OneD, const NekDouble > &Fwd, Array< OneD, NekDouble > &Bwd)
Definition: ExpList.cpp:5008
std::map< int, RobinBCInfoSharedPtr > GetRobinBCInfo()
Definition: ExpList.h:879
virtual void v_FillBwdWithBoundCond(const Array< OneD, NekDouble > &Fwd, Array< OneD, NekDouble > &Bwd, bool PutFwdInBwdOnBCs)
Definition: ExpList.cpp:4425
void DivideByQuadratureMetric(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Divided by the metric jacobi and quadrature weights.
Definition: ExpList.cpp:1364
virtual const Array< OneD, const std::shared_ptr< ExpList > > & v_GetBndCondExpansions(void)
Definition: ExpList.cpp:3791
Array< OneD, int > m_phys_offset
Offset of elemental data into the array m_phys.
Definition: ExpList.h:1122
virtual void v_SetHomoLen(const NekDouble lhom)
Definition: ExpList.cpp:3280
void Upwind(const Array< OneD, const NekDouble > &Vn, const Array< OneD, const NekDouble > &Fwd, const Array< OneD, const NekDouble > &Bwd, Array< OneD, NekDouble > &Upwind)
Definition: ExpList.h:2105
const DNekScalBlkMatSharedPtr GenBlockMatrix(const GlobalMatrixKey &gkey)
This function assembles the block diagonal matrix of local matrices of the type mtype.
Definition: ExpList.cpp:1881
void PhysDeriv(Direction edir, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &out_d)
Definition: ExpList.h:1771
void MultiplyByElmtInvMass(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
This function elementally mulplies the coefficient space of Sin my the elemental inverse of the mass ...
Definition: ExpList.cpp:1771
void BwdTrans(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
This function elementally evaluates the backward transformation of the global spectral/hp element exp...
Definition: ExpList.h:1677
virtual void v_GetBndElmtExpansion(int i, std::shared_ptr< ExpList > &result, const bool DeclareCoeffPhysArrays)
Definition: ExpList.cpp:4825
virtual void v_FwdTrans(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: ExpList.cpp:4701
virtual std::shared_ptr< ExpList > & v_UpdateBndCondExpansion(int i)
Definition: ExpList.cpp:3799
int GetPhys_Offset(int n) const
Get the start offset position for a local contiguous list of quadrature points in a full array corres...
Definition: ExpList.h:2044
virtual const std::shared_ptr< LocTraceToTraceMap > & v_GetLocTraceToTraceMap(void) const
Definition: ExpList.cpp:6045
void ExtractDataToCoeffs(LibUtilities::FieldDefinitionsSharedPtr &fielddef, std::vector< NekDouble > &fielddata, std::string &field, Array< OneD, NekDouble > &coeffs, std::unordered_map< int, int > zIdToPlane=std::unordered_map< int, int >())
Extract the data in fielddata into the coeffs.
Definition: ExpList.cpp:3563
ExpansionType m_expType
Exapnsion type.
Definition: ExpList.h:1044
Array< OneD, NekDouble > m_phys
The global expansion evaluated at the quadrature points.
Definition: ExpList.h:1092
ExpansionType GetExpType(void)
Returns the type of the expansion.
Definition: ExpList.cpp:1310
NekDouble Linf(const Array< OneD, const NekDouble > &inarray, const Array< OneD, const NekDouble > &soln=NullNekDouble1DArray)
This function calculates the error of the global spectral/hp element approximation.
Definition: ExpList.cpp:3139
int GetTotPoints(void) const
Returns the total number of quadrature points m_npoints .
Definition: ExpList.h:1537
int GetCoordim(int eid)
This function returns the dimension of the coordinates of the element eid.
Definition: ExpList.h:1861
GlobalSysSolnType GetGlobalSysSolnType() const
Return the associated solution type.
Describes a matrix with ordering defined by a local to global map.
const StdRegions::ConstFactorMap & GetConstFactors() const
Returns all the constants.
LibUtilities::ShapeType GetShapeType() const
Return the expansion type associated with key.
const StdRegions::VarCoeffMap & GetVarCoeffs() const
StdRegions::MatrixType GetMatrixType() const
Return the matrix type.
static void Dscal(const int &n, const double &alpha, double *x, const int &incx)
BLAS level 1: x = alpha x.
Definition: Blas.hpp:168
std::map< OperatorType, ImplementationType > OperatorImpMap
Definition: Operator.h:112
void PhysGalerkinProject3D(const BasisKey &fbasis0, const BasisKey &fbasis1, const BasisKey &fbasis2, const Array< OneD, const NekDouble > &from, const BasisKey &tbasis0, const BasisKey &tbasis1, const BasisKey &tbasis2, Array< OneD, NekDouble > &to)
std::shared_ptr< FieldIO > FieldIOSharedPtr
Definition: FieldIO.h:327
static const BasisKey NullBasisKey(eNoBasisType, 0, NullPointsKey)
Defines a null basis with no type or points.
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:52
std::shared_ptr< SessionReader > SessionReaderSharedPtr
void Interp3D(const BasisKey &fbasis0, const BasisKey &fbasis1, const BasisKey &fbasis2, const Array< OneD, const NekDouble > &from, const BasisKey &tbasis0, const BasisKey &tbasis1, const BasisKey &tbasis2, Array< OneD, NekDouble > &to)
this function interpolates a 3D function evaluated at the quadrature points of the 3D basis,...
Definition: Interp.cpp:167
std::shared_ptr< FieldDefinitions > FieldDefinitionsSharedPtr
Definition: FieldIO.h:186
void Interp2D(const BasisKey &fbasis0, const BasisKey &fbasis1, const Array< OneD, const NekDouble > &from, const BasisKey &tbasis0, const BasisKey &tbasis1, Array< OneD, NekDouble > &to)
this function interpolates a 2D function evaluated at the quadrature points of the 2D basis,...
Definition: Interp.cpp:106
int GetNumberOfCoefficients(ShapeType shape, std::vector< unsigned int > &modes, int offset=0)
Definition: ShapeType.hpp:310
FieldIOFactory & GetFieldIOFactory()
Returns the FieldIO factory.
Definition: FieldIO.cpp:72
std::shared_ptr< Transposition > TranspositionSharedPtr
@ eNodalTriElec
2D Nodal Electrostatic Points on a Triangle
Definition: PointsType.h:83
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition: Comm.h:54
void PhysGalerkinProject2D(const BasisKey &fbasis0, const BasisKey &fbasis1, const Array< OneD, const NekDouble > &from, const BasisKey &tbasis0, const BasisKey &tbasis1, Array< OneD, NekDouble > &to)
@ eGauss_Lagrange
Lagrange Polynomials using the Gauss points.
Definition: BasisType.h:59
@ eOrtho_A
Principle Orthogonal Functions .
Definition: BasisType.h:44
@ eGLL_Lagrange
Lagrange for SEM basis .
Definition: BasisType.h:58
std::shared_ptr< PointExp > PointExpSharedPtr
Definition: PointExp.h:135
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:68
std::shared_ptr< Expansion2D > Expansion2DSharedPtr
Definition: Expansion1D.h:47
std::shared_ptr< Expansion0D > Expansion0DSharedPtr
Definition: Expansion0D.h:48
std::shared_ptr< Expansion1D > Expansion1DSharedPtr
Definition: Expansion1D.h:51
std::shared_ptr< Expansion3D > Expansion3DSharedPtr
Definition: Expansion2D.h:50
std::vector< ExpansionSharedPtr > ExpansionVector
Definition: Expansion.h:70
MultiRegions::Direction const DirCartesianMap[]
Definition: ExpList.h:91
void AlignFace(const StdRegions::Orientation orient, const int nquad1, const int nquad2, const Array< OneD, const NekDouble > &in, Array< OneD, NekDouble > &out)
Helper function to re-align face to a given orientation.
Definition: ExpList.cpp:3948
static ExpListSharedPtr NullExpListSharedPtr
Definition: ExpList.h:1479
std::shared_ptr< AssemblyMapCG > AssemblyMapCGSharedPtr
Definition: AssemblyMapCG.h:51
std::shared_ptr< RobinBCInfo > RobinBCInfoSharedPtr
const char *const GlobalSysSolnTypeMap[]
static LibUtilities::NekManager< GlobalLinSysKey, GlobalLinSys > NullGlobalLinSysManager
Definition: ExpList.h:1483
std::shared_ptr< GlobalLinSys > GlobalLinSysSharedPtr
Pointer to a GlobalLinSys object.
Definition: GlobalLinSys.h:50
std::shared_ptr< GlobalMatrix > GlobalMatrixSharedPtr
Shared pointer to a GlobalMatrix object.
Definition: GlobalMatrix.h:86
GlobalLinSysFactory & GetGlobalLinSysFactory()
static LocTraceToTraceMapSharedPtr NullLocTraceToTraceMapSharedPtr
std::shared_ptr< ExpList > ExpListSharedPtr
Shared pointer to an ExpList object.
static GlobalLinSysKey NullGlobalLinSysKey(StdRegions::eNoMatrixType)
std::shared_ptr< LocTraceToTraceMap > LocTraceToTraceMapSharedPtr
std::map< StdRegions::ConstFactorType, Array< OneD, NekDouble > > VarFactorsMap
std::shared_ptr< AssemblyMap > AssemblyMapSharedPtr
Definition: AssemblyMap.h:51
std::map< int, std::vector< PeriodicEntity > > PeriodicMap
std::map< GlobalMatrixKey, DNekScalBlkMatSharedPtr > BlockMatrixMap
A map between global matrix keys and their associated block matrices.
Definition: ExpList.h:95
static const NekDouble kNekZeroTol
std::shared_ptr< QuadGeom > QuadGeomSharedPtr
Definition: HexGeom.h:46
GeomMMF
Principle direction for MMF.
std::shared_ptr< BoundaryConditionBase > BoundaryConditionShPtr
Definition: Conditions.h:212
std::shared_ptr< PrismGeom > PrismGeomSharedPtr
Definition: PrismGeom.h:85
std::map< int, BoundaryConditionMapShPtr > BoundaryConditionCollection
Definition: Conditions.h:219
@ eDeformed
Geometry is curved or has non-constant factors.
std::shared_ptr< HexGeom > HexGeomSharedPtr
Definition: HexGeom.h:87
std::shared_ptr< SegGeom > SegGeomSharedPtr
Definition: Geometry2D.h:62
std::shared_ptr< PyrGeom > PyrGeomSharedPtr
Definition: PyrGeom.h:77
std::shared_ptr< ExpansionInfo > ExpansionInfoShPtr
Definition: MeshGraph.h:140
std::shared_ptr< TetGeom > TetGeomSharedPtr
Definition: TetGeom.h:85
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:172
std::shared_ptr< BoundaryConditionMap > BoundaryConditionMapShPtr
Definition: Conditions.h:218
std::shared_ptr< PointGeom > PointGeomSharedPtr
Definition: Geometry.h:59
std::shared_ptr< Geometry2D > Geometry2DSharedPtr
Definition: Geometry.h:65
std::shared_ptr< TriGeom > TriGeomSharedPtr
Definition: TriGeom.h:58
std::shared_ptr< Geometry1D > Geometry1DSharedPtr
Definition: Geometry.h:63
std::map< int, ExpansionInfoShPtr > ExpansionInfoMap
Definition: MeshGraph.h:143
std::map< int, CompositeSharedPtr > CompositeMap
Definition: MeshGraph.h:138
std::shared_ptr< StdExpansion > StdExpansionSharedPtr
VarCoeffMap RestrictCoeffMap(const VarCoeffMap &m, size_t offset, size_t cnt)
Definition: StdRegions.hpp:346
std::map< ConstFactorType, NekDouble > ConstFactorMap
Definition: StdRegions.hpp:399
std::map< StdRegions::VarCoeffType, VarCoeffEntry > VarCoeffMap
Definition: StdRegions.hpp:343
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
NekMatrix< NekMatrix< NekMatrix< NekDouble, StandardMatrixTag >, ScaledMatrixTag >, BlockMatrixTag > DNekScalBlkMat
Definition: NekTypeDefs.hpp:68
NekMatrix< NekMatrix< NekDouble, StandardMatrixTag >, ScaledMatrixTag > DNekScalMat
std::shared_ptr< DNekScalMat > DNekScalMatSharedPtr
std::pair< IndexType, IndexType > CoordType
std::shared_ptr< DNekScalBlkMat > DNekScalBlkMatSharedPtr
Definition: NekTypeDefs.hpp:79
@ ePOSITIVE_DEFINITE_SYMMETRIC_BANDED
@ ePOSITIVE_DEFINITE_SYMMETRIC
std::map< CoordType, NekDouble > COOMatType
static Array< OneD, NekDouble > NullNekDouble1DArray
std::shared_ptr< DNekMat > DNekMatSharedPtr
Definition: NekTypeDefs.hpp:75
double NekDouble
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:622
void Neg(int n, T *x, const int incx)
Negate x = -x.
Definition: Vmath.cpp:518
T Vsum(int n, const T *x, const int incx)
Subtract return sum(x)
Definition: Vmath.cpp:895
void Scatr(int n, const T *x, const int *y, T *z)
Scatter vector z[y[i]] = x[i].
Definition: Vmath.cpp:822
void Vadd(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Add vector z = x+y.
Definition: Vmath.cpp:359
void Smul(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha*x.
Definition: Vmath.cpp:248
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:492
T Vmax(int n, const T *x, const int incx)
Return the maximum element in x – called vmax to avoid conflict with max.
Definition: Vmath.cpp:945
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1255
void Vsub(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Subtract vector z = x-y.
Definition: Vmath.cpp:419
scalarT< T > abs(scalarT< T > in)
Definition: scalar.hpp:298
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:294
Used to lookup the create function in NekManager.
Definition: MatrixKey.h:71
std::shared_ptr< RobinBCInfo > next