Nektar++
DisContField1D.cpp
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // File DisContField1D.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: Field definition for 1D domain with boundary
32 // conditions using LDG-H
33 //
34 ///////////////////////////////////////////////////////////////////////////////
35 
36 #include <boost/core/ignore_unused.hpp>
37 
39 #include <StdRegions/StdSegExp.h>
42 
43 using namespace std;
44 
45 namespace Nektar
46 {
47  namespace MultiRegions
48  {
49  /**
50  * @class DisContField1D
51  * This class augments the list of local expansions inherited from
52  * ExpList1D with boundary conditions. Inter-element boundaries are
53  * handled using an discontinuous Galerkin scheme.
54  */
55 
56  /**
57  * Constructs an empty expansion list with no boundary conditions.
58  */
59  DisContField1D::DisContField1D():
60  ExpList1D(),
61  m_bndCondExpansions(),
62  m_bndConditions()
63  {
64  }
65 
66 
67  /**
68  * An expansion list for the boundary expansions is generated first for
69  * the field. These are subsequently evaluated for time zero. The trace
70  * map is then constructed.
71  * @param graph1D A mesh, containing information about the domain
72  * and the spectral/hp element expansions.
73  * @param bcs Information about the enforced boundary
74  * conditions.
75  * @param variable The session variable associated with the
76  * boundary conditions to enforce.
77  * @param solnType Type of global system to use.
78  */
82  const std::string &variable,
83  const bool SetUpJustDG,
84  const Collections::ImplementationType ImpType)
85  : ExpList1D(pSession,graph1D,true, ImpType),
88  {
89  if (variable.compare("DefaultVar") != 0)
90  {
92 
93  GenerateBoundaryConditionExpansion(graph1D,bcs,variable);
94  EvaluateBoundaryConditions(0.0, variable);
95  ApplyGeomInfo();
96  FindPeriodicVertices(bcs,variable);
97  }
98 
99  if(SetUpJustDG)
100  {
101  SetUpDG(variable);
102  }
103  else
104  {
105  int i;
106  Array<OneD, int> ElmtID, VertexID;
107  GetBoundaryToElmtMap(ElmtID, VertexID);
108 
109  for(i = 0; i < m_bndCondExpansions.num_elements(); ++i)
110  {
112  locExpList = m_bndCondExpansions[i];
113 
115  (*m_exp)[ElmtID[i]]->
116  as<LocalRegions::Expansion1D>();
118  locExpList->GetExp(0)->
119  as<LocalRegions::Expansion0D>();
120 
121  exp0d->SetAdjacentElementExp(VertexID[i], exp1d);
122  }
123 
125  }
126 
127  }
128 
129  void DisContField1D::SetUpDG(const std::string &variable)
130  {
131  // Check for multiple calls
133  {
134  return;
135  }
136 
138 
143  *m_exp,m_graph,
145 
146  m_trace = std::dynamic_pointer_cast<ExpList>(trace);
147 
149  AllocateSharedPtr(m_session, m_graph, trace, *this,
151  m_periodicVerts, variable);
152 
153  if (m_session->DefinesCmdLineArgument("verbose"))
154  {
155  m_traceMap->PrintStats(std::cout, variable);
156  }
157 
158  // Scatter trace points to 1D elements. For each element, we find
159  // the trace point associated to each vertex. The element then
160  // retains a pointer to the trace space points, to ensure
161  // uniqueness of normals when retrieving from two adjoining
162  // elements which do not lie in a plane.
163 
164  int ElmtPointGeom = 0;
165  int TracePointGeom = 0;
168  for (int i = 0; i < m_exp->size(); ++i)
169  {
170  exp1d = (*m_exp)[i]->as<LocalRegions::Expansion1D>();
171  for (int j = 0; j < exp1d->GetNverts(); ++j)
172  {
173  ElmtPointGeom = (exp1d->GetGeom1D())->GetVid(j);
174 
175  for (int k = 0; k < m_trace->GetExpSize(); ++k)
176  {
177  TracePointGeom = m_trace->GetExp(k)->GetGeom()->GetVid(0);
178 
179  if (TracePointGeom == ElmtPointGeom)
180  {
181  exp0d = m_trace->GetExp(k)->as<LocalRegions::Expansion0D>();
182  exp0d->SetAdjacentElementExp(j,exp1d);
183  break;
184  }
185  }
186  }
187  }
188 
190 
191  // Set up information for parallel and periodic problems.
192  for (int i = 0; i < m_trace->GetExpSize(); ++i)
193  {
195  m_trace->GetExp(i)->as<LocalRegions::Expansion0D>();
196 
197  int offset = m_trace->GetPhys_Offset(i);
198  int traceGeomId = traceEl->GetGeom0D()->GetGlobalID();
199  PeriodicMap::iterator pIt = m_periodicVerts.find(traceGeomId);
200 
201  if (pIt != m_periodicVerts.end() && !pIt->second[0].isLocal)
202  {
203  if (traceGeomId != min(pIt->second[0].id, traceGeomId))
204  {
205  traceEl->GetLeftAdjacentElementExp()->NegateVertexNormal(
206  traceEl->GetLeftAdjacentElementVertex());
207  }
208  }
209  else if (m_traceMap->GetTraceToUniversalMapUnique(offset) < 0)
210  {
211  traceEl->GetLeftAdjacentElementExp()->NegateVertexNormal(
212  traceEl->GetLeftAdjacentElementVertex());
213  }
214  }
215 
216  int cnt, n, e;
217 
218  // Identify boundary verts
219  for(cnt = 0, n = 0; n < m_bndCondExpansions.num_elements(); ++n)
220  {
221  if (m_bndConditions[n]->GetBoundaryConditionType() !=
223  {
224  for(e = 0; e < m_bndCondExpansions[n]->GetExpSize(); ++e)
225  {
226  m_boundaryVerts.insert(
227  m_traceMap->GetBndCondTraceToGlobalTraceMap(cnt+e));
228  }
229  }
230  cnt += m_bndCondExpansions[n]->GetExpSize();
231  }
232 
233  // Set up left-adjacent edge list.
234  m_leftAdjacentVerts.resize(2*((*m_exp).size()));
235 
236  // count size of trace
237  for (cnt = n = 0; n < m_exp->size(); ++n)
238  {
239  for (int v = 0; v < (*m_exp)[n]->GetNverts(); ++v, ++cnt)
240  {
242  }
243  }
244 
245 
246  std::unordered_map<int,pair<int,int> > perVertToExpMap;
247  for (n = 0; n < m_exp->size(); ++n)
248  {
249  for (int v = 0; v < (*m_exp)[n]->GetNverts(); ++v)
250  {
251  auto it = m_periodicVerts.find(
252  (*m_exp)[n]->GetGeom()->GetVid(v));
253 
254  if (it != m_periodicVerts.end())
255  {
256  perVertToExpMap[it->first] = make_pair(n,v);
257  }
258  }
259  }
260 
261 
262  // Set up mapping to copy Fwd of periodic bcs to Bwd of other edge.
263  for (n = 0; n < m_exp->size(); ++n)
264  {
265  for (int v = 0; v < (*m_exp)[n]->GetNverts(); ++v)
266  {
267  int vertGeomId = (*m_exp)[n]->GetGeom()->GetVid(v);
268 
269  // Check to see if this face is periodic.
270  auto it = m_periodicVerts.find(vertGeomId);
271 
272  if (it != m_periodicVerts.end())
273  {
274  const PeriodicEntity &ent = it->second[0];
275  auto it2 = perVertToExpMap.find(ent.id);
276 
277  if (it2 == perVertToExpMap.end())
278  {
279  if (m_session->GetComm()->GetRowComm()->GetSize() > 1 &&
280  !ent.isLocal)
281  {
282  continue;
283  }
284  else
285  {
286  ASSERTL1(false, "Periodic vert not found!");
287  }
288  }
289 
290  int offset = m_trace->GetPhys_Offset((m_traceMap->GetElmtToTrace())
291  [n][v]->GetElmtId());
292  m_periodicFwdCopy.push_back(offset);
293 
294  int offset2 = m_trace->GetPhys_Offset((m_traceMap->GetElmtToTrace())
295  [it2->second.first]
296  [it2->second.second]->GetElmtId());
297  m_periodicBwdCopy.push_back(offset2);
298  }
299  }
300  }
301  }
302 
303 
304  bool DisContField1D::IsLeftAdjacentVertex(const int n, const int e)
305  {
307  m_traceMap->GetElmtToTrace()[n][e]->as<LocalRegions::Expansion0D>();
308 
309  bool fwd = true;
310  if (traceEl->GetLeftAdjacentElementVertex () == -1 ||
311  traceEl->GetRightAdjacentElementVertex() == -1)
312  {
313  // Boundary edge (1 connected element). Do nothing in
314  // serial.
315  auto it = m_boundaryVerts.find(traceEl->GetElmtId());
316 
317  // If the edge does not have a boundary condition set on
318  // it, then assume it is a partition edge or periodic.
319  if (it == m_boundaryVerts.end())
320  {
321  int traceGeomId = traceEl->GetGeom0D()->GetGlobalID();
322  auto pIt = m_periodicVerts.find(traceGeomId);
323 
324  if (pIt != m_periodicVerts.end() && !pIt->second[0].isLocal)
325  {
326  fwd = traceGeomId == min(traceGeomId,pIt->second[0].id);
327  }
328  else
329  {
330  int offset = m_trace->GetPhys_Offset(traceEl->GetElmtId());
331  fwd = m_traceMap->
332  GetTraceToUniversalMapUnique(offset) >= 0;
333  }
334  }
335  }
336  else if (traceEl->GetLeftAdjacentElementVertex () != -1 &&
337  traceEl->GetRightAdjacentElementVertex() != -1)
338  {
339  // Non-boundary edge (2 connected elements).
340  fwd = (traceEl->GetLeftAdjacentElementExp().get()) == (*m_exp)[n].get();
341  }
342  else
343  {
344  ASSERTL2(false, "Unconnected trace element!");
345  }
346 
347  return fwd;
348  }
349 
350 
351  // Given all boundary regions for the whole solution determine
352  // which ones (if any) are part of domain and ensure all other
353  // conditions are given as UserDefined Dirichlet.
355  const SpatialDomains::CompositeMap &domain,
357  const std::string &variable)
358  {
360 
362 
363  map<int,int> GeometryToRegionsMap;
364 
366  = Allbcs.GetBoundaryRegions();
368  = Allbcs.GetBoundaryConditions();
369 
370  // Set up a map of all boundary regions
371  for(auto &it : bregions)
372  {
373  for (auto &bregionIt : *it.second)
374  {
375  // can assume that all regions only contain one point in 1D
376  // Really do not need loop above
377  int id = bregionIt.second->m_geomVec[0]->GetGlobalID();
378  GeometryToRegionsMap[id] = it.first;
379  }
380  }
381 
382  map<int,SpatialDomains::GeometrySharedPtr> EndOfDomain;
383 
384  // Now find out which points in domain have only one vertex
385  for(auto &domIt : domain)
386  {
387  SpatialDomains::CompositeSharedPtr geomvector = domIt.second;
388  for(int i = 0; i < geomvector->m_geomVec.size(); ++i)
389  {
390  for(int j = 0; j < 2; ++j)
391  {
392  int vid = geomvector->m_geomVec[i]->GetVid(j);
393  if(EndOfDomain.count(vid) == 0)
394  {
395  EndOfDomain[vid] = geomvector->m_geomVec[i]->GetVertex(j);
396  }
397  else
398  {
399  EndOfDomain.erase(vid);
400  }
401  }
402  }
403  }
404  ASSERTL1(EndOfDomain.size() == 2,"Did not find two ends of domain");
405 
406  int numNewBc = 1;
407  for(auto &regIt : EndOfDomain)
408  {
409  if(GeometryToRegionsMap.count(regIt.first) != 0)
410  {
411  // Set up boundary condition up
412  auto iter = GeometryToRegionsMap.find(regIt.first);
413  ASSERTL1(iter != GeometryToRegionsMap.end(),
414  "Failied to find GeometryToRegionMap");
415 
416  int regionId = iter->second;
417  auto bregionsIter = bregions.find(regionId);
418  ASSERTL1(bregionsIter != bregions.end(),
419  "Failed to find boundary region");
420 
422  bregionsIter->second;
423  returnval->AddBoundaryRegions(regionId, breg);
424 
425  auto bconditionsIter = bconditions.find(regionId);
426  ASSERTL1(bconditionsIter != bconditions.end(),
427  "Failed to find boundary collection");
428 
430  bconditionsIter->second;
431  returnval->AddBoundaryConditions(regionId,bcond);
432  }
433  else // Set up an undefined region.
434  {
436 
437  // Set up Composite (GemetryVector) to contain vertex and put into bRegion
441  gvec->m_geomVec.push_back(regIt.second);
442  (*breg)[regIt.first] = gvec;
443 
444  returnval->AddBoundaryRegions(bregions.size()+numNewBc,breg);
445 
447 
448  // Set up just boundary condition for this variable.
450  (*bCondition)[variable] = notDefinedCondition;
451 
452  returnval->AddBoundaryConditions(bregions.size()+numNewBc,bCondition);
453  ++numNewBc;
454 
455  }
456  }
457 
458  return returnval;
459  }
460 
461  /**
462  * Constructor for use in multidomain computations where a
463  * domain list can be passed instead of graph1D
464  *
465  * @param domain Subdomain specified in the inputfile from
466  * which the DisContField1D is set up
467  */
469  const LibUtilities::SessionReaderSharedPtr &pSession,
470  const SpatialDomains::MeshGraphSharedPtr &graph1D,
471  const SpatialDomains::CompositeMap &domain,
472  const SpatialDomains::BoundaryConditions &Allbcs,
473  const std::string &variable,
474  bool SetToOneSpaceDimension,
475  const Collections::ImplementationType ImpType):
476  ExpList1D(pSession,graph1D,domain, true,variable,SetToOneSpaceDimension,ImpType),
479  {
480  if (variable.compare("DefaultVar") != 0)
481  {
482  SpatialDomains::BoundaryConditionsSharedPtr DomBCs = GetDomainBCs(domain,Allbcs,variable);
483 
485  EvaluateBoundaryConditions(0.0, variable);
486  ApplyGeomInfo();
487  FindPeriodicVertices(*DomBCs,variable);
488  }
489 
490  SetUpDG(variable);
491  }
492 
493  /**
494  * Constructs a field as a copy of an existing field.
495  * @param In Existing DisContField1D object to copy.
496  */
498  ExpList1D(In),
502  m_trace(In.m_trace),
509  {
510  }
511 
512 
513  /**
514  * Constructs a field as a copy of an existing explist1D field.
515  * @param In Existing ExpList1D object to copy.
516  */
518  ExpList1D(In)
519  {
520  }
521 
522  /**
523  *
524  */
526  {
527  }
528 
529 
530  /**
531  * Generate the boundary condition expansion list
532  * @param graph1D A mesh, containing information about the domain
533  * and the spectral/hp element expansions.
534  * @param bcs Information about the enforced boundary
535  * conditions.
536  * @param variable The session variable associated with the
537  * boundary conditions to enforce.
538  */
540  const SpatialDomains::MeshGraphSharedPtr &graph1D,
542  const std::string variable)
543  {
544  int cnt = 0;
545 
547  = bcs.GetBoundaryRegions();
549  = bcs.GetBoundaryConditions();
550 
551  // count the number of non-periodic boundary points
552  for (auto &it : bregions)
553  {
554  const SpatialDomains::BoundaryConditionShPtr boundaryCondition =
555  GetBoundaryCondition(bconditions, it.first, variable);
556  SpatialDomains::BoundaryRegion::iterator bregionIt;
557  for (auto &bregionIt : *(it.second))
558  {
559  cnt += bregionIt.second->m_geomVec.size();
560  }
561  }
562 
567 
568  SetBoundaryConditionExpansion(graph1D,bcs,variable,
570  m_bndConditions);
571  }
572 
573 
574  /**
575  * @param graph1D A mesh containing information about the domain
576  * and the spectral/hp element expansion.
577  * @param bcs Information about the boundary conditions.
578  * @param variable Specifies the field.
579  * @param periodicVertices Map into which the list of periodic
580  * vertices is placed.
581  */
584  const std::string variable)
585  {
587  = bcs.GetBoundaryRegions();
589  = bcs.GetBoundaryConditions();
590 
592  m_session->GetComm()->GetRowComm();
593 
594  int i, region1ID, region2ID;
595 
597 
598  map<int,int> BregionToVertMap;
599 
600  // Construct list of all periodic Region and their global vertex on
601  // this process.
602  for (auto &it : bregions)
603  {
604  locBCond = GetBoundaryCondition(bconditions, it.first, variable);
605 
606  if (locBCond->GetBoundaryConditionType()
608  {
609  continue;
610  }
611  int id = it.second->begin()->second->m_geomVec[0]->GetGlobalID();
612 
613  BregionToVertMap[it.first] = id;
614  }
615 
616  set<int> islocal;
617 
618  int n = vComm->GetSize();
619  int p = vComm->GetRank();
620 
621  Array<OneD, int> nregions(n, 0);
622  nregions[p] = BregionToVertMap.size();
623  vComm->AllReduce(nregions, LibUtilities::ReduceSum);
624 
625  int totRegions = Vmath::Vsum(n, nregions, 1);
626 
627  Array<OneD, int> regOffset(n, 0);
628 
629  for (i = 1; i < n; ++i)
630  {
631  regOffset[i] = regOffset[i-1] + nregions[i-1];
632  }
633 
634  Array<OneD, int> bregmap(totRegions, 0);
635  Array<OneD, int> bregid (totRegions, 0);
636 
637  i = regOffset[p];
638  for (auto &iit : BregionToVertMap)
639  {
640  bregid [i ] = iit.first;
641  bregmap[i++] = iit.second;
642  islocal.insert(iit.first);
643  }
644 
645  vComm->AllReduce(bregmap, LibUtilities::ReduceSum);
646  vComm->AllReduce(bregid, LibUtilities::ReduceSum);
647 
648  for (int i = 0; i < totRegions; ++i)
649  {
650  BregionToVertMap[bregid[i]] = bregmap[i];
651  }
652 
653  // Construct list of all periodic pairs local to this process.
654  for (auto &it : bregions)
655  {
656  locBCond = GetBoundaryCondition(bconditions, it.first, variable);
657 
658  if (locBCond->GetBoundaryConditionType()
660  {
661  continue;
662  }
663 
664  // Identify periodic boundary region IDs.
665  region1ID = it.first;
666  region2ID = std::static_pointer_cast<
668  locBCond)->m_connectedBoundaryRegion;
669 
670  ASSERTL0(BregionToVertMap.count(region1ID) != 0,
671  "Cannot determine vertex of region1ID");
672 
673  ASSERTL0(BregionToVertMap.count(region2ID) != 0,
674  "Cannot determine vertex of region2ID");
675 
676  PeriodicEntity ent(BregionToVertMap[region2ID],
678  islocal.count(region2ID) != 0);
679 
680  m_periodicVerts[BregionToVertMap[region1ID]].push_back(ent);
681  }
682  }
683 
684 
685  /**
686  * @param graph1D A mesh containing information about the domain
687  * and the Spectral/hp element expansion.
688  * @param bcs Information about the boundary conditions.
689  * @param variable Specifies the field.
690  * @param bndCondExpansions Array of ExpList1D objects each
691  * containing a 1D spectral/hp element expansion
692  * on a single boundary region.
693  * @param bncConditions Array of BoundaryCondition objects which
694  * contain information about the boundary
695  * conditions on the different boundary regions.
696  */
698  const SpatialDomains::MeshGraphSharedPtr &graph1D,
700  const std::string variable,
702  &bndCondExpansions,
703  Array<OneD, SpatialDomains
704  ::BoundaryConditionShPtr> &bndConditions)
705  {
706  boost::ignore_unused(graph1D);
707 
708  int k;
709  int cnt = 0;
710 
712  = bcs.GetBoundaryRegions();
714  = bcs.GetBoundaryConditions();
715 
719 
720  cnt = 0;
721  for (auto &it : bregions)
722  {
723  locBCond = GetBoundaryCondition(bconditions, it.first, variable);
724 
725  for (auto &bregionIt : *(it.second))
726  {
727  for (k = 0; k < bregionIt.second->m_geomVec.size(); k++)
728  {
729  if((vert = std::dynamic_pointer_cast
731  bregionIt.second->m_geomVec[k])))
732  {
733  locPointExp
736  bndCondExpansions[cnt] = locPointExp;
737  bndConditions[cnt++] = locBCond;
738  }
739  else
740  {
741  ASSERTL0(false,
742  "dynamic cast to a vertex failed");
743  }
744  }
745  }
746  }
747  }
748 
749  /**
750  *
751  */
753  const GlobalLinSysKey &mkey)
754  {
756  "Routine currently only tested for HybridDGHelmholtz");
757 
759  "Full matrix global systems are not supported for HDG "
760  "expansions");
761 
763  ==m_traceMap->GetGlobalSysSolnType(),
764  "The local to global map is not set up for the requested "
765  "solution type");
766 
767  GlobalLinSysSharedPtr glo_matrix;
768  auto matrixIter = m_globalBndMat->find(mkey);
769 
770  if (matrixIter == m_globalBndMat->end())
771  {
772  glo_matrix = GenGlobalBndLinSys(mkey,m_traceMap);
773  (*m_globalBndMat)[mkey] = glo_matrix;
774  }
775  else
776  {
777  glo_matrix = matrixIter->second;
778  }
779 
780  return glo_matrix;
781  }
782 
783 
785  {
786  if(m_negatedFluxNormal.size() == 0)
787  {
789  &elmtToTrace = m_traceMap->GetElmtToTrace();
790 
791  m_negatedFluxNormal.resize(2*GetExpSize());
792 
793  for(int i = 0; i < GetExpSize(); ++i)
794  {
795 
796  for(int v = 0; v < 2; ++v)
797  {
798 
800  elmtToTrace[i][v]->as<LocalRegions::Expansion0D>();
801 
802  if(vertExp->GetLeftAdjacentElementExp()->GetGeom()->GetGlobalID() != (*m_exp)[i]->GetGeom()->GetGlobalID())
803  {
804  m_negatedFluxNormal[2*i+v] = true;
805  }
806  else
807  {
808  m_negatedFluxNormal[2*i+v] = false;
809  }
810 
811  if(vertExp->GetLeftAdjacentElementExp()->
812  VertexNormalNegated(vertExp->GetLeftAdjacentElementVertex()))
813  {
814  m_negatedFluxNormal[2*i+v] =
815  (!m_negatedFluxNormal[2*i+v]);
816  }
817  }
818  }
819 
820  }
821 
822  return m_negatedFluxNormal;
823  }
824 
825  /**
826  * Generate the forward or backward state for each trace point.
827  * @param Fwd Forward state.
828  * @param Bwd Backward state.
829  */
832  {
833  v_GetFwdBwdTracePhys(m_phys,Fwd,Bwd);
834  }
835 
836 
837  /**
838  * @brief This method extracts the "forward" and "backward" trace data
839  * from the array @a field and puts the data into output vectors @a Fwd
840  * and @a Bwd.
841  *
842  * We first define the convention which defines "forwards" and
843  * "backwards". First an association is made between the vertex of each
844  * element and its corresponding vertex in the trace space using the
845  * mapping #m_traceMap. The element can either be left-adjacent or
846  * right-adjacent to this trace edge (see
847  * Expansion0D::GetLeftAdjacentElementExp). Boundary edges are never
848  * left-adjacent since elemental left-adjacency is populated first.
849  *
850  * If the element is left-adjacent we extract the vertex trace data from
851  * @a field into the forward trace space @a Fwd; otherwise, we place it
852  * in the backwards trace space @a Bwd. In this way, we form a unique
853  * set of trace normals since these are always extracted from
854  * left-adjacent elements.
855  *
856  * @param field is a NekDouble array which contains the 1D data
857  * from which we wish to extract the backward and forward
858  * orientated trace/edge arrays.
859  * @param Fwd The resulting forwards space.
860  * @param Bwd The resulting backwards space.
861  */
862 
864  const Array<OneD, const NekDouble> &field,
867  {
868  // Counter variables
869  int n, v;
870 
871  // Number of elements
872  int nElements = GetExpSize();
873 
874  // Initial index of each element
875  int phys_offset;
876 
878  &elmtToTrace = m_traceMap->GetElmtToTrace();
879 
880  // Set forward and backard state to zero
881  Vmath::Zero(Fwd.num_elements(), Fwd, 1);
882  Vmath::Zero(Bwd.num_elements(), Bwd, 1);
883 
884  int cnt;
885 
886  // Loop on the elements
887  for (cnt = n = 0; n < nElements; ++n)
888  {
889  // Set the offset of each element
890  phys_offset = GetPhys_Offset(n);
891 
892  for(v = 0; v < 2; ++v, ++cnt)
893  {
894  int offset = m_trace->GetPhys_Offset(elmtToTrace[n][v]->GetElmtId());
895 
896  if (m_leftAdjacentVerts[cnt])
897  {
898  (*m_exp)[n]->GetVertexPhysVals(v, field + phys_offset,
899  Fwd[offset]);
900  }
901  else
902  {
903  (*m_exp)[n]->GetVertexPhysVals(v, field + phys_offset,
904  Bwd[offset]);
905  }
906  }
907  }
908 
909  // Fill boundary conditions into missing elements.
910  int id = 0;
911 
912  for(cnt = n = 0; n < m_bndCondExpansions.num_elements(); ++n)
913  {
914  if (m_bndConditions[n]->GetBoundaryConditionType() ==
916  {
917  id = m_trace->GetPhys_Offset(m_traceMap->GetBndCondTraceToGlobalTraceMap(cnt));
918  Bwd[id] = m_bndCondExpansions[n]->GetPhys()[0]; //this is not getting the correct value?
919  cnt++;
920  }
921  else if (m_bndConditions[n]->GetBoundaryConditionType() ==
923  m_bndConditions[n]->GetBoundaryConditionType() ==
925  {
926  ASSERTL0((m_bndCondExpansions[n]->GetPhys())[0]==0.0,
927  "Method not set up for non-zero Neumann "
928  "boundary condition");
929  id = m_trace->GetPhys_Offset(m_traceMap->GetBndCondTraceToGlobalTraceMap(cnt));
930  Bwd[id] = Fwd[id];
931 
932  cnt++;
933  }
934  else if (m_bndConditions[n]->GetBoundaryConditionType() ==
936  {
937  // Do nothing
938  }
939  else if (m_bndConditions[n]->GetBoundaryConditionType() !=
941  {
942  ASSERTL0(false,
943  "Method not set up for this boundary condition.");
944  }
945  }
946 
947  // Copy any periodic boundary conditions.
948  for (n = 0; n < m_periodicFwdCopy.size(); ++n)
949  {
950  Bwd[m_periodicBwdCopy[n]] = Fwd[m_periodicFwdCopy[n]];
951  }
952 
953  // Do parallel exchange for forwards/backwards spaces.
954  m_traceMap->UniversalTraceAssemble(Fwd);
955  m_traceMap->UniversalTraceAssemble(Bwd);
956 
957  }
958 
959 
961  Array<OneD, NekDouble> &outarray)
962  {
963  ASSERTL1(m_physState == true,"local physical space is not true ");
964  v_ExtractTracePhys(m_phys, outarray);
965  }
966 
967  /**
968  * @brief This method extracts the trace (verts in 1D) from the field @a
969  * inarray and puts the values in @a outarray.
970  *
971  * It assumes the field is C0 continuous so that it can overwrite the
972  * edge data when visited by the two adjacent elements.
973  *
974  * @param inarray An array containing the 1D data from which we wish
975  * to extract the edge data.
976  * @param outarray The resulting edge information.
977  *
978  * This will not work for non-boundary expansions
979  */
981  const Array<OneD, const NekDouble> &inarray,
982  Array<OneD, NekDouble> &outarray)
983  {
984  // Loop over elemente and collect forward expansion
985  int nexp = GetExpSize();
986  int n,p,offset,phys_offset;
987 
988  ASSERTL1(outarray.num_elements() >= m_trace->GetExpSize(),
989  "input array is of insufficient length");
990 
991  for (n = 0; n < nexp; ++n)
992  {
993  phys_offset = GetPhys_Offset(n);
994 
995  for (p = 0; p < (*m_exp)[n]->GetNverts(); ++p)
996  {
997  offset = m_trace->GetPhys_Offset(
998  (m_traceMap->GetElmtToTrace())[n][p]->GetElmtId());
999  (*m_exp)[n]->GetVertexPhysVals(p, inarray + phys_offset,
1000  outarray[offset]);
1001  }
1002  }
1003  }
1004 
1006  const Array<OneD, const NekDouble> &Fn,
1007  Array<OneD, NekDouble> &outarray)
1008  {
1009  int n,offset, t_offset;
1010 
1012  &elmtToTrace = m_traceMap->GetElmtToTrace();
1013 
1014  vector<bool> negatedFluxNormal = GetNegatedFluxNormal();
1015 
1016  for (n = 0; n < GetExpSize(); ++n)
1017  {
1018  // Number of coefficients on each element
1019  int e_ncoeffs = (*m_exp)[n]->GetNcoeffs();
1020 
1021  offset = GetCoeff_Offset(n);
1022 
1023  // Implementation for every points except Gauss points
1024  if ((*m_exp)[n]->GetBasis(0)->GetBasisType() !=
1026  {
1027  t_offset = GetTrace()->GetCoeff_Offset(elmtToTrace[n][0]->GetElmtId());
1028  if(negatedFluxNormal[2*n])
1029  {
1030  outarray[offset] -= Fn[t_offset];
1031  }
1032  else
1033  {
1034  outarray[offset] += Fn[t_offset];
1035  }
1036 
1037  t_offset = GetTrace()->GetCoeff_Offset(elmtToTrace[n][1]->GetElmtId());
1038 
1039  if(negatedFluxNormal[2*n+1])
1040  {
1041  outarray[offset+(*m_exp)[n]->GetVertexMap(1)] -= Fn[t_offset];
1042  }
1043  else
1044  {
1045  outarray[offset+(*m_exp)[n]->GetVertexMap(1)] += Fn[t_offset];
1046  }
1047 
1048  }
1049  else
1050  {
1051 #if 0
1052  DNekMatSharedPtr m_Ixm;
1055  BS_p(e_ncoeffs,LibUtilities::eGaussGaussLegendre);
1057  BS_k(LibUtilities::eGauss_Lagrange,e_ncoeffs,BS_p);
1058 
1059  BASE = LibUtilities::BasisManager()[BS_k];
1060 
1061  Array<OneD, NekDouble> coords(3, 0.0);
1062 
1063  int j;
1064 
1065  for(p = 0; p < 2; ++p)
1066  {
1067  NekDouble vertnorm = 0.0;
1068  for (int i=0; i<((*m_exp)[n]->
1069  GetVertexNormal(p)).num_elements(); i++)
1070  {
1071  vertnorm += ((*m_exp)[n]->GetVertexNormal(p))[i][0];
1072  coords[0] = vertnorm ;
1073  }
1074 
1075  t_offset = GetTrace()->GetPhys_Offset(n+p);
1076 
1077  if (vertnorm >= 0.0)
1078  {
1079  m_Ixm = BASE->GetI(coords);
1080 
1081 
1082  for (j = 0; j < e_ncoeffs; j++)
1083  {
1084  outarray[offset + j] +=
1085  (m_Ixm->GetPtr())[j] * Fn[t_offset];
1086  }
1087  }
1088 
1089  if (vertnorm < 0.0)
1090  {
1091  m_Ixm = BASE->GetI(coords);
1092 
1093  for (j = 0; j < e_ncoeffs; j++)
1094  {
1095  outarray[offset + j] -=
1096  (m_Ixm->GetPtr())[j] * Fn[t_offset];
1097  }
1098  }
1099  }
1100 #else
1101  int j;
1102  static DNekMatSharedPtr m_Ixm, m_Ixp;
1103  static int sav_ncoeffs = 0;
1104  if(!m_Ixm.get() || e_ncoeffs != sav_ncoeffs)
1105  {
1108  BS_p(e_ncoeffs,LibUtilities::eGaussGaussLegendre);
1110  BS_k(LibUtilities::eGauss_Lagrange,e_ncoeffs,BS_p);
1111 
1112  BASE = LibUtilities::BasisManager()[BS_k];
1113 
1114  Array<OneD, NekDouble> coords(1, 0.0);
1115 
1116  coords[0] = -1.0;
1117  m_Ixm = BASE->GetI(coords);
1118 
1119  coords[0] = 1.0;
1120  m_Ixp = BASE->GetI(coords);
1121 
1122  sav_ncoeffs = e_ncoeffs;
1123  }
1124 
1125  t_offset = GetTrace()->GetCoeff_Offset(elmtToTrace[n][0]->GetElmtId());
1126  if(negatedFluxNormal[2*n])
1127  {
1128  for (j = 0; j < e_ncoeffs; j++)
1129  {
1130  outarray[offset + j] -=
1131  (m_Ixm->GetPtr())[j] * Fn[t_offset];
1132  }
1133  }
1134  else
1135  {
1136  for (j = 0; j < e_ncoeffs; j++)
1137  {
1138  outarray[offset + j] +=
1139  (m_Ixm->GetPtr())[j] * Fn[t_offset];
1140  }
1141  }
1142 
1143  t_offset = GetTrace()->GetCoeff_Offset(elmtToTrace[n][1]->GetElmtId());
1144  if (negatedFluxNormal[2*n+1])
1145  {
1146  for (j = 0; j < e_ncoeffs; j++)
1147  {
1148  outarray[offset + j] -=
1149  (m_Ixp->GetPtr())[j] * Fn[t_offset];
1150  }
1151  }
1152  else
1153  {
1154  for (j = 0; j < e_ncoeffs; j++)
1155  {
1156  outarray[offset + j] +=
1157  (m_Ixp->GetPtr())[j] * Fn[t_offset];
1158  }
1159  }
1160 #endif
1161  }
1162  }
1163  }
1164 
1165 
1167  const Array<OneD, const NekDouble> &inarray,
1168  Array<OneD, NekDouble> &outarray,
1169  const FlagList &flags,
1170  const StdRegions::ConstFactorMap &factors,
1171  const StdRegions::VarCoeffMap &varcoeff,
1172  const MultiRegions::VarFactorsMap &varfactors,
1173  const Array<OneD, const NekDouble> &dirForcing,
1174  const bool PhysSpaceForcing)
1175  {
1176  boost::ignore_unused(flags, varfactors, dirForcing);
1177 
1178  int i,n,cnt,nbndry;
1179  int nexp = GetExpSize();
1181  DNekVec F(m_ncoeffs,f,eWrapper);
1182  Array<OneD,NekDouble> e_f, e_l;
1183 
1184  //----------------------------------
1185  // Setup RHS Inner product if required
1186  //----------------------------------
1187  if(PhysSpaceForcing)
1188  {
1189  IProductWRTBase(inarray,f);
1190  Vmath::Neg(m_ncoeffs,f,1);
1191  }
1192  else
1193  {
1194  Vmath::Smul(m_ncoeffs,-1.0,inarray,1,f,1);
1195  }
1196 
1197  //----------------------------------
1198  // Solve continuous Boundary System
1199  //----------------------------------
1200  int GloBndDofs = m_traceMap->GetNumGlobalBndCoeffs();
1201  int NumDirBCs = m_traceMap->GetNumLocalDirBndCoeffs();
1202  int e_ncoeffs,id;
1203 
1204  GlobalMatrixKey HDGLamToUKey(
1207  factors,
1208  varcoeff);
1209 
1210  const DNekScalBlkMatSharedPtr &HDGLamToU =
1211  GetBlockMatrix(HDGLamToUKey);
1212 
1213  // Retrieve global trace space storage, \Lambda, from trace expansion
1215  (m_traceMap->GetNumLocalBndCoeffs());
1216 
1217 
1218  Array<OneD,NekDouble> BndRhs(GloBndDofs,0.0);
1219  // Zero trace space
1220  Vmath::Zero(GloBndDofs,BndSol,1);
1221 
1222  int LocBndCoeffs = m_traceMap->GetNumLocalBndCoeffs();
1223  Array<OneD, NekDouble> loc_lambda(LocBndCoeffs);
1224  DNekVec LocLambda(LocBndCoeffs,loc_lambda,eWrapper);
1225 
1226  //----------------------------------
1227  // Evaluate Trace Forcing
1228  //----------------------------------
1229  // Determing <u_lam,f> terms using HDGLamToU matrix
1230  for (cnt = n = 0; n < nexp; ++n)
1231  {
1232  nbndry = (*m_exp)[n]->NumDGBndryCoeffs();
1233 
1234  e_ncoeffs = (*m_exp)[n]->GetNcoeffs();
1235  e_f = f+m_coeff_offset[n];
1236  e_l = loc_lambda + cnt;
1237 
1238  // use outarray as tmp space
1239  DNekVec Floc (nbndry, e_l, eWrapper);
1240  DNekVec ElmtFce (e_ncoeffs, e_f, eWrapper);
1241  Floc = Transpose(*(HDGLamToU->GetBlock(n,n)))*ElmtFce;
1242 
1243  cnt += nbndry;
1244  }
1245 
1246  // Assemble into global operator
1247  m_traceMap->AssembleBnd(loc_lambda,BndRhs);
1248 
1249  cnt = 0;
1250  // Copy Dirichlet boundary conditions into trace space
1251  for (i = 0; i < m_bndCondExpansions.num_elements(); ++i)
1252  {
1253  if (m_bndConditions[i]->GetBoundaryConditionType() ==
1255  {
1256  id = m_traceMap->GetBndCondCoeffsToGlobalCoeffsMap(i);
1257  BndSol[id] = m_bndCondExpansions[i]->GetCoeff(0);
1258  }
1259  else if (m_bndConditions[i]->GetBoundaryConditionType() ==
1261  m_bndConditions[i]->GetBoundaryConditionType() ==
1263  {
1264  id = m_traceMap->GetBndCondCoeffsToGlobalCoeffsMap(i);
1265  BndRhs[id] += m_bndCondExpansions[i]->GetCoeff(0);
1266  }
1267  else if (m_bndConditions[i]->GetBoundaryConditionType() ==
1269  {
1270  ASSERTL0(false, "HDG implementation does not support "
1271  "periodic boundary conditions at present.");
1272  }
1273  }
1274 
1275  //----------------------------------
1276  // Solve trace problem
1277  //----------------------------------
1278  if (GloBndDofs - NumDirBCs > 0)
1279  {
1281  m_traceMap,factors);
1283  LinSys->Solve(BndRhs,BndSol,m_traceMap);
1284  }
1285 
1286  //----------------------------------
1287  // Internal element solves
1288  //----------------------------------
1291  factors);
1292 
1293  const DNekScalBlkMatSharedPtr& InvHDGHelm =
1294  GetBlockMatrix(invHDGhelmkey);
1295  DNekVec out(m_ncoeffs,outarray,eWrapper);
1296  Vmath::Zero(m_ncoeffs,outarray,1);
1297 
1298  // get local trace solution from BndSol
1299  m_traceMap->GlobalToLocalBnd(BndSol,loc_lambda);
1300 
1301  // out = u_f + u_lam = (*InvHDGHelm)*f + (LamtoU)*Lam
1302  out = (*InvHDGHelm)*F + (*HDGLamToU)*LocLambda;
1303  }
1304 
1305  /**
1306  * Based on the expression \f$g(x,t)\f$ for the boundary conditions,
1307  * this function evaluates the boundary conditions for all boundaries
1308  * at time-level \a t.
1309  * @param time The time at which the boundary conditions
1310  * should be evaluated.
1311  * @param bndCondExpansions List of boundary expansions.
1312  * @param bndConditions Information about the boundary conditions.
1313  */
1315  const NekDouble time,
1316  const std::string varName,
1317  const NekDouble x2_in,
1318  const NekDouble x3_in)
1319  {
1320  boost::ignore_unused(varName);
1321 
1322  int i;
1323 
1324  Array<OneD, NekDouble> x0(1);
1325  Array<OneD, NekDouble> x1(1);
1326  Array<OneD, NekDouble> x2(1);
1327 
1328  for (i = 0; i < m_bndCondExpansions.num_elements(); ++i)
1329  {
1330  if (time == 0.0 || m_bndConditions[i]->IsTimeDependent())
1331  {
1332  m_bndCondExpansions[i]->GetCoords(x0, x1, x2);
1333 
1334  if (x2_in != NekConstants::kNekUnsetDouble && x3_in !=
1336  {
1337  x1[0] = x2_in;
1338  x2[0] = x3_in;
1339  }
1340 
1341  if (m_bndConditions[i]->GetBoundaryConditionType() ==
1343  {
1344  m_bndCondExpansions[i]->SetCoeff(0,
1345  (std::static_pointer_cast<SpatialDomains
1346  ::DirichletBoundaryCondition>(m_bndConditions[i])
1347  ->m_dirichletCondition).Evaluate(x0[0],x1[0],x2[0],time));
1348  m_bndCondExpansions[i]->SetPhys(0,m_bndCondExpansions[i]->GetCoeff(0));
1349  }
1350  else if (m_bndConditions[i]->GetBoundaryConditionType()
1352  {
1353  m_bndCondExpansions[i]->SetCoeff(0,
1354  (std::static_pointer_cast<SpatialDomains
1355  ::NeumannBoundaryCondition>(m_bndConditions[i])
1356  ->m_neumannCondition).Evaluate(x0[0],x1[0],x2[0],time));
1357  }
1358  else if (m_bndConditions[i]->GetBoundaryConditionType()
1360  {
1361  m_bndCondExpansions[i]->SetCoeff(0,
1362  (std::static_pointer_cast<SpatialDomains
1363  ::RobinBoundaryCondition>(m_bndConditions[i])
1364  ->m_robinFunction).Evaluate(x0[0],x1[0],x2[0],time));
1365 
1366  }
1367  else if (m_bndConditions[i]->GetBoundaryConditionType()
1369  {
1370  continue;
1371  }
1372  else if (m_bndConditions[i]->GetBoundaryConditionType()
1374  {
1375  }
1376  else
1377  {
1378  ASSERTL0(false, "This type of BC not implemented yet");
1379  }
1380  }
1381  }
1382  }
1383 
1384  // Set up a list of element ids and edge ids that link to the
1385  // boundary conditions
1387  Array<OneD, int> &ElmtID, Array<OneD,int> &VertID)
1388  {
1389  map<int, int> VertGID;
1390  int i,n,id;
1391  int bid,cnt,Vid;
1392  int nbcs = m_bndConditions.num_elements();
1393 
1394  // make sure arrays are of sufficient length
1395  if (ElmtID.num_elements() != nbcs)
1396  {
1397  ElmtID = Array<OneD, int>(nbcs,-1);
1398  }
1399  else
1400  {
1401  fill(ElmtID.get(), ElmtID.get()+nbcs, -1);
1402  }
1403 
1404  if (VertID.num_elements() != nbcs)
1405  {
1406  VertID = Array<OneD, int>(nbcs);
1407  }
1408 
1409  // setup map of all global ids along boundary
1410  for (cnt = n = 0; n < m_bndCondExpansions.num_elements(); ++n)
1411  {
1412  Vid = m_bndCondExpansions[n]->GetExp(0)->GetGeom()->GetVertex(0)->GetVid();
1413  VertGID[Vid] = cnt++;
1414  }
1415 
1416  // Loop over elements and find verts that match;
1418  for(cnt = n = 0; n < GetExpSize(); ++n)
1419  {
1420  exp = (*m_exp)[n];
1421  for(i = 0; i < exp->GetNverts(); ++i)
1422  {
1423  id = exp->GetGeom()->GetVid(i);
1424 
1425  if (VertGID.count(id) > 0)
1426  {
1427  bid = VertGID.find(id)->second;
1428  ASSERTL1(ElmtID[bid] == -1,"Edge already set");
1429  ElmtID[bid] = n;
1430  VertID[bid] = i;
1431  cnt ++;
1432  }
1433  }
1434  }
1435 
1436  ASSERTL1(cnt == nbcs,"Failed to visit all boundary condtiions");
1437  }
1438 
1440  std::shared_ptr<ExpList> &result,
1441  const bool DeclareCoeffPhysArrays)
1442  {
1443  int n, cnt, nq;
1444  int offsetOld, offsetNew;
1445  std::vector<unsigned int> eIDs;
1446 
1447  Array<OneD, int> ElmtID,EdgeID;
1448  GetBoundaryToElmtMap(ElmtID,EdgeID);
1449 
1450  // Skip other boundary regions
1451  for (cnt = n = 0; n < i; ++n)
1452  {
1453  cnt += m_bndCondExpansions[n]->GetExpSize();
1454  }
1455 
1456  // Populate eIDs with information from BoundaryToElmtMap
1457  for (n = 0; n < m_bndCondExpansions[i]->GetExpSize(); ++n)
1458  {
1459  eIDs.push_back(ElmtID[cnt+n]);
1460  }
1461 
1462  // Create expansion list
1463  result =
1465  (*this, eIDs, DeclareCoeffPhysArrays);
1466 
1467  // Copy phys and coeffs to new explist
1468  if( DeclareCoeffPhysArrays)
1469  {
1470  Array<OneD, NekDouble> tmp1, tmp2;
1471  for (n = 0; n < result->GetExpSize(); ++n)
1472  {
1473  nq = GetExp(ElmtID[cnt+n])->GetTotPoints();
1474  offsetOld = GetPhys_Offset(ElmtID[cnt+n]);
1475  offsetNew = result->GetPhys_Offset(n);
1476  Vmath::Vcopy(nq, tmp1 = GetPhys()+ offsetOld, 1,
1477  tmp2 = result->UpdatePhys()+ offsetNew, 1);
1478 
1479  nq = GetExp(ElmtID[cnt+n])->GetNcoeffs();
1480  offsetOld = GetCoeff_Offset(ElmtID[cnt+n]);
1481  offsetNew = result->GetCoeff_Offset(n);
1482  Vmath::Vcopy(nq, tmp1 = GetCoeffs()+ offsetOld, 1,
1483  tmp2 = result->UpdateCoeffs()+ offsetNew, 1);
1484  }
1485  }
1486  }
1487 
1488  /**
1489  * @brief Reset this field, so that geometry information can be updated.
1490  */
1492  {
1493  ExpList::v_Reset();
1494 
1495  // Reset boundary condition expansions.
1496  for (int n = 0; n < m_bndCondExpansions.num_elements(); ++n)
1497  {
1498  m_bndCondExpansions[n]->Reset();
1499  }
1500  }
1501 
1502  /**
1503  * Search through the edge expansions and identify which ones
1504  * have Robin/Mixed type boundary conditions. If find a Robin
1505  * boundary then store the edge id of the boundary condition
1506  * and the array of points of the physical space boundary
1507  * condition which are hold the boundary condition primitive
1508  * variable coefficient at the quatrature points
1509  *
1510  * \return std map containing the robin boundary condition
1511  * info using a key of the element id
1512  *
1513  * There is a next member to allow for more than one Robin
1514  * boundary condition per element
1515  */
1516  map<int, RobinBCInfoSharedPtr> DisContField1D::v_GetRobinBCInfo(void)
1517  {
1518  int i;
1519  map<int, RobinBCInfoSharedPtr> returnval;
1520  Array<OneD, int> ElmtID,VertID;
1521  GetBoundaryToElmtMap(ElmtID,VertID);
1522 
1523  for (i = 0; i < m_bndCondExpansions.num_elements(); ++i)
1524  {
1525  if (m_bndConditions[i]->GetBoundaryConditionType() ==
1527  {
1528  int elmtid;
1529 
1530  Array<OneD, NekDouble> x0(1);
1531  Array<OneD, NekDouble> x1(1);
1532  Array<OneD, NekDouble> x2(1);
1533  Array<OneD, NekDouble> coeffphys(1);
1534 
1535  m_bndCondExpansions[i]->GetCoords(x0, x1, x2);
1536 
1537  coeffphys[0] = (std::static_pointer_cast<SpatialDomains
1538  ::RobinBoundaryCondition>(m_bndConditions[i])
1539  ->m_robinPrimitiveCoeff).Evaluate(x0[0],x1[0],x2[0],0.0);
1540 
1541  RobinBCInfoSharedPtr rInfo =
1543  AllocateSharedPtr(VertID[i],coeffphys);
1544 
1545  elmtid = ElmtID[i];
1546  // make link list if necessary (not likely in
1547  // 1D but needed in 2D & 3D)
1548  if(returnval.count(elmtid) != 0)
1549  {
1550  rInfo->next = returnval.find(elmtid)->second;
1551  }
1552  returnval[elmtid] = rInfo;
1553  }
1554  }
1555 
1556  return returnval;
1557  }
1558  } // end of namespace
1559 } //end of namespace
const Array< OneD, const NekDouble > & GetPhys() const
This function returns (a reference to) the array (implemented as m_phys) containing the function ev...
Definition: ExpList.h:2161
const DNekScalBlkMatSharedPtr & GetBlockMatrix(const GlobalMatrixKey &gkey)
Definition: ExpList.cpp:1004
virtual void v_HelmSolve(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const FlagList &flags, const StdRegions::ConstFactorMap &factors, const StdRegions::VarCoeffMap &varcoeff, const MultiRegions::VarFactorsMap &varfactors, const Array< OneD, const NekDouble > &dirForcing, const bool PhysSpaceForcing)
Solve the Helmholtz equation.
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
virtual void v_Reset()
Reset geometry information, metrics, matrix managers and geometry information.
Definition: ExpList.cpp:1583
std::shared_ptr< RobinBCInfo > RobinBCInfoSharedPtr
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:163
void SetBoundaryConditionExpansion(const SpatialDomains::MeshGraphSharedPtr &graph1D, const SpatialDomains::BoundaryConditions &bcs, const std::string variable, Array< OneD, MultiRegions::ExpListSharedPtr > &bndCondExpansions, Array< OneD, SpatialDomains ::BoundaryConditionShPtr > &bndConditions)
Populates the list of boundary condition expansions.
int id
Geometry ID of entity.
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)
Evaluate all boundary conditions at a given time..
static ExpListSharedPtr NullExpListSharedPtr
Definition: ExpList.h:1550
std::shared_ptr< LocalRegions::ExpansionVector > m_exp
The list of local expansions.
Definition: ExpList.h:1090
void EvaluateBoundaryConditions(const NekDouble time=0.0, const std::string varName="", const NekDouble=NekConstants::kNekUnsetDouble, const NekDouble=NekConstants::kNekUnsetDouble)
Definition: ExpList.h:2356
std::shared_ptr< ExpList > ExpListSharedPtr
Shared pointer to an ExpList object.
virtual void v_AddTraceIntegral(const Array< OneD, const NekDouble > &Fn, Array< OneD, NekDouble > &outarray)
General purpose memory allocation routines with the ability to allocate from thread specific memory p...
std::shared_ptr< DNekScalBlkMat > DNekScalBlkMatSharedPtr
Definition: NekTypeDefs.hpp:73
std::shared_ptr< BoundaryConditions > BoundaryConditionsSharedPtr
Definition: Conditions.h:289
Array< OneD, SpatialDomains::BoundaryConditionShPtr > m_bndConditions
An array which contains the information about the boundary condition on the different boundary region...
const BoundaryConditionCollection & GetBoundaryConditions(void) const
Definition: Conditions.h:248
const Array< OneD, const NekDouble > & GetCoeffs() const
This function returns (a reference to) the array (implemented as m_coeffs) containing all local expa...
Definition: ExpList.h:2062
virtual std::map< int, RobinBCInfoSharedPtr > v_GetRobinBCInfo()
void FindPeriodicVertices(const SpatialDomains::BoundaryConditions &bcs, const std::string variable)
Generate a associative map of periodic vertices in a mesh.
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition: Comm.h:53
std::shared_ptr< ExpList0D > ExpList0DSharedPtr
Shared pointer to an ExpList0D object.
Definition: ExpList0D.h:53
Lagrange Polynomials using the Gauss points .
Definition: BasisType.h:55
std::shared_ptr< GlobalLinSys > GlobalLinSysSharedPtr
Pointer to a GlobalLinSys object.
Definition: GlobalLinSys.h:50
STL namespace.
SpatialDomains::BoundaryConditionsSharedPtr GetDomainBCs(const SpatialDomains::CompositeMap &domain, const SpatialDomains::BoundaryConditions &Allbcs, const std::string &variable)
std::map< int, CompositeSharedPtr > CompositeMap
Definition: MeshGraph.h:137
std::map< ConstFactorType, NekDouble > ConstFactorMap
Definition: StdRegions.hpp:294
void SetUpDG(const std::string &variable)
void GetBoundaryToElmtMap(Array< OneD, int > &ElmtID, Array< OneD, int > &EdgeID)
Definition: ExpList.h:2409
Array< OneD, NekDouble > m_phys
The global expansion evaluated at the quadrature points.
Definition: ExpList.h:1069
std::shared_ptr< Composite > CompositeSharedPtr
Definition: MeshGraph.h:136
std::shared_ptr< DNekMat > DNekMatSharedPtr
Definition: NekTypeDefs.hpp:69
virtual void v_GetBndElmtExpansion(int i, std::shared_ptr< ExpList > &result, const bool DeclareCoeffPhysArrays)
void ApplyGeomInfo()
Apply geometry information to each expansion.
Definition: ExpList.cpp:1570
std::shared_ptr< Basis > BasisSharedPtr
int GetExpSize(void)
This function returns the number of elements in the expansion.
Definition: ExpList.h:2170
const std::shared_ptr< LocalRegions::ExpansionVector > GetExp() const
This function returns the vector of elements in the expansion.
Definition: ExpList.h:2191
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:1381
void SetAdjacentElementExp(int vertex, Expansion1DSharedPtr &v)
Definition: Expansion0D.h:112
1D Gauss-Gauss-Legendre quadrature points
Definition: PointsType.h:48
virtual void v_GetFwdBwdTracePhys(Array< OneD, NekDouble > &Fwd, Array< OneD, NekDouble > &Bwd)
BasisManagerT & BasisManager(void)
GlobalLinSysSharedPtr GetGlobalBndLinSys(const GlobalLinSysKey &mkey)
For a given key, returns the associated global linear system.
std::shared_ptr< BoundaryConditionMap > BoundaryConditionMapShPtr
Definition: Conditions.h:225
Array< OneD, int > m_coeff_offset
Offset of elemental data into the array m_coeffs.
Definition: ExpList.h:1101
Base class for all multi-elemental spectral/hp expansions.
Definition: ExpList.h:103
virtual void v_ExtractTracePhys(Array< OneD, NekDouble > &outarray)
std::shared_ptr< BoundaryRegion > BoundaryRegionShPtr
Definition: Conditions.h:215
void Smul(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha*y.
Definition: Vmath.cpp:216
StdRegions::MatrixType GetMatrixType() const
Return the matrix type.
DisContField1D()
Default constructor.
std::shared_ptr< Expansion0D > Expansion0DSharedPtr
Definition: Expansion0D.h:48
std::map< StdRegions::VarCoeffType, Array< OneD, NekDouble > > VarCoeffMap
Definition: StdRegions.hpp:264
bool m_physState
The state of the array m_phys.
Definition: ExpList.h:1078
int m_ncoeffs
The total number of local degrees of freedom. m_ncoeffs .
Definition: ExpList.h:1030
std::map< int, BoundaryRegionShPtr > BoundaryRegionCollection
Definition: Conditions.h:217
bool isLocal
Flag specifying if this entity is local to this partition.
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
This class is the abstraction of a global discontinuous two- dimensional spectral/hp element expansio...
NekMatrix< InnerMatrixType, BlockMatrixTag > Transpose(NekMatrix< InnerMatrixType, BlockMatrixTag > &rhs)
SpatialDomains::MeshGraphSharedPtr m_graph
Mesh associated with this expansion list.
Definition: ExpList.h:1026
void GenerateBoundaryConditionExpansion(const SpatialDomains::MeshGraphSharedPtr &graph1D, const SpatialDomains::BoundaryConditions &bcs, const std::string variable)
Discretises the boundary conditions.
LibUtilities::SessionReaderSharedPtr m_session
Session.
Definition: ExpList.h:1023
AssemblyMapDGSharedPtr m_traceMap
Local to global DG mapping for trace space.
Defines a specification for a set of points.
Definition: Points.h:59
void Neg(int n, T *x, const int incx)
Negate x = -x.
Definition: Vmath.cpp:399
double NekDouble
Defines a list of flags.
std::map< int, BoundaryConditionMapShPtr > BoundaryConditionCollection
Definition: Conditions.h:226
std::shared_ptr< PointGeom > PointGeomSharedPtr
Definition: Geometry.h:59
static const NekDouble kNekUnsetDouble
Describe a linear system.
std::shared_ptr< BoundaryConditionBase > BoundaryConditionShPtr
Definition: Conditions.h:219
Describes a matrix with ordering defined by a local to global map.
bool IsLeftAdjacentVertex(const int n, const int e)
GlobalLinSysMapShPtr m_globalBndMat
Global boundary matrix.
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:65
static AssemblyMapSharedPtr NullAssemblyMapSharedPtr
Definition: AssemblyMap.h:54
std::vector< bool > & GetNegatedFluxNormal(void)
Array< OneD, MultiRegions::ExpListSharedPtr > m_bndCondExpansions
Discretised boundary conditions.
virtual void v_Reset()
Reset this field, so that geometry information can be updated.
#define ASSERTL2(condition, msg)
Assert Level 2 – Debugging which is used FULLDEBUG compilation mode. This level assert is designed t...
Definition: ErrorUtil.hpp:274
NekDouble GetCoeff(int i)
Get the i th value (coefficient) of m_coeffs.
Definition: ExpList.h:2139
std::set< int > m_boundaryVerts
A set storing the global IDs of any boundary edges.
void IProductWRTBase(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, CoeffState coeffstate=eLocal)
Definition: ExpList.h:1714
This class is the abstraction of a one-dimensional multi-elemental expansions which is merely a colle...
Definition: ExpList1D.h:58
ExpListSharedPtr m_trace
Trace space storage for points between elements.
std::vector< int > m_periodicFwdCopy
A vector indicating degress of freedom which need to be copied from forwards to backwards space in ca...
static SpatialDomains::BoundaryConditionShPtr GetBoundaryCondition(const SpatialDomains::BoundaryConditionCollection &collection, unsigned int index, const std::string &variable)
Definition: ExpList.cpp:3261
GlobalSysSolnType GetGlobalSysSolnType() const
Return the associated solution type.
PeriodicMap m_periodicVerts
A map which identifies groups of periodic vertices.
int GetCoeff_Offset(int n) const
Get the start offset position for a global list of m_coeffs correspoinding to element n...
Definition: ExpList.h:2200
T Vsum(int n, const T *x, const int incx)
Subtract return sum(x)
Definition: Vmath.cpp:740
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:376
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:250
int GetPhys_Offset(int n) const
Get the start offset position for a global list of m_phys correspoinding to element n...
Definition: ExpList.h:2208
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1064
std::shared_ptr< Expansion1D > Expansion1DSharedPtr
Definition: Expansion1D.h:51
Describes the specification for a Basis.
Definition: Basis.h:49
std::shared_ptr< SessionReader > SessionReaderSharedPtr
const BoundaryRegionCollection & GetBoundaryRegions(void) const
Definition: Conditions.h:238
std::shared_ptr< ExpList > & GetTrace()
Definition: ExpList.h:2267
std::map< StdRegions::ConstFactorType, Array< OneD, NekDouble > > VarFactorsMap
virtual void v_GetBoundaryToElmtMap(Array< OneD, int > &ElmtID, Array< OneD, int > &VertID)