Nektar++
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::map< int, std::vector< ExtraDirDof > > & GetExtraDirDofs ()
 
- 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
 
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...
 
int GetBndCondCoeffsToGlobalCoeffsMap (const int i)
 Retrieves the global index corresponding to a boundary expansion mode. More...
 
const Array< OneD, const int > & GetBndCondCoeffsToGlobalCoeffsMap ()
 Retrieves the global indices corresponding to the boundary expansion modes. More...
 
NekDouble GetBndCondCoeffsToGlobalCoeffsSign (const int i)
 Returns the modal sign associated with a given boundary expansion mode. More...
 
int GetBndCondTraceToGlobalTraceMap (const int i)
 Returns the global index of the boundary trace giving the index on the boundary expansion. More...
 
const Array< OneD, const int > & GetBndCondTraceToGlobalTraceMap ()
 
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 NekVector< NekDouble > &loc, NekVector< NekDouble > &global, int offset) const
 
void LocalBndToGlobal (const NekVector< NekDouble > &loc, NekVector< NekDouble > &global) const
 
void LocalBndToGlobal (const Array< OneD, const NekDouble > &loc, Array< OneD, NekDouble > &global, int offset) const
 
void LocalBndToGlobal (const Array< OneD, const NekDouble > &loc, Array< OneD, NekDouble > &global) 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
 
int GetLowestStaticCondLevel () 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::map< int, std::vector< ExtraDirDof > > m_extraDirDofs
 Map indicating degrees of freedom which are Dirichlet but whose value is stored on another processor. 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 boundary coeffs to global space. More...
 
Array< OneD, NekDoublem_localToGlobalBndSign
 Integer sign of local boundary coeffs to global space. More...
 
Array< OneD, int > m_bndCondCoeffsToGlobalCoeffsMap
 Integer map of bnd cond coeffs to global coefficients. More...
 
Array< OneD, NekDoublem_bndCondCoeffsToGlobalCoeffsSign
 Integer map of bnd cond coeffs to global coefficients. More...
 
Array< OneD, int > m_bndCondTraceToGlobalTraceMap
 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...
 
Gs::gs_datam_gsh
 
Gs::gs_datam_bndGsh
 
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

: 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.

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), ASSERTL0, Nektar::MultiRegions::AssemblyMapCG::CreateGraph(), Nektar::MultiRegions::DeterminePeriodicEdgeOrientId(), Nektar::MultiRegions::eDirectMultiLevelStaticCond, Nektar::SpatialDomains::eDirichlet, Nektar::LibUtilities::eModified_A, Nektar::LibUtilities::eModified_B, Nektar::SpatialDomains::ePeriodic, FindEdgeIdToAddMeanPressure(), Nektar::StdRegions::StdExpansion::GetEdgeNcoeffs(), Nektar::StdRegions::StdExpansion::GetNcoeffs(), Nektar::StdRegions::StdExpansion::GetVertexMap(), Nektar::NekConstants::kNekZeroTol, Nektar::MultiRegions::AssemblyMap::m_bndCondCoeffsToGlobalCoeffsMap, Nektar::MultiRegions::AssemblyMap::m_localToGlobalBndMap, Nektar::MultiRegions::AssemblyMap::m_localToGlobalBndSign, Nektar::MultiRegions::AssemblyMapCG::m_localToGlobalMap, Nektar::MultiRegions::AssemblyMapCG::m_localToGlobalSign, 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(), and Vmath::Vmax().

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.num_elements();
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.num_elements(); ++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()->GetEdgeNormal(loc_exp->GetLeftAdjacentElementEdge());
172  //locnorm = bndCondExp[j]->GetExp(k)->Get GetMetricInfo()->GetNormal();
173 
174  int ndir = locnorm.num_elements();
175  if(i < ndir) // account for Fourier version where n can be larger then ndir
176  {
177  for(int l = 0; l < locnorm[0].num_elements(); ++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].num_elements(); ++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]->GetEdgeNcoeffs(j)-2)*nz_loc;
267  }
268 
269  // Adjust for Dirichlet boundary conditions to give number to be solved
270  if(IsDirEdgeDof.count(edgeId) != 0)
271  {
272  Dofs[1][edgeId] -= IsDirEdgeDof[edgeId]*nz_loc*(locExpVector[i]->GetEdgeNcoeffs(j)-2);
273  }
274  }
275  }
276 
277  set<int> extraDirVerts, extraDirEdges;
278 
279  CreateGraph(*fields[0], bndCondExp, bndConditionsVec, false,
280  periodicVerts, periodicEdges, periodicFaces,
281  ReorderedGraphVertId, bottomUpGraph, extraDirVerts,
282  extraDirEdges, firstNonDirGraphVertId, nExtraDirichlet, 4);
283  /*
284  SetUp2DGraphC0ContMap(*fields[0],
285  bndCondExp,
286  bndConditionsVec,
287  periodicVerts, periodicEdges,
288  Dofs, ReorderedGraphVertId,
289  firstNonDirGraphVertId, nExtraDirichlet,
290  bottomUpGraph, extraDir, false, 4);
291  */
292 
293  /**
294  * STEP 2a: Set the mean pressure modes to edges depending on
295  * type of direct solver technique;
296  */
297 
298  // determine which edge to add mean pressure dof based on
299  // ensuring that at least one pressure dof from an internal
300  // patch is associated with its boundary system
301  if(m_session->MatchSolverInfoAsEnum("GlobalSysSoln", MultiRegions::eDirectMultiLevelStaticCond))
302  {
303 
304 
305  FindEdgeIdToAddMeanPressure(ReorderedGraphVertId,
306  nel, locExpVector,
307  edgeId, vertId, firstNonDirGraphVertId, IsDirEdgeDof,
308  bottomUpGraph,
309  AddMeanPressureToEdgeId);
310  }
311 
312  // Set unset elmts to non-Dirichlet edges.
313  // special case of singular problem - need to fix one
314  // pressure dof to a dirichlet edge
315  for(i = 0; i < nel; ++i)
316  {
317  for(j = 0; j < locExpVector[i]->GetNverts(); ++j)
318  {
319  edgeId = (locExpVector[i]->as<LocalRegions::Expansion2D>()
320  ->GetGeom2D())->GetEid(j);
321 
322  if(IsDirEdgeDof.count(edgeId) == 0) // interior edge
323  {
324  // setup AddMeanPressureToEdgeId to decide where to
325  // put pressure
326  if(AddMeanPressureToEdgeId[i] == -1)
327  {
328  AddMeanPressureToEdgeId[i] = edgeId;
329  }
330  }
331  }
332  ASSERTL0((AddMeanPressureToEdgeId[i] != -1),"Did not determine "
333  "an edge to attach mean pressure dof");
334  // Add the mean pressure degree of freedom to this edge
335  Dofs[1][AddMeanPressureToEdgeId[i]] += nz_loc;
336  }
337 
338  map<int,int> pressureEdgeOffset;
339 
340  /**
341  * STEP 2: Count out the number of Dirichlet vertices and edges first
342  */
343  for(i = 0; i < bndCondExp.num_elements(); i++)
344  {
345  for(j = 0; j < bndCondExp[i]->GetNumElmts(); j++)
346  {
347  bndSegExp = bndCondExp[i]->GetExp(j)
348  ->as<LocalRegions::SegExp>();
349  for(k = 0; k < nvel; ++k)
350  {
351  if(bndConditionsVec[k][i]->GetBoundaryConditionType()==SpatialDomains::eDirichlet)
352  {
353  nLocDirBndCondDofs += bndSegExp->GetNcoeffs()*nz_loc;
354  }
355 
356  if (bndConditionsVec[k][i]->GetBoundaryConditionType()!=SpatialDomains::ePeriodic)
357  {
358  nLocBndCondDofs += bndSegExp->GetNcoeffs()*nz_loc;
359  }
360  }
361  }
362  }
363 
364  if(m_systemSingular)
365  {
366  m_numLocalDirBndCoeffs = nLocDirBndCondDofs+nExtraDirichlet+nz_loc;
367  }
368  else
369  {
370  m_numLocalDirBndCoeffs = nLocDirBndCondDofs+nExtraDirichlet;
371  }
372 
373  /**
374  * STEP 3: Set up an array which contains the offset information of
375  * the different graph vertices.
376  *
377  * This basically means to identify how many global degrees of
378  * freedom the individual graph vertices correspond. Obviously,
379  * the graph vertices corresponding to the mesh-vertices account
380  * for a single global DOF. However, the graph vertices
381  * corresponding to the element edges correspond to 2*(N-2) global DOF
382  * where N is equal to the number of boundary modes on this edge.
383  */
384  Array<OneD, int> graphVertOffset(nvel*nz_loc*(ReorderedGraphVertId[0].size() + ReorderedGraphVertId[1].size()),0);
385  graphVertOffset[0] = 0;
386 
387  m_signChange = false;
388 
389  for(i = 0; i < nel; ++i)
390  {
391  locExpansion = locExpVector[i]->as<StdRegions::StdExpansion2D>();
392 
393  for(j = 0; j < locExpansion->GetNedges(); ++j)
394  {
395  nEdgeCoeffs = locExpansion->GetEdgeNcoeffs(j);
396  meshEdgeId = (locExpansion->as<LocalRegions::Expansion2D>()
397  ->GetGeom2D())->GetEid(j);
398  meshVertId = (locExpansion->as<LocalRegions::Expansion2D>()
399  ->GetGeom2D())->GetVid(j);
400 
401  for(k = 0; k < nvel*nz_loc; ++k)
402  {
403  graphVertOffset[ReorderedGraphVertId[0][meshVertId]*nvel*nz_loc+k] = 1;
404  graphVertOffset[ReorderedGraphVertId[1][meshEdgeId]*nvel*nz_loc+k] = (nEdgeCoeffs-2);
405  }
406 
407  bType = locExpansion->GetEdgeBasisType(j);
408  // need a sign vector for modal expansions if nEdgeCoeffs >=4
409  if( (nEdgeCoeffs >= 4)&&
410  ( (bType == LibUtilities::eModified_A)||
411  (bType == LibUtilities::eModified_B) ) )
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].num_elements(); ++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.num_elements(); ++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.num_elements(); ++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.num_elements(); ++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 
554  m_numLocalCoeffs += m_numLocalBndCoeffs;
555 
556 
557  m_localToGlobalMap = Array<OneD, int>(m_numLocalCoeffs,-1);
558  m_localToGlobalBndMap = Array<OneD, int>(m_numLocalBndCoeffs,-1);
559  m_bndCondCoeffsToGlobalCoeffsMap = 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  /**
579  * STEP 4: Now, all ingredients are ready to set up the actual
580  * local to global mapping.
581  *
582  * The remainder of the map consists of the element-interior
583  * degrees of freedom. This leads to the block-diagonal submatrix
584  * as each element-interior mode is globally orthogonal to modes
585  * in all other elements.
586  */
587  cnt = 0;
588  int nv,velnbndry;
589  Array<OneD, unsigned int> bmap;
590 
591 
592  // Loop over all the elements in the domain in shuffled
593  // ordering (element type consistency)
594  for(i = 0; i < nel; ++i)
595  {
596  locExpansion = locExpVector[i]->as<StdRegions::StdExpansion2D>();
597 
598  velnbndry = locExpansion->NumBndryCoeffs();
599 
600  // require an inverse ordering of the bmap system to store
601  // local numbering system which takes matrix these
602  // matrices. Therefore get hold of elemental bmap and set
603  // up an inverse map
604  map<int,int> inv_bmap;
605  locExpansion->GetBoundaryMap(bmap);
606  for(j = 0; j < bmap.num_elements(); ++j)
607  {
608  inv_bmap[bmap[j]] = j;
609  }
610 
611  // Loop over all edges (and vertices) of element i
612  for(j = 0; j < locExpansion->GetNedges(); ++j)
613  {
614  nEdgeInteriorCoeffs = locExpansion->GetEdgeNcoeffs(j)-2;
615  edgeOrient = (locExpansion->as<LocalRegions::Expansion2D>()
616  ->GetGeom2D())->GetEorient(j);
617  meshEdgeId = (locExpansion->as<LocalRegions::Expansion2D>()
618  ->GetGeom2D())->GetEid(j);
619  meshVertId = (locExpansion->as<LocalRegions::Expansion2D>()
620  ->GetGeom2D())->GetVid(j);
621 
622  auto pIt = periodicEdges.find(meshEdgeId);
623 
624  // See if this edge is periodic. If it is, then we map all
625  // edges to the one with lowest ID, and align all
626  // coefficients to this edge orientation.
627  if (pIt != periodicEdges.end())
628  {
629  pair<int, StdRegions::Orientation> idOrient =
631  meshEdgeId, edgeOrient, pIt->second);
632  edgeOrient = idOrient.second;
633  }
634 
635  locExpansion->GetEdgeInteriorMap(j,edgeOrient,edgeInteriorMap,edgeInteriorSign);
636  // Set the global DOF for vertex j of element i
637 
638  for(nv = 0; nv < nvel*nz_loc; ++nv)
639  {
640  m_localToGlobalMap[cnt+nv*velnbndry+inv_bmap[locExpansion->GetVertexMap(j)]] = graphVertOffset[ReorderedGraphVertId[0][meshVertId]*nvel*nz_loc+ nv];
641  // Set the global DOF's for the interior modes of edge j
642  for(k = 0; k < nEdgeInteriorCoeffs; ++k)
643  {
644  m_localToGlobalMap[cnt+nv*velnbndry+inv_bmap[edgeInteriorMap[k]]] = graphVertOffset[ReorderedGraphVertId[1][meshEdgeId]*nvel*nz_loc+nv]+k;
645  }
646  }
647 
648  // Fill the sign vector if required
649  if(m_signChange)
650  {
651  for(nv = 0; nv < nvel*nz_loc; ++nv)
652  {
653  for(k = 0; k < nEdgeInteriorCoeffs; ++k)
654  {
655  m_localToGlobalSign[cnt+nv*velnbndry + inv_bmap[edgeInteriorMap[k]]] = (NekDouble) edgeInteriorSign[k];
656  }
657  }
658  }
659  }
660 
661  // use difference between two edges of the AddMeanPressureEdgeId to det nEdgeInteriorCoeffs.
662  nEdgeInteriorCoeffs = graphVertOffset[(ReorderedGraphVertId[1][AddMeanPressureToEdgeId[i]])*nvel*nz_loc+1] - graphVertOffset[(ReorderedGraphVertId[1][AddMeanPressureToEdgeId[i]])*nvel*nz_loc];
663 
664  int psize = pressure->GetExp(i)->GetNcoeffs();
665  for(n = 0; n < nz_loc; ++n)
666  {
667  m_localToGlobalMap[cnt + nz_loc*nvel*velnbndry + n*psize] = graphVertOffset[(ReorderedGraphVertId[1][AddMeanPressureToEdgeId[i]]+1)*nvel*nz_loc-1]+nEdgeInteriorCoeffs + pressureEdgeOffset[AddMeanPressureToEdgeId[i]];
668 
669  pressureEdgeOffset[AddMeanPressureToEdgeId[i]] += 1;
670  }
671 
672  cnt += (velnbndry*nvel+ psize)*nz_loc;
673  }
674 
675  // Set up the mapping for the boundary conditions
676  offset = cnt = 0;
677  for(nv = 0; nv < nvel; ++nv)
678  {
679  for(i = 0; i < bndCondExp.num_elements(); i++)
680  {
681  if (bndConditionsVec[nv][i]->GetBoundaryConditionType()==SpatialDomains::ePeriodic)
682  {
683  continue;
684  }
685 
686  for(n = 0; n < nz_loc; ++n)
687  {
688  int ncoeffcnt = 0;
689  for(j = 0; j < bndCondExp[i]->GetNumElmts(); j++)
690  {
691  bndSegExp = bndCondExp[i]->GetExp(j)
692  ->as<LocalRegions::SegExp>();
693 
694  cnt = offset + bndCondExp[i]->GetCoeff_Offset(j);
695  for(k = 0; k < 2; k++)
696  {
697  meshVertId = (bndSegExp->GetGeom1D())->GetVid(k);
698  m_bndCondCoeffsToGlobalCoeffsMap[cnt+bndSegExp->GetVertexMap(k)] = graphVertOffset[ReorderedGraphVertId[0][meshVertId]*nvel*nz_loc+nv*nz_loc+n];
699  }
700 
701  meshEdgeId = (bndSegExp->GetGeom1D())->GetGlobalID();
702  bndEdgeCnt = 0;
703  nEdgeCoeffs = bndSegExp->GetNcoeffs();
704  for(k = 0; k < nEdgeCoeffs; k++)
705  {
706  if(m_bndCondCoeffsToGlobalCoeffsMap[cnt+k] == -1)
707  {
709  graphVertOffset[ReorderedGraphVertId[1][meshEdgeId]*nvel*nz_loc+nv*nz_loc+n]+bndEdgeCnt;
710  bndEdgeCnt++;
711  }
712  }
713  ncoeffcnt += nEdgeCoeffs;
714  }
715  // Note: Can not use bndCondExp[i]->GetNcoeffs()
716  // due to homogeneous extension not returning just
717  // the value per plane
718  offset += ncoeffcnt;
719  }
720  }
721  }
722 
723  globalId = Vmath::Vmax(m_numLocalCoeffs,&m_localToGlobalMap[0],1)+1;
724  m_numGlobalBndCoeffs = globalId;
725 
726  /**
727  * STEP 5: The boundary condition mapping is generated from the
728  * same vertex renumbering and fill in a unique interior map.
729  */
730  cnt=0;
731  for(i = 0; i < m_numLocalCoeffs; ++i)
732  {
733  if(m_localToGlobalMap[i] == -1)
734  {
735  m_localToGlobalMap[i] = globalId++;
736  }
737  else
738  {
739  if(m_signChange)
740  {
742  }
744  }
745  }
746  m_numGlobalCoeffs = globalId;
747 
748  // Set up the local to global map for the next level when using
749  // multi-level static condensation
750  if( m_session->MatchSolverInfoAsEnum("GlobalSysSoln", MultiRegions::eDirectMultiLevelStaticCond) )
751  {
752  if (m_staticCondLevel < (bottomUpGraph->GetNlevels()-1))
753  {
754  Array<OneD, int> vwgts_perm(
755  Dofs[0].size()+Dofs[1].size()-firstNonDirGraphVertId);
756  for(i = 0; i < locExpVector.size(); ++i)
757  {
758  locExpansion = locExpVector[i]
759  ->as<StdRegions::StdExpansion2D>();
760  for(j = 0; j < locExpansion->GetNverts(); ++j)
761  {
762  meshEdgeId = (locExpansion
763  ->as<LocalRegions::Expansion2D>()
764  ->GetGeom2D())->GetEid(j);
765  meshVertId = (locExpansion
766  ->as<LocalRegions::Expansion2D>()
767  ->GetGeom2D())->GetVid(j);
768 
769  if(ReorderedGraphVertId[0][meshVertId] >=
770  firstNonDirGraphVertId)
771  {
772  vwgts_perm[ReorderedGraphVertId[0][meshVertId]-
773  firstNonDirGraphVertId] =
774  Dofs[0][meshVertId];
775  }
776 
777  if(ReorderedGraphVertId[1][meshEdgeId] >=
778  firstNonDirGraphVertId)
779  {
780  vwgts_perm[ReorderedGraphVertId[1][meshEdgeId]-
781  firstNonDirGraphVertId] =
782  Dofs[1][meshEdgeId];
783  }
784  }
785  }
786 
787  bottomUpGraph->ExpandGraphWithVertexWeights(vwgts_perm);
788 
790  AllocateSharedPtr(this,bottomUpGraph);
791  }
792  }
793  }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
bool m_systemSingular
Flag indicating if the system is singular or not.
Definition: AssemblyMap.h:321
bool m_signChange
Flag indicating if modes require sign reversal.
Definition: AssemblyMap.h:346
AssemblyMapCG(const LibUtilities::SessionReaderSharedPtr &pSession, const std::string variable="DefaultVar")
Default constructor.
int m_numGlobalBndCoeffs
Total number of global boundary coefficients.
Definition: AssemblyMap.h:315
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:782
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)
Principle Modified Functions .
Definition: BasisType.h:48
int m_numLocalCoeffs
Total number of local coefficients.
Definition: AssemblyMap.h:332
std::shared_ptr< StdExpansion2D > StdExpansion2DSharedPtr
std::vector< ExpansionSharedPtr > ExpansionVector
Definition: Expansion.h:67
Array< OneD, int > m_localToGlobalMap
Integer map of local coeffs to global space.
AssemblyMapSharedPtr m_nextLevelLocalToGlobalMap
Map from the patches of the previous level to the patches of the current level.
Definition: AssemblyMap.h:396
static const NekDouble kNekZeroTol
Array< OneD, unsigned int > m_numLocalBndCoeffsPerPatch
The number of bnd dofs per patch.
Definition: AssemblyMap.h:389
int m_numGlobalDirBndCoeffs
Number of Global Dirichlet Boundary Coefficients.
Definition: AssemblyMap.h:319
Principle Modified Functions .
Definition: BasisType.h:49
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
double NekDouble
Array< OneD, unsigned int > m_numLocalIntCoeffsPerPatch
The number of int dofs per patch.
Definition: AssemblyMap.h:391
std::map< int, std::vector< PeriodicEntity > > PeriodicMap
Array< OneD, int > m_localToGlobalBndMap
Integer map of local boundary coeffs to global space.
Definition: AssemblyMap.h:349
int m_numLocalDirBndCoeffs
Number of Local Dirichlet Boundary Coefficients.
Definition: AssemblyMap.h:317
Array< OneD, int > m_bndCondCoeffsToGlobalCoeffsMap
Integer map of bnd cond coeffs to global coefficients.
Definition: AssemblyMap.h:353
int m_numLocalBndCoeffs
Number of local boundary coefficients.
Definition: AssemblyMap.h:313
int m_staticCondLevel
The level of recursion in the case of multi-level static condensation.
Definition: AssemblyMap.h:385
Array< OneD, NekDouble > m_localToGlobalBndSign
Integer sign of local boundary coeffs to global space.
Definition: AssemblyMap.h:351
Array< OneD, NekDouble > m_localToGlobalSign
Integer sign of local coeffs to global space.
std::shared_ptr< SegExp > SegExpSharedPtr
Definition: SegExp.h:266
LibUtilities::SessionReaderSharedPtr m_session
Session object.
Definition: AssemblyMap.h:304
std::shared_ptr< Geometry1D > Geometry1DSharedPtr
Definition: Geometry.h:63
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)
int m_numGlobalCoeffs
Total number of global coefficients.
Definition: AssemblyMap.h:343
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::shared_ptr< Expansion1D > Expansion1DSharedPtr
Definition: Expansion1D.h:51
std::shared_ptr< BottomUpSubStructuredGraph > BottomUpSubStructuredGraphSharedPtr
int m_numPatches
The number of patches (~elements) in the current level.
Definition: AssemblyMap.h:387

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 797 of file CoupledLocalToGlobalC0ContMap.cpp.

Referenced by CoupledLocalToGlobalC0ContMap().

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