Nektar++
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
Public Member Functions | List of all members
Nektar::CoupledLocalToGlobalC0ContMap Class Reference

#include <CoupledLocalToGlobalC0ContMap.h>

Inheritance diagram for Nektar::CoupledLocalToGlobalC0ContMap:
[legend]

Public Member Functions

 CoupledLocalToGlobalC0ContMap (const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &graph, const SpatialDomains::BoundaryConditionsSharedPtr &boundaryConditions, const Array< OneD, MultiRegions::ExpListSharedPtr > &fields, const MultiRegions::ExpListSharedPtr &pressure, const int nz_loc, const bool CheeckForSingularSys=true)
 
void FindEdgeIdToAddMeanPressure (std::vector< std::map< int, int > > &ReorderedGraphVertId, int &nel, const LocalRegions::ExpansionVector &locExpVector, int &edgeId, int &vertId, int &firstNonDirGraphVertId, std::map< int, int > &IsDirEdgeDof, MultiRegions::BottomUpSubStructuredGraphSharedPtr &bottomUpGraph, Array< OneD, int > &AddMeanPressureToEdgeId)
 
- Public Member Functions inherited from Nektar::MultiRegions::AssemblyMapCG
 AssemblyMapCG (const LibUtilities::SessionReaderSharedPtr &pSession, const std::string variable="DefaultVar")
 Default constructor. More...
 
 AssemblyMapCG (const LibUtilities::SessionReaderSharedPtr &pSession, const int numLocalCoeffs, const ExpList &locExp, const BndCondExp &bndCondExp=NullExpListSharedPtrArray, const BndCond &bndConditions=SpatialDomains::NullBoundaryConditionShPtrArray, const bool checkIfSingular=false, const std::string variable="defaultVar", const PeriodicMap &periodicVerts=NullPeriodicMap, const PeriodicMap &periodicEdges=NullPeriodicMap, const PeriodicMap &periodicFaces=NullPeriodicMap)
 General constructor for expansions of all dimensions without boundary conditions. More...
 
virtual ~AssemblyMapCG ()
 Destructor. More...
 
std::set< ExtraDirDof > & GetCopyLocalDirDofs ()
 
std::set< int > & GetParallelDirBndSign ()
 
- Public Member Functions inherited from Nektar::MultiRegions::AssemblyMap
 AssemblyMap ()
 Default constructor. More...
 
 AssemblyMap (const LibUtilities::SessionReaderSharedPtr &pSession, const std::string variable="DefaultVar")
 Constructor with a communicator. More...
 
 AssemblyMap (AssemblyMap *oldLevelMap, const BottomUpSubStructuredGraphSharedPtr &multiLevelGraph)
 Constructor for next level in multi-level static condensation. More...
 
virtual ~AssemblyMap ()
 Destructor. More...
 
LibUtilities::CommSharedPtr GetComm ()
 Retrieves the communicator. More...
 
size_t GetHash () const
 Retrieves the hash of this map. More...
 
int GetLocalToGlobalMap (const int i) const
 
int GetGlobalToUniversalMap (const int i) const
 
int GetGlobalToUniversalMapUnique (const int i) const
 
const Array< OneD, const int > & GetLocalToGlobalMap ()
 
const Array< OneD, const int > & GetGlobalToUniversalMap ()
 
const Array< OneD, const int > & GetGlobalToUniversalMapUnique ()
 
NekDouble GetLocalToGlobalSign (const int i) const
 
const Array< OneD, NekDouble > & GetLocalToGlobalSign () const
 
void LocalToGlobal (const Array< OneD, const NekDouble > &loc, Array< OneD, NekDouble > &global, bool useComm=true) const
 
void LocalToGlobal (const NekVector< NekDouble > &loc, NekVector< NekDouble > &global, bool useComm=true) const
 
void GlobalToLocal (const Array< OneD, const NekDouble > &global, Array< OneD, NekDouble > &loc) const
 
void GlobalToLocal (const NekVector< NekDouble > &global, NekVector< NekDouble > &loc) const
 
void Assemble (const Array< OneD, const NekDouble > &loc, Array< OneD, NekDouble > &global) const
 
void Assemble (const NekVector< NekDouble > &loc, NekVector< NekDouble > &global) const
 
void UniversalAssemble (Array< OneD, NekDouble > &pGlobal) const
 
void UniversalAssemble (NekVector< NekDouble > &pGlobal) const
 
void UniversalAssemble (Array< OneD, NekDouble > &pGlobal, int offset) const
 
void UniversalAbsMaxBnd (Array< OneD, NekDouble > &bndvals)
 
int GetLocalToGlobalBndMap (const int i) const
 Retrieve the global index of a given local boundary mode. More...
 
const Array< OneD, const int > & GetLocalToGlobalBndMap ()
 Retrieve the global indices of the local boundary modes. More...
 
const Array< OneD, const int > & GetGlobalToUniversalBndMap ()
 
const Array< OneD, const int > & GetGlobalToUniversalBndMapUnique ()
 
bool GetSignChange ()
 Returns true if using a modal expansion requiring a change of sign of some modes. More...
 
NekDouble GetLocalToGlobalBndSign (const int i) const
 Retrieve the sign change of a given local boundary mode. More...
 
Array< OneD, const NekDoubleGetLocalToGlobalBndSign () const
 Retrieve the sign change for all local boundary modes. More...
 
const Array< OneD, const int > & GetBndCondCoeffsToLocalCoeffsMap ()
 Retrieves the local indices corresponding to the boundary expansion modes. More...
 
const Array< OneD, NekDouble > & GetBndCondCoeffsToLocalCoeffsSign ()
 Returns the modal sign associated with a given boundary expansion mode. More...
 
const Array< OneD, const int > & GetBndCondCoeffsToLocalTraceMap ()
 Retrieves the local indices corresponding to the boundary expansion modes to global trace. More...
 
int GetBndCondIDToGlobalTraceID (const int i)
 Returns the global index of the boundary trace giving the index on the boundary expansion. More...
 
const Array< OneD, const int > & GetBndCondIDToGlobalTraceID ()
 
int GetNumGlobalDirBndCoeffs () const
 Returns the number of global Dirichlet boundary coefficients. More...
 
int GetNumLocalDirBndCoeffs () const
 Returns the number of local Dirichlet boundary coefficients. More...
 
int GetNumGlobalBndCoeffs () const
 Returns the total number of global boundary coefficients. More...
 
int GetNumLocalBndCoeffs () const
 Returns the total number of local boundary coefficients. More...
 
int GetNumLocalCoeffs () const
 Returns the total number of local coefficients. More...
 
int GetNumGlobalCoeffs () const
 Returns the total number of global coefficients. More...
 
bool GetSingularSystem () const
 Retrieves if the system is singular (true) or not (false) More...
 
void GlobalToLocalBnd (const NekVector< NekDouble > &global, NekVector< NekDouble > &loc, int offset) const
 
void GlobalToLocalBnd (const NekVector< NekDouble > &global, NekVector< NekDouble > &loc) const
 
void GlobalToLocalBnd (const Array< OneD, const NekDouble > &global, Array< OneD, NekDouble > &loc, int offset) const
 
void GlobalToLocalBnd (const Array< OneD, const NekDouble > &global, Array< OneD, NekDouble > &loc) const
 
void LocalBndToGlobal (const Array< OneD, const NekDouble > &loc, Array< OneD, NekDouble > &global, int offset, bool UseComm=true) const
 
void LocalBndToGlobal (const Array< OneD, const NekDouble > &loc, Array< OneD, NekDouble > &global, bool UseComm=true) const
 
void LocalToLocalBnd (const Array< OneD, const NekDouble > &local, Array< OneD, NekDouble > &locbnd) const
 
void LocalToLocalInt (const Array< OneD, const NekDouble > &local, Array< OneD, NekDouble > &locint) const
 
void LocalBndToLocal (const Array< OneD, const NekDouble > &locbnd, Array< OneD, NekDouble > &local) const
 
void LocalIntToLocal (const Array< OneD, const NekDouble > &locbnd, Array< OneD, NekDouble > &local) const
 
void AssembleBnd (const NekVector< NekDouble > &loc, NekVector< NekDouble > &global, int offset) const
 
void AssembleBnd (const NekVector< NekDouble > &loc, NekVector< NekDouble > &global) const
 
void AssembleBnd (const Array< OneD, const NekDouble > &loc, Array< OneD, NekDouble > &global, int offset) const
 
void AssembleBnd (const Array< OneD, const NekDouble > &loc, Array< OneD, NekDouble > &global) const
 
void UniversalAssembleBnd (Array< OneD, NekDouble > &pGlobal) const
 
void UniversalAssembleBnd (NekVector< NekDouble > &pGlobal) const
 
void UniversalAssembleBnd (Array< OneD, NekDouble > &pGlobal, int offset) const
 
int GetFullSystemBandWidth () const
 
int GetNumNonDirVertexModes () const
 
int GetNumNonDirEdgeModes () const
 
int GetNumNonDirFaceModes () const
 
int GetNumDirEdges () const
 
int GetNumDirFaces () const
 
int GetNumNonDirEdges () const
 
int GetNumNonDirFaces () const
 
void PrintStats (std::ostream &out, std::string variable, bool printHeader=true) const
 
const Array< OneD, const int > & GetExtraDirEdges ()
 
std::shared_ptr< AssemblyMapLinearSpaceMap (const ExpList &locexp, GlobalSysSolnType solnType)
 
int GetBndSystemBandWidth () const
 Returns the bandwidth of the boundary system. More...
 
int GetStaticCondLevel () const
 Returns the level of static condensation for this map. More...
 
int GetNumPatches () const
 Returns the number of patches in this static condensation level. More...
 
const Array< OneD, const unsigned int > & GetNumLocalBndCoeffsPerPatch ()
 Returns the number of local boundary coefficients in each patch. More...
 
const Array< OneD, const unsigned int > & GetNumLocalIntCoeffsPerPatch ()
 Returns the number of local interior coefficients in each patch. More...
 
const AssemblyMapSharedPtr GetNextLevelLocalToGlobalMap () const
 Returns the local to global mapping for the next level in the multi-level static condensation. More...
 
void SetNextLevelLocalToGlobalMap (AssemblyMapSharedPtr pNextLevelLocalToGlobalMap)
 
const PatchMapSharedPtrGetPatchMapFromPrevLevel (void) const
 Returns the patch map from the previous level of the multi-level static condensation. More...
 
bool AtLastLevel () const
 Returns true if this is the last level in the multi-level static condensation. More...
 
GlobalSysSolnType GetGlobalSysSolnType () const
 Returns the method of solving global systems. More...
 
PreconditionerType GetPreconType () const
 
NekDouble GetIterativeTolerance () const
 
int GetMaxIterations () const
 
int GetSuccessiveRHS () const
 
std::string GetLinSysIterSolver () const
 
int GetLowestStaticCondLevel () const
 
void PatchLocalToGlobal (const Array< OneD, const NekDouble > &loc, Array< OneD, NekDouble > &global) const
 
void PatchGlobalToLocal (const Array< OneD, const NekDouble > &global, Array< OneD, NekDouble > &loc) const
 
void PatchAssemble (const Array< OneD, const NekDouble > &loc, Array< OneD, NekDouble > &global) const
 

Additional Inherited Members

- Protected Member Functions inherited from Nektar::MultiRegions::AssemblyMapCG
int CreateGraph (const ExpList &locExp, const BndCondExp &bndCondExp, const Array< OneD, const BndCond > &bndConditions, const bool checkIfSystemSingular, const PeriodicMap &periodicVerts, const PeriodicMap &periodicEdges, const PeriodicMap &periodicFaces, DofGraph &graph, BottomUpSubStructuredGraphSharedPtr &bottomUpGraph, std::set< int > &extraDirVerts, std::set< int > &extraDirEdges, int &firstNonDirGraphVertId, int &nExtraDirichlet, int mdswitch=1)
 
void SetUpUniversalC0ContMap (const ExpList &locExp, const PeriodicMap &perVerts=NullPeriodicMap, const PeriodicMap &perEdges=NullPeriodicMap, const PeriodicMap &perFaces=NullPeriodicMap)
 
void CalculateFullSystemBandWidth ()
 Calculate the bandwith of the full matrix system. More...
 
virtual int v_GetLocalToGlobalMap (const int i) const
 
virtual int v_GetGlobalToUniversalMap (const int i) const
 
virtual int v_GetGlobalToUniversalMapUnique (const int i) const
 
virtual const Array< OneD, const int > & v_GetLocalToGlobalMap ()
 
virtual const Array< OneD, const int > & v_GetGlobalToUniversalMap ()
 
virtual const Array< OneD, const int > & v_GetGlobalToUniversalMapUnique ()
 
virtual NekDouble v_GetLocalToGlobalSign (const int i) const
 
virtual const Array< OneD, NekDouble > & v_GetLocalToGlobalSign () const
 
virtual void v_LocalToGlobal (const Array< OneD, const NekDouble > &loc, Array< OneD, NekDouble > &global, bool useComm) const
 
virtual void v_LocalToGlobal (const NekVector< NekDouble > &loc, NekVector< NekDouble > &global, bool useComm) const
 
virtual void v_GlobalToLocal (const Array< OneD, const NekDouble > &global, Array< OneD, NekDouble > &loc) const
 
virtual void v_GlobalToLocal (const NekVector< NekDouble > &global, NekVector< NekDouble > &loc) const
 
virtual void v_Assemble (const Array< OneD, const NekDouble > &loc, Array< OneD, NekDouble > &global) const
 
virtual void v_Assemble (const NekVector< NekDouble > &loc, NekVector< NekDouble > &global) const
 
virtual void v_UniversalAssemble (Array< OneD, NekDouble > &pGlobal) const
 
virtual void v_UniversalAssemble (NekVector< NekDouble > &pGlobal) const
 
virtual void v_UniversalAssemble (Array< OneD, NekDouble > &pGlobal, int offset) const
 
virtual int v_GetFullSystemBandWidth () const
 
virtual int v_GetNumNonDirVertexModes () const
 
virtual int v_GetNumNonDirEdgeModes () const
 
virtual int v_GetNumNonDirFaceModes () const
 
virtual int v_GetNumDirEdges () const
 
virtual int v_GetNumDirFaces () const
 
virtual int v_GetNumNonDirEdges () const
 
virtual int v_GetNumNonDirFaces () const
 
virtual const Array< OneD, const int > & v_GetExtraDirEdges ()
 
virtual AssemblyMapSharedPtr v_LinearSpaceMap (const ExpList &locexp, GlobalSysSolnType solnType)
 Construct an AssemblyMapCG object which corresponds to the linear space of the current object. More...
 
- Protected Member Functions inherited from Nektar::MultiRegions::AssemblyMap
void CalculateBndSystemBandWidth ()
 Calculates the bandwidth of the boundary system. More...
 
void GlobalToLocalBndWithoutSign (const Array< OneD, const NekDouble > &global, Array< OneD, NekDouble > &loc)
 
- Protected Attributes inherited from Nektar::MultiRegions::AssemblyMapCG
Array< OneD, int > m_localToGlobalMap
 Integer map of local coeffs to global space. More...
 
Array< OneD, NekDoublem_localToGlobalSign
 Integer sign of local coeffs to global space. More...
 
int m_fullSystemBandWidth
 Bandwith of the full matrix system (no static condensation). More...
 
Array< OneD, int > m_globalToUniversalMap
 Integer map of process coeffs to universal space. More...
 
Array< OneD, int > m_globalToUniversalMapUnique
 Integer map of unique process coeffs to universal space (signed) More...
 
int m_numNonDirVertexModes
 Number of non Dirichlet vertex modes. More...
 
int m_numNonDirEdgeModes
 Number of non Dirichlet edge modes. More...
 
int m_numNonDirFaceModes
 Number of non Dirichlet face modes. More...
 
int m_numDirEdges
 Number of Dirichlet edges. More...
 
int m_numDirFaces
 Number of Dirichlet faces. More...
 
int m_numNonDirEdges
 Number of Dirichlet edges. More...
 
int m_numNonDirFaces
 Number of Dirichlet faces. More...
 
int m_numLocalBndCondCoeffs
 Number of local boundary condition coefficients. More...
 
Array< OneD, int > m_extraDirEdges
 Extra dirichlet edges in parallel. More...
 
int m_numLocDirBndCondDofs
 Number of local boundary condition degrees of freedom. More...
 
int m_maxStaticCondLevel
 Maximum static condensation level. More...
 
std::set< ExtraDirDofm_copyLocalDirDofs
 Set indicating degrees of freedom which are Dirichlet but whose value is stored on another processor. More...
 
std::set< int > m_parallelDirBndSign
 Set indicating the local coeffs just touching parallel dirichlet boundary that have a sign change. More...
 
- Protected Attributes inherited from Nektar::MultiRegions::AssemblyMap
LibUtilities::SessionReaderSharedPtr m_session
 Session object. More...
 
LibUtilities::CommSharedPtr m_comm
 Communicator. More...
 
size_t m_hash
 Hash for map. More...
 
int m_numLocalBndCoeffs
 Number of local boundary coefficients. More...
 
int m_numGlobalBndCoeffs
 Total number of global boundary coefficients. More...
 
int m_numLocalDirBndCoeffs
 Number of Local Dirichlet Boundary Coefficients. More...
 
int m_numGlobalDirBndCoeffs
 Number of Global Dirichlet Boundary Coefficients. More...
 
bool m_systemSingular
 Flag indicating if the system is singular or not. More...
 
int m_numLocalCoeffs
 Total number of local coefficients. More...
 
int m_numGlobalCoeffs
 Total number of global coefficients. More...
 
bool m_signChange
 Flag indicating if modes require sign reversal. More...
 
Array< OneD, int > m_localToGlobalBndMap
 Integer map of local coeffs to global Boundary Dofs. More...
 
Array< OneD, NekDoublem_localToGlobalBndSign
 Integer sign of local boundary coeffs to global space. More...
 
Array< OneD, int > m_localToLocalBndMap
 Integer map of local boundary coeffs to local boundary system numbering. More...
 
Array< OneD, int > m_localToLocalIntMap
 Integer map of local boundary coeffs to local interior system numbering. More...
 
Array< OneD, int > m_bndCondCoeffsToLocalCoeffsMap
 Integer map of bnd cond coeffs to local coefficients. More...
 
Array< OneD, NekDoublem_bndCondCoeffsToLocalCoeffsSign
 Integer map of sign of bnd cond coeffs to local coefficients. More...
 
Array< OneD, int > m_bndCondCoeffsToLocalTraceMap
 Integer map of bnd cond coeff to local trace coeff. More...
 
Array< OneD, int > m_bndCondIDToGlobalTraceID
 Integer map of bnd cond trace number to global trace number. More...
 
Array< OneD, int > m_globalToUniversalBndMap
 Integer map of process coeffs to universal space. More...
 
Array< OneD, int > m_globalToUniversalBndMapUnique
 Integer map of unique process coeffs to universal space (signed) More...
 
GlobalSysSolnType m_solnType
 The solution type of the global system. More...
 
int m_bndSystemBandWidth
 The bandwith of the global bnd system. More...
 
PreconditionerType m_preconType
 Type type of preconditioner to use in iterative solver. More...
 
int m_maxIterations
 Maximum iterations for iterative solver. More...
 
NekDouble m_iterativeTolerance
 Tolerance for iterative solver. More...
 
int m_successiveRHS
 sucessive RHS for iterative solver More...
 
std::string m_linSysIterSolver
 Iterative solver: Conjugate Gradient, GMRES. More...
 
Gs::gs_datam_gsh
 
Gs::gs_datam_bndGsh
 
Gs::gs_datam_dirBndGsh
 gs gather communication to impose Dirhichlet BCs. More...
 
int m_staticCondLevel
 The level of recursion in the case of multi-level static condensation. More...
 
int m_numPatches
 The number of patches (~elements) in the current level. More...
 
Array< OneD, unsigned int > m_numLocalBndCoeffsPerPatch
 The number of bnd dofs per patch. More...
 
Array< OneD, unsigned int > m_numLocalIntCoeffsPerPatch
 The number of int dofs per patch. More...
 
AssemblyMapSharedPtr m_nextLevelLocalToGlobalMap
 Map from the patches of the previous level to the patches of the current level. More...
 
int m_lowestStaticCondLevel
 Lowest static condensation level. More...
 

Detailed Description

Definition at line 44 of file CoupledLocalToGlobalC0ContMap.h.

Constructor & Destructor Documentation

◆ CoupledLocalToGlobalC0ContMap()

Nektar::CoupledLocalToGlobalC0ContMap::CoupledLocalToGlobalC0ContMap ( const LibUtilities::SessionReaderSharedPtr pSession,
const SpatialDomains::MeshGraphSharedPtr graph,
const SpatialDomains::BoundaryConditionsSharedPtr boundaryConditions,
const Array< OneD, MultiRegions::ExpListSharedPtr > &  fields,
const MultiRegions::ExpListSharedPtr pressure,
const int  nz_loc,
const bool  CheckforSingularSys = true 
)

This is an vector extension of MultiRegions::AssemblyMapCG::SetUp2DExpansionC0ContMap related to the Linearised Navier Stokes problem

STEP 1: Wrap boundary conditions vector in an array (since routine is set up for multiple fields) and call the graph re-odering subroutine to obtain the reordered values

@TODO: Fix this so that we can extract normals from edges

STEP 2a: Set the mean pressure modes to edges depending on type of direct solver technique;

STEP 2: Count out the number of Dirichlet vertices and edges first

STEP 3: Set up an array which contains the offset information of the different graph vertices.

This basically means to identify how many global degrees of freedom the individual graph vertices correspond. Obviously, the graph vertices corresponding to the mesh-vertices account for a single global DOF. However, the graph vertices corresponding to the element edges correspond to 2*(N-2) global DOF where N is equal to the number of boundary modes on this edge.

STEP 4: Now, all ingredients are ready to set up the actual local to global mapping.

The remainder of the map consists of the element-interior degrees of freedom. This leads to the block-diagonal submatrix as each element-interior mode is globally orthogonal to modes in all other elements.

STEP 5: The boundary condition mapping is generated from the same vertex renumbering and fill in a unique interior map.

Definition at line 52 of file CoupledLocalToGlobalC0ContMap.cpp.

59  :
60  AssemblyMapCG(pSession)
61  {
62  int i,j,k,n;
63  int cnt = 0,offset=0;
64  int meshVertId;
65  int meshEdgeId;
66  int bndEdgeCnt;
67  int globalId;
68  int nEdgeCoeffs;
69  int nEdgeInteriorCoeffs;
70  int firstNonDirGraphVertId;
71  int nLocBndCondDofs = 0;
72  int nLocDirBndCondDofs = 0;
73  int nExtraDirichlet = 0;
77  StdRegions::Orientation edgeOrient;
78  Array<OneD, unsigned int> edgeInteriorMap;
79  Array<OneD, int> edgeInteriorSign;
80  int nvel = fields.size();
81 
82  const LocalRegions::ExpansionVector &locExpVector = *(fields[0]->GetExp());
83  int id, diff;
84  int nel = fields[0]->GetNumElmts();
85 
86  MultiRegions::PeriodicMap periodicVerts;
87  MultiRegions::PeriodicMap periodicEdges;
88  MultiRegions::PeriodicMap periodicFaces;
89  vector<map<int,int> > ReorderedGraphVertId(3);
91  int staticCondLevel = 0;
92 
93  if(CheckforSingularSys) //all singularity checking by setting flag to true
94  {
95  m_systemSingular = true;
96  }
97  else // Turn off singular checking by setting flag to false
98  {
99  m_systemSingular = false;
100  }
101 
102  /**
103  * STEP 1: Wrap boundary conditions vector in an array
104  * (since routine is set up for multiple fields) and call
105  * the graph re-odering subroutine to obtain the reordered
106  * values
107  */
108 
109  // Obtain any periodic information and allocate default mapping array
110  fields[0]->GetPeriodicEntities(periodicVerts,periodicEdges,periodicFaces);
111 
112 
113  const Array<OneD, const MultiRegions::ExpListSharedPtr> bndCondExp = fields[0]->GetBndCondExpansions();
114 
115  Array<OneD, Array<OneD, const SpatialDomains::BoundaryConditionShPtr> > bndConditionsVec(nvel);
116  for(i = 0; i < nvel; ++i)
117  {
118  bndConditionsVec[i] = fields[i]->GetBndConditions();
119  }
120 
121  map<int,int> IsDirVertDof;
122  map<int,int> IsDirEdgeDof;
123 
125  for(j = 0; j < bndCondExp.size(); ++j)
126  {
127  map<int,int> BndExpVids;
128  // collect unique list of vertex ids for this expansion
129  for(k = 0; k < bndCondExp[j]->GetNumElmts(); ++k)
130  {
131  g = bndCondExp[j]->GetExp(k)->as<LocalRegions::Expansion1D>()
132  ->GetGeom1D();
133  BndExpVids[g->GetVid(0)] = g->GetVid(0);
134  BndExpVids[g->GetVid(1)] = g->GetVid(1);
135  }
136 
137  for(i = 0; i < nvel; ++i)
138  {
139  if(bndConditionsVec[i][j]->GetBoundaryConditionType()==SpatialDomains::eDirichlet)
140  {
141  // set number of Dirichlet conditions along edge
142  for(k = 0; k < bndCondExp[j]->GetNumElmts(); ++k)
143  {
144  IsDirEdgeDof[bndCondExp[j]->GetExp(k)
145  ->as<LocalRegions::Expansion1D>()
146  ->GetGeom1D()->GetGlobalID()] += 1;
147  }
148 
149 
150  // Set number of Dirichlet conditions at vertices
151  // with a clamp on its maximum value being nvel to
152  // handle corners between expansions
153  for(auto &mapIt : BndExpVids)
154  {
155  id = IsDirVertDof[mapIt.second]+1;
156  IsDirVertDof[mapIt.second] = (id > nvel)?nvel:id;
157  }
158  }
159  else
160  {
161  // Check to see that edge normals have non-zero
162  // component in this direction since otherwise
163  // also can be singular.
164  /// @TODO: Fix this so that we can extract normals from edges
165  for(k = 0; k < bndCondExp[j]->GetNumElmts(); ++k)
166  {
167  Array<OneD,Array<OneD,NekDouble> > locnorm;
169  = bndCondExp[j]->GetExp(k)
170  ->as<LocalRegions::Expansion1D>();
171  locnorm = loc_exp->GetLeftAdjacentElementExp()->
172  GetTraceNormal(loc_exp->GetLeftAdjacentElementTrace());
173 
174  int ndir = locnorm.size();
175  if(i < ndir) // account for Fourier version where n can be larger then ndir
176  {
177  for(int l = 0; l < locnorm[0].size(); ++l)
178  {
179  if(fabs(locnorm[i][l]) > NekConstants::kNekZeroTol)
180  {
181  m_systemSingular = false;
182  break;
183  }
184  }
185  }
186  if(m_systemSingular == false)
187  {
188  break;
189  }
190  }
191  }
192  }
193  }
194 
195  Array<OneD, map<int,int> >Dofs(2);
196 
197  Array<OneD, int> AddMeanPressureToEdgeId(nel,-1);
198  int edgeId,vertId;
199 
200 
201  // special case of singular problem - need to fix one pressure
202  // dof to a dirichlet edge. Since we attached pressure dof to
203  // last velocity component of edge need to make sure this
204  // component is Dirichlet
205  if(m_systemSingular)
206  {
207  id = -1;
208  for(i = 0; i < bndConditionsVec[0].size(); ++i)
209  {
210  if(bndConditionsVec[nvel-1][i]->GetBoundaryConditionType() == SpatialDomains::eDirichlet)
211  {
212  id = bndCondExp[i]->GetExp(0)
213  ->as<LocalRegions::Expansion1D>()->GetGeom1D()
214  ->GetGlobalID();
215  break;
216  }
217  }
218 
219  ASSERTL0(id != -1," Did not find an edge to attach singular pressure degree of freedom");
220 
221  // determine element with this edge id. There may be a
222  // more direct way of getting element from spatialDomains
223  for(i = 0; i < nel; ++i)
224  {
225  for(j = 0; j < locExpVector[i]->GetNverts(); ++j)
226  {
227  edgeId = (locExpVector[i]->as<LocalRegions::Expansion2D>()
228  ->GetGeom2D())->GetEid(j);
229 
230  if(edgeId == id)
231  {
232  AddMeanPressureToEdgeId[i] = id;
233  break;
234  }
235  }
236 
237  if(AddMeanPressureToEdgeId[i] != -1)
238  {
239  break;
240  }
241  }
242  }
243 
244 
245  for(i = 0; i < nel; ++i)
246  {
247  for(j = 0; j < locExpVector[i]->GetNverts(); ++j)
248  {
249  vertId = (locExpVector[i]->as<LocalRegions::Expansion2D>()
250  ->GetGeom2D())->GetVid(j);
251  if(Dofs[0].count(vertId) == 0)
252  {
253  Dofs[0][vertId] = nvel*nz_loc;
254 
255  // Adjust for a Dirichlet boundary condition to give number to be solved
256  if(IsDirVertDof.count(vertId) != 0)
257  {
258  Dofs[0][vertId] -= IsDirVertDof[vertId]*nz_loc;
259  }
260  }
261 
262  edgeId = (locExpVector[i]->as<LocalRegions::Expansion2D>()
263  ->GetGeom2D())->GetEid(j);
264  if(Dofs[1].count(edgeId) == 0)
265  {
266  Dofs[1][edgeId] = nvel*(locExpVector[i]->
267  GetTraceNcoeffs(j)-2)*nz_loc;
268  }
269 
270  // Adjust for Dirichlet boundary conditions to give number to be solved
271  if(IsDirEdgeDof.count(edgeId) != 0)
272  {
273  Dofs[1][edgeId] -= IsDirEdgeDof[edgeId]*nz_loc*(locExpVector[i]->
274  GetTraceNcoeffs(j)-2);
275  }
276  }
277  }
278 
279  set<int> extraDirVerts, extraDirEdges;
280 
281  CreateGraph(*fields[0], bndCondExp, bndConditionsVec, false,
282  periodicVerts, periodicEdges, periodicFaces,
283  ReorderedGraphVertId, bottomUpGraph, extraDirVerts,
284  extraDirEdges, firstNonDirGraphVertId, nExtraDirichlet, 4);
285  /*
286  SetUp2DGraphC0ContMap(*fields[0],
287  bndCondExp,
288  bndConditionsVec,
289  periodicVerts, periodicEdges,
290  Dofs, ReorderedGraphVertId,
291  firstNonDirGraphVertId, nExtraDirichlet,
292  bottomUpGraph, extraDir, false, 4);
293  */
294 
295  /**
296  * STEP 2a: Set the mean pressure modes to edges depending on
297  * type of direct solver technique;
298  */
299 
300  // determine which edge to add mean pressure dof based on
301  // ensuring that at least one pressure dof from an internal
302  // patch is associated with its boundary system
303  if(m_session->MatchSolverInfoAsEnum("GlobalSysSoln", MultiRegions::eDirectMultiLevelStaticCond))
304  {
305 
306 
307  FindEdgeIdToAddMeanPressure(ReorderedGraphVertId,
308  nel, locExpVector,
309  edgeId, vertId, firstNonDirGraphVertId, IsDirEdgeDof,
310  bottomUpGraph,
311  AddMeanPressureToEdgeId);
312  }
313 
314  // Set unset elmts to non-Dirichlet edges.
315  // special case of singular problem - need to fix one
316  // pressure dof to a dirichlet edge
317  for(i = 0; i < nel; ++i)
318  {
319  for(j = 0; j < locExpVector[i]->GetNverts(); ++j)
320  {
321  edgeId = (locExpVector[i]->as<LocalRegions::Expansion2D>()
322  ->GetGeom2D())->GetEid(j);
323 
324  if(IsDirEdgeDof.count(edgeId) == 0) // interior edge
325  {
326  // setup AddMeanPressureToEdgeId to decide where to
327  // put pressure
328  if(AddMeanPressureToEdgeId[i] == -1)
329  {
330  AddMeanPressureToEdgeId[i] = edgeId;
331  }
332  }
333  }
334  ASSERTL0((AddMeanPressureToEdgeId[i] != -1),"Did not determine "
335  "an edge to attach mean pressure dof");
336  // Add the mean pressure degree of freedom to this edge
337  Dofs[1][AddMeanPressureToEdgeId[i]] += nz_loc;
338  }
339 
340  map<int,int> pressureEdgeOffset;
341 
342  /**
343  * STEP 2: Count out the number of Dirichlet vertices and edges first
344  */
345  for(i = 0; i < bndCondExp.size(); i++)
346  {
347  for(j = 0; j < bndCondExp[i]->GetNumElmts(); j++)
348  {
349  bndSegExp = bndCondExp[i]->GetExp(j)
350  ->as<LocalRegions::SegExp>();
351  for(k = 0; k < nvel; ++k)
352  {
353  if(bndConditionsVec[k][i]->GetBoundaryConditionType()==SpatialDomains::eDirichlet)
354  {
355  nLocDirBndCondDofs += bndSegExp->GetNcoeffs()*nz_loc;
356  }
357 
358  if (bndConditionsVec[k][i]->GetBoundaryConditionType()!=SpatialDomains::ePeriodic)
359  {
360  nLocBndCondDofs += bndSegExp->GetNcoeffs()*nz_loc;
361  }
362  }
363  }
364  }
365 
366  if(m_systemSingular)
367  {
368  m_numLocalDirBndCoeffs = nLocDirBndCondDofs+nExtraDirichlet+nz_loc;
369  }
370  else
371  {
372  m_numLocalDirBndCoeffs = nLocDirBndCondDofs+nExtraDirichlet;
373  }
374 
375  /**
376  * STEP 3: Set up an array which contains the offset information of
377  * the different graph vertices.
378  *
379  * This basically means to identify how many global degrees of
380  * freedom the individual graph vertices correspond. Obviously,
381  * the graph vertices corresponding to the mesh-vertices account
382  * for a single global DOF. However, the graph vertices
383  * corresponding to the element edges correspond to 2*(N-2) global DOF
384  * where N is equal to the number of boundary modes on this edge.
385  */
386  Array<OneD, int> graphVertOffset(nvel*nz_loc*(ReorderedGraphVertId[0].size() + ReorderedGraphVertId[1].size()),0);
387  graphVertOffset[0] = 0;
388 
389  m_signChange = false;
390 
391  for(i = 0; i < nel; ++i)
392  {
393  locExpansion = locExpVector[i]->as<LocalRegions::Expansion2D>();
394 
395  for(j = 0; j < locExpansion->GetNtraces(); ++j)
396  {
397  nEdgeCoeffs = locExpansion->GetTraceNcoeffs(j);
398  meshEdgeId = (locExpansion->GetGeom2D())->GetEid(j);
399  meshVertId = (locExpansion->GetGeom2D())->GetVid(j);
400 
401  for(k = 0; k < nvel*nz_loc; ++k)
402  {
403  graphVertOffset[ReorderedGraphVertId[0]
404  [meshVertId]*nvel*nz_loc+k] = 1;
405  graphVertOffset[ReorderedGraphVertId[1]
406  [meshEdgeId]*nvel*nz_loc+k] = (nEdgeCoeffs-2);
407  }
408 
409  bType = locExpansion->GetBasisType(0);
410  // need a sign vector for modal expansions if nEdgeCoeffs >=4
411  if( (nEdgeCoeffs >= 4)&&(bType == LibUtilities::eModified_A))
412  {
413  m_signChange = true;
414  }
415  }
416  }
417 
418  // Add mean pressure modes;
419  for(i = 0; i < nel; ++i)
420  {
421  graphVertOffset[(ReorderedGraphVertId[1][AddMeanPressureToEdgeId[i]]+1)*nvel*nz_loc-1] += nz_loc;
422  //graphVertOffset[(ReorderedGraphVertId[1][AddMeanPressureToEdgeId[i]])*nvel*nz_loc] += nz_loc;
423  }
424 
425  // Negate the vertices and edges with only a partial
426  // Dirichlet conditon. Essentially we check to see if an edge
427  // has a mixed Dirichlet with Neumann/Robin Condition and if
428  // so negate the offset associated with this vertex.
429 
430  map<int,int> DirVertChk;
431 
432  for(i = 0; i < bndConditionsVec[0].size(); ++i)
433  {
434  cnt = 0;
435  for(j = 0; j < nvel; ++j)
436  {
437  if(bndConditionsVec[j][i]->GetBoundaryConditionType() == SpatialDomains::eDirichlet)
438  {
439  cnt ++;
440  }
441  }
442 
443  // Case where partial Dirichlet boundary condition
444  if((cnt > 0)&&(cnt < nvel))
445  {
446  for(j = 0; j < nvel; ++j)
447  {
448  if(bndConditionsVec[j][i]->GetBoundaryConditionType() == SpatialDomains::eDirichlet)
449  {
450  //negate graph offsets which should be
451  //Dirichlet conditions
452  for(k = 0; k < bndCondExp[i]->GetNumElmts(); ++k)
453  {
454  // vertices with mix condition;
455  id = bndCondExp[i]->GetExp(k)
456  ->as<LocalRegions::Expansion1D>()
457  ->GetGeom1D()->GetVid(0);
458  if(DirVertChk.count(id*nvel+j) == 0)
459  {
460  DirVertChk[id*nvel+j] = 1;
461  for(n = 0; n < nz_loc; ++n)
462  {
463  graphVertOffset[ReorderedGraphVertId[0][id]*nvel*nz_loc+j*nz_loc + n] *= -1;
464  }
465  }
466 
467  id = bndCondExp[i]->GetExp(k)
468  ->as<LocalRegions::Expansion1D>()
469  ->GetGeom1D()->GetVid(1);
470  if(DirVertChk.count(id*nvel+j) == 0)
471  {
472  DirVertChk[id*nvel+j] = 1;
473  for(n = 0; n < nz_loc; ++n)
474  {
475  graphVertOffset[ReorderedGraphVertId[0][id]*nvel*nz_loc+j*nz_loc+n] *= -1;
476  }
477  }
478 
479  // edges with mixed id;
480  id = bndCondExp[i]->GetExp(k)
481  ->as<LocalRegions::Expansion1D>()
482  ->GetGeom1D()->GetGlobalID();
483  for(n = 0; n < nz_loc; ++n)
484  {
485  graphVertOffset[ReorderedGraphVertId[1][id]*nvel*nz_loc+j*nz_loc +n] *= -1;
486  }
487  }
488  }
489  }
490  }
491  }
492 
493 
494  cnt = 0;
495  // assemble accumulative list of full Dirichlet values.
496  for(i = 0; i < firstNonDirGraphVertId*nvel*nz_loc; ++i)
497  {
498  diff = abs(graphVertOffset[i]);
499  graphVertOffset[i] = cnt;
500  cnt += diff;
501  }
502 
503  // set Dirichlet values with negative values to Dirichlet value
504  for(i = firstNonDirGraphVertId*nvel*nz_loc; i < graphVertOffset.size(); ++i)
505  {
506  if(graphVertOffset[i] < 0)
507  {
508  diff = -graphVertOffset[i];
509  graphVertOffset[i] = -cnt;
510  cnt += diff;
511  }
512  }
513 
514  // Accumulate all interior degrees of freedom with positive values
516 
517  // offset values
518  for(i = firstNonDirGraphVertId*nvel*nz_loc; i < graphVertOffset.size(); ++i)
519  {
520  if(graphVertOffset[i] >= 0)
521  {
522  diff = graphVertOffset[i];
523  graphVertOffset[i] = cnt;
524  cnt += diff;
525  }
526  }
527 
528  // Finally set negative entries (corresponding to Dirichlet
529  // values ) to be positive
530  for(i = firstNonDirGraphVertId*nvel*nz_loc; i < graphVertOffset.size(); ++i)
531  {
532  if(graphVertOffset[i] < 0)
533  {
534  graphVertOffset[i] = -graphVertOffset[i];
535  }
536  }
537 
538 
539  // Allocate the proper amount of space for the class-data and fill
540  // information that is already known
541  cnt = 0;
543  m_numLocalCoeffs = 0;
544 
545  for(i = 0; i < nel; ++i)
546  {
547  m_numLocalBndCoeffs += nz_loc*(nvel*locExpVector[i]->NumBndryCoeffs() + 1);
548  // add these coeffs up separately since
549  // pressure->GetNcoeffs can include the coefficient in
550  // multiple planes.
551  m_numLocalCoeffs += (pressure->GetExp(i)->GetNcoeffs()-1)*nz_loc;
552  }
553 
555 
556 
557  m_localToGlobalMap = Array<OneD, int>(m_numLocalCoeffs,-1);
558  m_localToGlobalBndMap = Array<OneD, int>(m_numLocalBndCoeffs,-1);
559  m_bndCondIDToGlobalTraceID = Array<OneD, int>(nLocBndCondDofs,-1);
560 
561 
562  // Set default sign array.
563  m_localToGlobalSign = Array<OneD, NekDouble>(m_numLocalCoeffs,1.0);
564  m_localToGlobalBndSign = Array<OneD, NekDouble>(m_numLocalBndCoeffs,1.0);
565 
566  m_staticCondLevel = staticCondLevel;
567  m_numPatches = nel;
568 
569  m_numLocalBndCoeffsPerPatch = Array<OneD, unsigned int>(nel);
570  m_numLocalIntCoeffsPerPatch = Array<OneD, unsigned int>(nel);
571 
572  for(i = 0; i < nel; ++i)
573  {
574  m_numLocalBndCoeffsPerPatch[i] = (unsigned int) nz_loc*(nvel*locExpVector[i]->NumBndryCoeffs() + 1);
575  m_numLocalIntCoeffsPerPatch[i] = (unsigned int) nz_loc*(pressure->GetExp(i)->GetNcoeffs()-1);
576  }
577 
578  // Set up local to local bnd and local int maps
579  m_localToLocalBndMap = Array<OneD, int>(m_numLocalBndCoeffs,-1);
580  m_localToLocalIntMap = Array<OneD, int>(m_numLocalCoeffs-
582 
583  int bndcnt = 0;
584  int intcnt = 0;
585  cnt = 0;
586  for(i = 0; i < nel; ++i)
587  {
588  for(j = 0; j < nz_loc*(nvel*locExpVector[i]->NumBndryCoeffs()); ++j)
589  {
590  m_localToLocalBndMap[bndcnt++] = cnt++;
591  }
592 
593  for(n = 0; n < nz_loc; ++n)
594  {
595  m_localToLocalBndMap[bndcnt++] = cnt++;
596  for(j = 1; j < pressure->GetExp(i)->GetNcoeffs(); ++j)
597  {
598  m_localToLocalIntMap[intcnt++] = cnt++;
599  }
600  }
601 
602  }
603 
604  /**
605  * STEP 4: Now, all ingredients are ready to set up the actual
606  * local to global mapping.
607  *
608  * The remainder of the map consists of the element-interior
609  * degrees of freedom. This leads to the block-diagonal submatrix
610  * as each element-interior mode is globally orthogonal to modes
611  * in all other elements.
612  */
613  cnt = 0;
614  int nv,velnbndry;
615  Array<OneD, unsigned int> bmap;
616 
617 
618  // Loop over all the elements in the domain in shuffled
619  // ordering (element type consistency)
620  for(i = 0; i < nel; ++i)
621  {
622  locExpansion = locExpVector[i]->as<LocalRegions::Expansion2D>();
623 
624  velnbndry = locExpansion->NumBndryCoeffs();
625 
626  // Require an inverse ordering of the bmap system to store
627  // local numbering system. Therefore get hold of elemental
628  // bmap and set up an inverse map
629  map<int,int> inv_bmap;
630  locExpansion->GetBoundaryMap(bmap);
631  for(j = 0; j < bmap.size(); ++j)
632  {
633  inv_bmap[bmap[j]] = j;
634  }
635 
636  // Loop over all edges (and vertices) of element i
637  for(j = 0; j < locExpansion->GetNtraces(); ++j)
638  {
639  nEdgeInteriorCoeffs = locExpansion->GetTraceNcoeffs(j)-2;
640  edgeOrient = (locExpansion->GetGeom())->GetEorient(j);
641  meshEdgeId = (locExpansion->GetGeom())->GetEid(j);
642  meshVertId = (locExpansion->GetGeom())->GetVid(j);
643 
644  auto pIt = periodicEdges.find(meshEdgeId);
645 
646  // See if this edge is periodic. If it is, then we map all
647  // edges to the one with lowest ID, and align all
648  // coefficients to this edge orientation.
649  if (pIt != periodicEdges.end())
650  {
651  pair<int, StdRegions::Orientation> idOrient =
653  meshEdgeId, edgeOrient, pIt->second);
654  edgeOrient = idOrient.second;
655  }
656 
657  locExpansion->GetTraceInteriorToElementMap(j,edgeInteriorMap,
658  edgeInteriorSign,edgeOrient);
659 
660  // Set the global DOF for vertex j of element i
661  for(nv = 0; nv < nvel*nz_loc; ++nv)
662  {
663  m_localToGlobalMap[cnt+nv*velnbndry+
664  inv_bmap[locExpansion->GetVertexMap(j)]]
665  = graphVertOffset[ReorderedGraphVertId[0]
666  [meshVertId]*nvel*nz_loc+ nv];
667 
668  // Set the global DOF's for the interior modes of edge j
669  for(k = 0; k < nEdgeInteriorCoeffs; ++k)
670  {
671  m_localToGlobalMap[cnt+nv*velnbndry+
672  inv_bmap[edgeInteriorMap[k]]] =
673  graphVertOffset[ReorderedGraphVertId[1]
674  [meshEdgeId]*nvel*nz_loc+nv]+k;
675  }
676  }
677 
678  // Fill the sign vector if required
679  if(m_signChange)
680  {
681  for(nv = 0; nv < nvel*nz_loc; ++nv)
682  {
683  for(k = 0; k < nEdgeInteriorCoeffs; ++k)
684  {
685  m_localToGlobalSign[cnt+nv*velnbndry +
686  inv_bmap[edgeInteriorMap[k]]]
687  = (NekDouble) edgeInteriorSign[k];
688  }
689  }
690  }
691  }
692 
693  // use difference between two edges of the
694  // AddMeanPressureEdgeId to det nEdgeInteriorCoeffs.
695  nEdgeInteriorCoeffs = graphVertOffset[(ReorderedGraphVertId[1][AddMeanPressureToEdgeId[i]])*nvel*nz_loc+1] - graphVertOffset[(ReorderedGraphVertId[1][AddMeanPressureToEdgeId[i]])*nvel*nz_loc];
696 
697  int psize = pressure->GetExp(i)->GetNcoeffs();
698  for(n = 0; n < nz_loc; ++n)
699  {
700  m_localToGlobalMap[cnt + nz_loc*nvel*velnbndry + n*psize] =
701  graphVertOffset[(ReorderedGraphVertId[1]
702  [AddMeanPressureToEdgeId[i]]+1)*nvel*nz_loc-1]+
703  nEdgeInteriorCoeffs +
704  pressureEdgeOffset[AddMeanPressureToEdgeId[i]];
705 
706  pressureEdgeOffset[AddMeanPressureToEdgeId[i]] += 1;
707  }
708 
709  cnt += (velnbndry*nvel+ psize)*nz_loc;
710  }
711 
712  // Set up the mapping for the boundary conditions
713  offset = cnt = 0;
714  for(nv = 0; nv < nvel; ++nv)
715  {
716  for(i = 0; i < bndCondExp.size(); i++)
717  {
718  if (bndConditionsVec[nv][i]->GetBoundaryConditionType()==
720  {
721  continue;
722  }
723 
724  for(n = 0; n < nz_loc; ++n)
725  {
726  int ncoeffcnt = 0;
727  for(j = 0; j < bndCondExp[i]->GetNumElmts(); j++)
728  {
729  bndSegExp = bndCondExp[i]->GetExp(j)
730  ->as<LocalRegions::SegExp>();
731 
732  cnt = offset + bndCondExp[i]->GetCoeff_Offset(j);
733  for(k = 0; k < 2; k++)
734  {
735  meshVertId = (bndSegExp->GetGeom1D())->GetVid(k);
737  bndSegExp->GetVertexMap(k)] =
738  graphVertOffset[ReorderedGraphVertId[0]
739  [meshVertId]*nvel*nz_loc+nv*nz_loc+n];
740  }
741 
742  meshEdgeId = (bndSegExp->GetGeom1D())->GetGlobalID();
743  bndEdgeCnt = 0;
744  nEdgeCoeffs = bndSegExp->GetNcoeffs();
745  for(k = 0; k < nEdgeCoeffs; k++)
746  {
747  if(m_bndCondIDToGlobalTraceID[cnt+k] == -1)
748  {
750  graphVertOffset[ReorderedGraphVertId[1]
751  [meshEdgeId]*nvel*nz_loc+nv*nz_loc+n]+bndEdgeCnt;
752  bndEdgeCnt++;
753  }
754  }
755  ncoeffcnt += nEdgeCoeffs;
756  }
757  // Note: Can not use bndCondExp[i]->GetNcoeffs()
758  // due to homogeneous extension not returning just
759  // the value per plane
760  offset += ncoeffcnt;
761  }
762  }
763  }
764 
765  globalId = Vmath::Vmax(m_numLocalCoeffs,&m_localToGlobalMap[0],1)+1;
766  m_numGlobalBndCoeffs = globalId;
767 
768  /**
769  * STEP 5: The boundary condition mapping is generated from the
770  * same vertex renumbering and fill in a unique interior map.
771  */
772  cnt=0;
773  for(i = 0; i < m_numLocalCoeffs; ++i)
774  {
775  if(m_localToGlobalMap[i] == -1)
776  {
777  m_localToGlobalMap[i] = globalId++;
778  }
779  else
780  {
781  if(m_signChange)
782  {
784  }
786  }
787  }
788  m_numGlobalCoeffs = globalId;
789 
790  // Set up the local to global map for the next level when using
791  // multi-level static condensation
792  if( m_session->MatchSolverInfoAsEnum("GlobalSysSoln", MultiRegions::eDirectMultiLevelStaticCond) )
793  {
794  if (m_staticCondLevel < (bottomUpGraph->GetNlevels()-1))
795  {
796  Array<OneD, int> vwgts_perm(
797  Dofs[0].size()+Dofs[1].size()-firstNonDirGraphVertId);
798  for(i = 0; i < locExpVector.size(); ++i)
799  {
800  locExpansion = locExpVector[i]->as<LocalRegions::Expansion2D>();
801  for(j = 0; j < locExpansion->GetNverts(); ++j)
802  {
803  meshEdgeId = (locExpansion->GetGeom2D())->GetEid(j);
804  meshVertId = (locExpansion->GetGeom2D())->GetVid(j);
805 
806  if(ReorderedGraphVertId[0][meshVertId] >=
807  firstNonDirGraphVertId)
808  {
809  vwgts_perm[ReorderedGraphVertId[0][meshVertId]-
810  firstNonDirGraphVertId] =
811  Dofs[0][meshVertId];
812  }
813 
814  if(ReorderedGraphVertId[1][meshEdgeId] >=
815  firstNonDirGraphVertId)
816  {
817  vwgts_perm[ReorderedGraphVertId[1][meshEdgeId]-
818  firstNonDirGraphVertId] =
819  Dofs[1][meshEdgeId];
820  }
821  }
822  }
823 
824  bottomUpGraph->ExpandGraphWithVertexWeights(vwgts_perm);
825 
827  AllocateSharedPtr(this,bottomUpGraph);
828  }
829  }
830  }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
void FindEdgeIdToAddMeanPressure(std::vector< std::map< int, int > > &ReorderedGraphVertId, int &nel, const LocalRegions::ExpansionVector &locExpVector, int &edgeId, int &vertId, int &firstNonDirGraphVertId, std::map< int, int > &IsDirEdgeDof, MultiRegions::BottomUpSubStructuredGraphSharedPtr &bottomUpGraph, Array< OneD, int > &AddMeanPressureToEdgeId)
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
int CreateGraph(const ExpList &locExp, const BndCondExp &bndCondExp, const Array< OneD, const BndCond > &bndConditions, const bool checkIfSystemSingular, const PeriodicMap &periodicVerts, const PeriodicMap &periodicEdges, const PeriodicMap &periodicFaces, DofGraph &graph, BottomUpSubStructuredGraphSharedPtr &bottomUpGraph, std::set< int > &extraDirVerts, std::set< int > &extraDirEdges, int &firstNonDirGraphVertId, int &nExtraDirichlet, int mdswitch=1)
Array< OneD, NekDouble > m_localToGlobalSign
Integer sign of local coeffs to global space.
AssemblyMapCG(const LibUtilities::SessionReaderSharedPtr &pSession, const std::string variable="DefaultVar")
Default constructor.
Array< OneD, int > m_localToGlobalMap
Integer map of local coeffs to global space.
int m_numLocalCoeffs
Total number of local coefficients.
Definition: AssemblyMap.h:357
bool m_signChange
Flag indicating if modes require sign reversal.
Definition: AssemblyMap.h:371
int m_numGlobalCoeffs
Total number of global coefficients.
Definition: AssemblyMap.h:368
Array< OneD, int > m_localToGlobalBndMap
Integer map of local coeffs to global Boundary Dofs.
Definition: AssemblyMap.h:374
Array< OneD, unsigned int > m_numLocalBndCoeffsPerPatch
The number of bnd dofs per patch.
Definition: AssemblyMap.h:425
LibUtilities::SessionReaderSharedPtr m_session
Session object.
Definition: AssemblyMap.h:329
int m_numLocalBndCoeffs
Number of local boundary coefficients.
Definition: AssemblyMap.h:338
AssemblyMapSharedPtr m_nextLevelLocalToGlobalMap
Map from the patches of the previous level to the patches of the current level.
Definition: AssemblyMap.h:432
int m_staticCondLevel
The level of recursion in the case of multi-level static condensation.
Definition: AssemblyMap.h:421
Array< OneD, NekDouble > m_localToGlobalBndSign
Integer sign of local boundary coeffs to global space.
Definition: AssemblyMap.h:376
Array< OneD, int > m_localToLocalIntMap
Integer map of local boundary coeffs to local interior system numbering.
Definition: AssemblyMap.h:380
int m_numLocalDirBndCoeffs
Number of Local Dirichlet Boundary Coefficients.
Definition: AssemblyMap.h:342
int m_numGlobalDirBndCoeffs
Number of Global Dirichlet Boundary Coefficients.
Definition: AssemblyMap.h:344
Array< OneD, unsigned int > m_numLocalIntCoeffsPerPatch
The number of int dofs per patch.
Definition: AssemblyMap.h:427
bool m_systemSingular
Flag indicating if the system is singular or not.
Definition: AssemblyMap.h:346
Array< OneD, int > m_localToLocalBndMap
Integer map of local boundary coeffs to local boundary system numbering.
Definition: AssemblyMap.h:378
int m_numPatches
The number of patches (~elements) in the current level.
Definition: AssemblyMap.h:423
Array< OneD, int > m_bndCondIDToGlobalTraceID
Integer map of bnd cond trace number to global trace number.
Definition: AssemblyMap.h:388
int m_numGlobalBndCoeffs
Total number of global boundary coefficients.
Definition: AssemblyMap.h:340
@ eModified_A
Principle Modified Functions .
Definition: BasisType.h:48
std::shared_ptr< SegExp > SegExpSharedPtr
Definition: SegExp.h:272
std::shared_ptr< Expansion2D > Expansion2DSharedPtr
Definition: Expansion1D.h:47
std::vector< ExpansionSharedPtr > ExpansionVector
Definition: Expansion.h:70
std::shared_ptr< Expansion1D > Expansion1DSharedPtr
Definition: Expansion1D.h:51
std::shared_ptr< BottomUpSubStructuredGraph > BottomUpSubStructuredGraphSharedPtr
pair< int, StdRegions::Orientation > DeterminePeriodicEdgeOrientId(int meshEdgeId, StdRegions::Orientation edgeOrient, const vector< PeriodicEntity > &periodicEdges)
Determine orientation of an edge to its periodic equivalents, as well as the ID of the representative...
std::map< int, std::vector< PeriodicEntity > > PeriodicMap
static const NekDouble kNekZeroTol
std::shared_ptr< Geometry1D > Geometry1DSharedPtr
Definition: Geometry.h:63
double NekDouble
T Vmax(int n, const T *x, const int incx)
Return the maximum element in x – called vmax to avoid conflict with max.
Definition: Vmath.cpp:892
scalarT< T > abs(scalarT< T > in)
Definition: scalar.hpp:272

References tinysimd::abs(), Nektar::MemoryManager< DataType >::AllocateSharedPtr(), ASSERTL0, Nektar::MultiRegions::AssemblyMapCG::CreateGraph(), Nektar::MultiRegions::DeterminePeriodicEdgeOrientId(), Nektar::MultiRegions::eDirectMultiLevelStaticCond, Nektar::SpatialDomains::eDirichlet, Nektar::LibUtilities::eModified_A, Nektar::SpatialDomains::ePeriodic, FindEdgeIdToAddMeanPressure(), Nektar::StdRegions::StdExpansion::GetNcoeffs(), Nektar::StdRegions::StdExpansion::GetTraceNcoeffs(), Nektar::StdRegions::StdExpansion::GetVertexMap(), Nektar::NekConstants::kNekZeroTol, Nektar::MultiRegions::AssemblyMap::m_bndCondIDToGlobalTraceID, Nektar::MultiRegions::AssemblyMap::m_localToGlobalBndMap, Nektar::MultiRegions::AssemblyMap::m_localToGlobalBndSign, Nektar::MultiRegions::AssemblyMapCG::m_localToGlobalMap, Nektar::MultiRegions::AssemblyMapCG::m_localToGlobalSign, Nektar::MultiRegions::AssemblyMap::m_localToLocalBndMap, Nektar::MultiRegions::AssemblyMap::m_localToLocalIntMap, Nektar::MultiRegions::AssemblyMap::m_nextLevelLocalToGlobalMap, Nektar::MultiRegions::AssemblyMap::m_numGlobalBndCoeffs, Nektar::MultiRegions::AssemblyMap::m_numGlobalCoeffs, Nektar::MultiRegions::AssemblyMap::m_numGlobalDirBndCoeffs, Nektar::MultiRegions::AssemblyMap::m_numLocalBndCoeffs, Nektar::MultiRegions::AssemblyMap::m_numLocalBndCoeffsPerPatch, Nektar::MultiRegions::AssemblyMap::m_numLocalCoeffs, Nektar::MultiRegions::AssemblyMap::m_numLocalDirBndCoeffs, Nektar::MultiRegions::AssemblyMap::m_numLocalIntCoeffsPerPatch, Nektar::MultiRegions::AssemblyMap::m_numPatches, Nektar::MultiRegions::AssemblyMap::m_session, Nektar::MultiRegions::AssemblyMap::m_signChange, Nektar::MultiRegions::AssemblyMap::m_staticCondLevel, Nektar::MultiRegions::AssemblyMap::m_systemSingular, Nektar::StdRegions::StdExpansion::NumBndryCoeffs(), CG_Iterations::pressure, and Vmath::Vmax().

Member Function Documentation

◆ FindEdgeIdToAddMeanPressure()

void Nektar::CoupledLocalToGlobalC0ContMap::FindEdgeIdToAddMeanPressure ( std::vector< std::map< int, int > > &  ReorderedGraphVertId,
int &  nel,
const LocalRegions::ExpansionVector locExpVector,
int &  edgeId,
int &  vertId,
int &  firstNonDirGraphVertId,
std::map< int, int > &  IsDirEdgeDof,
MultiRegions::BottomUpSubStructuredGraphSharedPtr bottomUpGraph,
Array< OneD, int > &  AddMeanPressureToEdgeId 
)

Definition at line 834 of file CoupledLocalToGlobalC0ContMap.cpp.

839 {
840 
841  int i,j,k;
842 
843  // Make list of homogeneous graph edges to elmt mappings
844  Array<TwoD, int> EdgeIdToElmts(ReorderedGraphVertId[1].size(),2,-1);
845  map<int,int> HomGraphEdgeIdToEdgeId;
846 
847  for(i = 0; i < nel; ++i)
848  {
849  for(j = 0; j < locExpVector[i]->GetNverts(); ++j)
850  {
851  edgeId = (locExpVector[i]->as<LocalRegions::Expansion2D>()
852  ->GetGeom2D())->GetEid(j);
853 
854  // note second condition stops us using mixed boundary condition
855  if((ReorderedGraphVertId[1][edgeId] >= firstNonDirGraphVertId)
856  && (IsDirEdgeDof.count(edgeId) == 0))
857  {
858  HomGraphEdgeIdToEdgeId[ReorderedGraphVertId[1][edgeId]-firstNonDirGraphVertId] = edgeId;
859 
860  if(EdgeIdToElmts[edgeId][0] == -1)
861  {
862  EdgeIdToElmts[edgeId][0] = i;
863  }
864  else
865  {
866  EdgeIdToElmts[edgeId][1] = i;
867  }
868  }
869  }
870  }
871 
872  // Start at second to last level and find edge on boundary
873  // to attach element
874  int nlevels = bottomUpGraph->GetNlevels();
875 
876  // determine a default edge to attach pressure modes to
877  // which is part of the inner solve;
878  int defedge = -1;
879 
880  vector<MultiRegions::SubGraphSharedPtr> bndgraphs = bottomUpGraph->GetInteriorBlocks(nlevels);
881  for(i = 0; i < bndgraphs.size(); ++i)
882  {
883  int GlobIdOffset = bndgraphs[i]->GetIdOffset();
884 
885  for(j = 0; j < bndgraphs[i]->GetNverts(); ++j)
886  {
887  // find edge in graph vert list
888  if(HomGraphEdgeIdToEdgeId.count(GlobIdOffset+j) != 0)
889  {
890  edgeId = HomGraphEdgeIdToEdgeId[GlobIdOffset+j];
891 
892  if(defedge == -1)
893  {
894  defedge = edgeId;
895  break;
896  }
897  }
898  }
899  if(defedge != -1)
900  {
901  break;
902  }
903  }
904 
905  for(int n = 1; n < nlevels; ++n)
906  {
907  // produce a map with a key that is the element id
908  // that contains which next level patch it belongs to
909  vector<MultiRegions::SubGraphSharedPtr> bndgraphs = bottomUpGraph->GetInteriorBlocks(n+1);
910 
911  // Fill next level graph of adjacent elements and their level
912  map<int,int> ElmtInBndry;
913 
914  for(i = 0; i < bndgraphs.size(); ++i)
915  {
916  int GlobIdOffset = bndgraphs[i]->GetIdOffset();
917 
918  for(j = 0; j < bndgraphs[i]->GetNverts(); ++j)
919  {
920  // find edge in graph vert list
921  if(HomGraphEdgeIdToEdgeId.count(GlobIdOffset+j) != 0)
922  {
923  edgeId = HomGraphEdgeIdToEdgeId[GlobIdOffset+j];
924 
925  if(EdgeIdToElmts[edgeId][0] != -1)
926  {
927  ElmtInBndry[EdgeIdToElmts[edgeId][0]] = i;
928  }
929  if(EdgeIdToElmts[edgeId][1] != -1)
930  {
931  ElmtInBndry[EdgeIdToElmts[edgeId][1]] = i;
932  }
933  }
934  }
935  }
936 
937  // Now search interior patches in this level for edges
938  // that share the same element as a boundary edge and
939  // assign this elmt that boundary edge
940  vector<MultiRegions::SubGraphSharedPtr> intgraphs = bottomUpGraph->GetInteriorBlocks(n);
941  for(i = 0; i < intgraphs.size(); ++i)
942  {
943  int GlobIdOffset = intgraphs[i]->GetIdOffset();
944  bool SetEdge = false;
945  int elmtid = 0;
946  for(j = 0; j < intgraphs[i]->GetNverts(); ++j)
947  {
948  // Check to see if graph vert is an edge
949  if(HomGraphEdgeIdToEdgeId.count(GlobIdOffset+j) != 0)
950  {
951  edgeId = HomGraphEdgeIdToEdgeId[GlobIdOffset+j];
952 
953  for(k = 0; k < 2; ++k)
954  {
955  // relevant edge id
956  elmtid = EdgeIdToElmts[edgeId][k];
957 
958  if(elmtid != -1)
959  {
960  auto mapIt = ElmtInBndry.find(elmtid);
961 
962  if(mapIt != ElmtInBndry.end())
963  {
964  // now find a edge in the next level boundary graph
965  int GlobIdOffset1 = bndgraphs[mapIt->second]->GetIdOffset();
966  for(int l = 0; l < bndgraphs[mapIt->second]->GetNverts(); ++l)
967  {
968  // find edge in graph vert list
969  if(HomGraphEdgeIdToEdgeId.count(GlobIdOffset1+l) != 0)
970  {
971  //June 2012: commenting this condition apparently
972  //solved the bug caused by the edge reordering procedure
973 
974  //if(AddMeanPressureToEdgeId[elmtid] == -1)
975  //{
976 
977  //AddMeanPressureToEdgeId[elmtid] = HomGraphEdgeIdToEdgeId[GlobIdOffset1+l];
978  AddMeanPressureToEdgeId[elmtid] = defedge;
979 
980  //}
981  SetEdge = true;
982  break;
983  }
984  }
985  }
986  }
987  }
988  }
989  }
990 
991 
992  // if we have failed to find matching edge in next
993  // level patch boundary then set last found elmt
994  // associated to this interior patch to the
995  // default edget value
996  if(SetEdge == false)
997  {
998  if(elmtid == -1) // find an elmtid in patch
999  {
1000  for(j = 0; j < intgraphs[i]->GetNverts(); ++j)
1001  {
1002  if(HomGraphEdgeIdToEdgeId.count(GlobIdOffset+j) != 0)
1003  {
1004  edgeId = HomGraphEdgeIdToEdgeId[GlobIdOffset+j];
1005  for(k = 0; k < 2; ++k)
1006  {
1007  // relevant edge id
1008  elmtid = EdgeIdToElmts[edgeId][k];
1009  if(elmtid != -1)
1010  {
1011  break;
1012  }
1013  }
1014  }
1015  if(elmtid != -1)
1016  {
1017  break;
1018  }
1019  }
1020  }
1021  if(AddMeanPressureToEdgeId[elmtid] == -1)
1022  {
1023  AddMeanPressureToEdgeId[elmtid] = defedge;
1024  }
1025  }
1026  }
1027  }
1028 
1029 }

Referenced by CoupledLocalToGlobalC0ContMap().