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