Nektar++
Loading...
Searching...
No Matches
Public Member Functions | Protected Member Functions | Protected Attributes | Private Types | Private Member Functions | List of all members
Nektar::MultiRegions::AssemblyMapCG Class Reference

Constructs mappings for the C0 scalar continuous Galerkin formulation. More...

#include <AssemblyMapCG.h>

Inheritance diagram for Nektar::MultiRegions::AssemblyMapCG:
[legend]

Public Member Functions

 AssemblyMapCG (const LibUtilities::SessionReaderSharedPtr &pSession, const LibUtilities::CommSharedPtr &comm, const std::string variable="DefaultVar")
 Default constructor.
 
 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.
 
 ~AssemblyMapCG () override
 Destructor.
 
std::set< ExtraDirDof > & GetCopyLocalDirDofs ()
 
std::set< int > & GetParallelDirBndSign ()
 
- Public Member Functions inherited from Nektar::MultiRegions::AssemblyMap
 AssemblyMap ()
 Default constructor.
 
 AssemblyMap (const LibUtilities::SessionReaderSharedPtr &pSession, const LibUtilities::CommSharedPtr &comm, const std::string variable="DefaultVar")
 Constructor with a communicator.
 
 AssemblyMap (AssemblyMap *oldLevelMap, const BottomUpSubStructuredGraphSharedPtr &multiLevelGraph)
 Constructor for next level in multi-level static condensation.
 
virtual ~AssemblyMap ()
 Destructor.
 
LibUtilities::CommSharedPtr GetComm ()
 Retrieves the communicator.
 
std::string GetVariable ()
 Retrieves the variable string.
 
size_t GetHash () const
 Retrieves the hash of this map.
 
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 AvgAssemble (const Array< OneD, const NekDouble > &loc, Array< OneD, NekDouble > &global, bool useComm=true) 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.
 
const Array< OneD, const int > & GetLocalToGlobalBndMap ()
 Retrieve the global indices of the local boundary modes.
 
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.
 
NekDouble GetLocalToGlobalBndSign (const int i) const
 Retrieve the sign change of a given local boundary mode.
 
Array< OneD, const NekDoubleGetLocalToGlobalBndSign () const
 Retrieve the sign change for all local boundary modes.
 
const Array< OneD, const int > & GetBndCondCoeffsToLocalCoeffsMap ()
 Retrieves the local indices corresponding to the boundary expansion modes.
 
const Array< OneD, NekDouble > & GetBndCondCoeffsToLocalCoeffsSign ()
 Returns the modal sign associated with a given boundary expansion mode.
 
const Array< OneD, const int > & GetBndCondCoeffsToLocalTraceMap ()
 Retrieves the local indices corresponding to the boundary expansion modes to global trace.
 
int GetBndCondIDToGlobalTraceID (const int i)
 Returns the global index of the boundary trace giving the index on the boundary expansion.
 
const Array< OneD, const int > & GetBndCondIDToGlobalTraceID ()
 
int GetPerBndCondIDToGlobalTraceID (const int i)
 Returns the global index of the rotational periodic boundary trace giving the index on the rotational periodic boundary condition.
 
const Array< OneD, const int > & GetPerBndCondIDToGlobalTraceID ()
 
int GetNumGlobalDirBndCoeffs () const
 Returns the number of global Dirichlet boundary coefficients.
 
int GetNumLocalDirBndCoeffs () const
 Returns the number of local Dirichlet boundary coefficients.
 
int GetNumGlobalBndCoeffs () const
 Returns the total number of global boundary coefficients.
 
int GetNumLocalBndCoeffs () const
 Returns the total number of local boundary coefficients.
 
int GetNumLocalCoeffs () const
 Returns the total number of local coefficients.
 
int GetNumGlobalCoeffs () const
 Returns the total number of global coefficients.
 
bool GetSingularSystem () const
 Retrieves if the system is singular (true) or not (false)
 
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.
 
int GetStaticCondLevel () const
 Returns the level of static condensation for this map.
 
int GetNumPatches () const
 Returns the number of patches in this static condensation level.
 
const Array< OneD, const unsigned int > & GetNumLocalBndCoeffsPerPatch ()
 Returns the number of local boundary coefficients in each patch.
 
const Array< OneD, const unsigned int > & GetNumLocalIntCoeffsPerPatch ()
 Returns the number of local interior coefficients in each patch.
 
const AssemblyMapSharedPtr GetNextLevelLocalToGlobalMap () const
 Returns the local to global mapping for the next level in the multi-level static condensation.
 
void SetNextLevelLocalToGlobalMap (AssemblyMapSharedPtr pNextLevelLocalToGlobalMap)
 
const PatchMapSharedPtrGetPatchMapFromPrevLevel (void) const
 Returns the patch map from the previous level of the multi-level static condensation.
 
bool AtLastLevel () const
 Returns true if this is the last level in the multi-level static condensation.
 
GlobalSysSolnType GetGlobalSysSolnType () const
 Returns the method of solving global systems.
 
std::string GetPreconType () const
 
bool IsAbsoluteTolerance () 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
 

Protected Member Functions

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.
 
int v_GetLocalToGlobalMap (const int i) const override
 
int v_GetGlobalToUniversalMap (const int i) const override
 
int v_GetGlobalToUniversalMapUnique (const int i) const override
 
const Array< OneD, const int > & v_GetLocalToGlobalMap () override
 
const Array< OneD, const int > & v_GetGlobalToUniversalMap () override
 
const Array< OneD, const int > & v_GetGlobalToUniversalMapUnique () override
 
NekDouble v_GetLocalToGlobalSign (const int i) const override
 
const Array< OneD, NekDouble > & v_GetLocalToGlobalSign () const override
 
void v_LocalToGlobal (const Array< OneD, const NekDouble > &loc, Array< OneD, NekDouble > &global, bool useComm) const override
 
void v_GlobalToLocal (const Array< OneD, const NekDouble > &global, Array< OneD, NekDouble > &loc) const override
 
void v_GlobalToLocal (const NekVector< NekDouble > &global, NekVector< NekDouble > &loc) const override
 
void v_AvgAssemble (const Array< OneD, const NekDouble > &loc, Array< OneD, NekDouble > &global, bool useComm) const override
 
void v_Assemble (const Array< OneD, const NekDouble > &loc, Array< OneD, NekDouble > &global) const override
 
void v_Assemble (const NekVector< NekDouble > &loc, NekVector< NekDouble > &global) const override
 
void v_UniversalAssemble (Array< OneD, NekDouble > &pGlobal) const override
 
void v_UniversalAssemble (Array< OneD, NekDouble > &pGlobal, int offset) const override
 
int v_GetFullSystemBandWidth () const override
 
int v_GetNumNonDirVertexModes () const override
 
int v_GetNumNonDirEdgeModes () const override
 
int v_GetNumNonDirFaceModes () const override
 
int v_GetNumDirEdges () const override
 
int v_GetNumDirFaces () const override
 
int v_GetNumNonDirEdges () const override
 
int v_GetNumNonDirFaces () const override
 
const Array< OneD, const int > & v_GetExtraDirEdges () override
 
AssemblyMapSharedPtr v_LinearSpaceMap (const ExpList &locexp, GlobalSysSolnType solnType) override
 Construct an AssemblyMapCG object which corresponds to the linear space of the current object.
 
- Protected Member Functions inherited from Nektar::MultiRegions::AssemblyMap
void CalculateBndSystemBandWidth ()
 Calculates the bandwidth of the boundary system.
 
void GlobalToLocalBndWithoutSign (const Array< OneD, const NekDouble > &global, Array< OneD, NekDouble > &loc)
 

Protected Attributes

Array< OneD, int > m_localToGlobalMap
 Integer map of local coeffs to global space.
 
Array< OneD, NekDoublem_localToGlobalSign
 Integer sign of local coeffs to global space.
 
Array< OneD, NekDoublem_invMultiplicityWithSign
 Inverse of multiplicity with sign.
 
int m_fullSystemBandWidth
 Bandwith of the full matrix system (no static condensation).
 
Array< OneD, int > m_globalToUniversalMap
 Integer map of process coeffs to universal space.
 
Array< OneD, int > m_globalToUniversalMapUnique
 Integer map of unique process coeffs to universal space (signed)
 
int m_numNonDirVertexModes
 Number of non Dirichlet vertex modes.
 
int m_numNonDirEdgeModes
 Number of non Dirichlet edge modes.
 
int m_numNonDirFaceModes
 Number of non Dirichlet face modes.
 
int m_numDirEdges
 Number of Dirichlet edges.
 
int m_numDirFaces
 Number of Dirichlet faces.
 
int m_numNonDirEdges
 Number of Dirichlet edges.
 
int m_numNonDirFaces
 Number of Dirichlet faces.
 
int m_numLocalBndCondCoeffs
 Number of local boundary condition coefficients.
 
Array< OneD, int > m_extraDirEdges
 Extra dirichlet edges in parallel.
 
int m_numLocDirBndCondDofs
 Number of local boundary condition degrees of freedom.
 
int m_maxStaticCondLevel
 Maximum static condensation level.
 
std::set< ExtraDirDofm_copyLocalDirDofs
 Set indicating degrees of freedom which are Dirichlet but whose value is stored on another processor.
 
std::set< int > m_parallelDirBndSign
 Set indicating the local coeffs just touching parallel dirichlet boundary that have a sign change.
 
- Protected Attributes inherited from Nektar::MultiRegions::AssemblyMap
LibUtilities::SessionReaderSharedPtr m_session
 Session object.
 
LibUtilities::CommSharedPtr m_comm
 Communicator.
 
std::string m_variable
 Variable string identifier.
 
size_t m_hash
 Hash for map.
 
int m_numLocalBndCoeffs
 Number of local boundary coefficients.
 
int m_numGlobalBndCoeffs
 Total number of global boundary coefficients.
 
int m_numLocalDirBndCoeffs
 Number of Local Dirichlet Boundary Coefficients.
 
int m_numGlobalDirBndCoeffs
 Number of Global Dirichlet Boundary Coefficients.
 
bool m_systemSingular
 Flag indicating if the system is singular or not.
 
int m_numLocalCoeffs
 Total number of local coefficients.
 
int m_numGlobalCoeffs
 Total number of global coefficients.
 
bool m_signChange
 Flag indicating if modes require sign reversal.
 
Array< OneD, int > m_localToGlobalBndMap
 Integer map of local coeffs to global Boundary Dofs.
 
Array< OneD, NekDoublem_localToGlobalBndSign
 Integer sign of local boundary coeffs to global space.
 
Array< OneD, int > m_localToLocalBndMap
 Integer map of local boundary coeffs to local boundary system numbering.
 
Array< OneD, int > m_localToLocalIntMap
 Integer map of local boundary coeffs to local interior system numbering.
 
Array< OneD, int > m_bndCondCoeffsToLocalCoeffsMap
 Integer map of bnd cond coeffs to local coefficients.
 
Array< OneD, NekDoublem_bndCondCoeffsToLocalCoeffsSign
 Integer map of sign of bnd cond coeffs to local coefficients.
 
Array< OneD, int > m_bndCondCoeffsToLocalTraceMap
 Integer map of bnd cond coeff to local trace coeff.
 
Array< OneD, int > m_bndCondIDToGlobalTraceID
 Integer map of bnd cond trace number to global trace number.
 
Array< OneD, int > m_perbndCondIDToGlobalTraceID
 Integer map of rotational periodic bnd cond trace number to global trace number.
 
Array< OneD, int > m_globalToUniversalBndMap
 Integer map of process coeffs to universal space.
 
Array< OneD, int > m_globalToUniversalBndMapUnique
 Integer map of unique process coeffs to universal space (signed)
 
GlobalSysSolnType m_solnType
 The solution type of the global system.
 
int m_bndSystemBandWidth
 The bandwith of the global bnd system.
 
std::string m_preconType
 Type type of preconditioner to use in iterative solver.
 
NekDouble m_iterativeTolerance
 Tolerance for iterative solver.
 
bool m_isAbsoluteTolerance
 
int m_successiveRHS
 sucessive RHS for iterative solver
 
std::string m_linSysIterSolver
 Iterative solver: Conjugate Gradient, GMRES.
 
Gs::gs_datam_gsh
 
Gs::gs_datam_bndGsh
 
Gs::gs_datam_dirBndGsh
 gs gather communication to impose Dirhichlet BCs.
 
int m_staticCondLevel
 The level of recursion in the case of multi-level static condensation.
 
int m_numPatches
 The number of patches (~elements) in the current level.
 
Array< OneD, unsigned int > m_numLocalBndCoeffsPerPatch
 The number of bnd dofs per patch.
 
Array< OneD, unsigned int > m_numLocalIntCoeffsPerPatch
 The number of int dofs per patch.
 
AssemblyMapSharedPtr m_nextLevelLocalToGlobalMap
 Map from the patches of the previous level to the patches of the current level.
 
int m_lowestStaticCondLevel
 Lowest static condensation level.
 

Private Types

typedef Array< OneD, const ExpListSharedPtrBndCondExp
 
typedef Array< OneD, const SpatialDomains::BoundaryConditionShPtrBndCond
 

Private Member Functions

void SetInvMultiplicityWithSign ()
 

Detailed Description

Constructs mappings for the C0 scalar continuous Galerkin formulation.

Mappings are created for three possible global solution types:

These mappings are used by GlobalLinSys to generate the global system.

Definition at line 65 of file AssemblyMapCG.h.

Member Typedef Documentation

◆ BndCond

Definition at line 68 of file AssemblyMapCG.h.

◆ BndCondExp

Definition at line 67 of file AssemblyMapCG.h.

Constructor & Destructor Documentation

◆ AssemblyMapCG() [1/2]

Nektar::MultiRegions::AssemblyMapCG::AssemblyMapCG ( const LibUtilities::SessionReaderSharedPtr pSession,
const LibUtilities::CommSharedPtr comm,
const std::string  variable = "DefaultVar" 
)

Default constructor.

Definition at line 69 of file AssemblyMapCG.cpp.

72 : AssemblyMap(pSession, comm, variable)
73{
74 pSession->LoadParameter("MaxStaticCondLevel", m_maxStaticCondLevel, 100);
75}
int m_maxStaticCondLevel
Maximum static condensation level.
AssemblyMap()
Default constructor.

References m_maxStaticCondLevel.

◆ AssemblyMapCG() [2/2]

Nektar::MultiRegions::AssemblyMapCG::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.

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

Definition at line 1271 of file AssemblyMapCG.cpp.

1278 : AssemblyMap(pSession, locExp.GetComm(), variable)
1279{
1280 int i, j, k;
1281 int p, q, numModes0, numModes1;
1282 int cnt = 0;
1283 int meshVertId, meshEdgeId, meshEdgeId2, meshFaceId, meshFaceId2;
1284 int globalId;
1285 int nEdgeInteriorCoeffs;
1286 int firstNonDirGraphVertId;
1287 LibUtilities::CommSharedPtr vRowComm = m_comm->GetRowComm();
1289 StdRegions::Orientation edgeOrient;
1290 StdRegions::Orientation faceOrient;
1291 Array<OneD, unsigned int> edgeInteriorMap;
1292 Array<OneD, int> edgeInteriorSign;
1293 Array<OneD, unsigned int> faceInteriorMap;
1294 Array<OneD, int> faceInteriorSign;
1295
1296 const LocalRegions::ExpansionVector &locExpVector = *(locExp.GetExp());
1297
1298 bool verbose = m_session->DefinesCmdLineArgument("verbose");
1299
1300 m_signChange = false;
1301
1302 // Stores vertex, edge and face reordered vertices.
1303 DofGraph graph(3);
1304 DofGraph dofs(3);
1305 vector<map<int, int>> faceModes(2);
1306 map<int, LibUtilities::ShapeType> faceType;
1307
1308 set<int> extraDirVerts, extraDirEdges;
1310
1311 // Construct list of number of degrees of freedom for each vertex,
1312 // edge and face.
1313 for (i = 0; i < locExpVector.size(); ++i)
1314 {
1315 exp = locExpVector[i];
1316
1317 for (j = 0; j < exp->GetNverts(); ++j)
1318 {
1319 dofs[0][exp->GetGeom()->GetVid(j)] = 1;
1320 }
1321
1322 for (j = 0; j < exp->GetGeom()->GetNumEdges(); ++j)
1323 {
1324 int nEdgeInt;
1325 if (exp->GetGeom()->GetNumFaces())
1326 {
1327 nEdgeInt =
1328 exp->as<LocalRegions::Expansion3D>()->GetEdgeNcoeffs(j) - 2;
1329 }
1330 else
1331 {
1332 nEdgeInt = exp->GetTraceNcoeffs(j) - 2;
1333 }
1334
1335 if (dofs[1].count(exp->GetGeom()->GetEid(j)) > 0)
1336 {
1337 if (dofs[1][exp->GetGeom()->GetEid(j)] != nEdgeInt)
1338 {
1339 ASSERTL0(
1340 (exp->GetBasisType(0) == LibUtilities::eModified_A) ||
1341 (exp->GetBasisType(1) ==
1343 (exp->GetBasisType(2) ==
1345 (exp->GetBasisType(2) ==
1347 "CG with variable order only available with "
1348 "modal expansion");
1349 }
1350 dofs[1][exp->GetGeom()->GetEid(j)] =
1351 min(dofs[1][exp->GetGeom()->GetEid(j)], nEdgeInt);
1352 }
1353 else
1354 {
1355 dofs[1][exp->GetGeom()->GetEid(j)] = nEdgeInt;
1356 }
1357 }
1358
1359 for (j = 0; j < exp->GetGeom()->GetNumFaces(); ++j)
1360 {
1361 faceOrient = exp->GetGeom()->GetForient(j);
1362 meshFaceId = exp->GetGeom()->GetFid(j);
1363 exp->GetTraceNumModes(j, numModes0, numModes1, faceOrient);
1364
1365 if (faceModes[0].count(meshFaceId) > 0)
1366 {
1367 faceModes[0][meshFaceId] =
1368 min(faceModes[0][meshFaceId], numModes0);
1369
1370 faceModes[1][meshFaceId] =
1371 min(faceModes[1][meshFaceId], numModes1);
1372 }
1373 else
1374 {
1375 faceModes[0][meshFaceId] = numModes0;
1376 faceModes[1][meshFaceId] = numModes1;
1377
1378 // Get shape of this face
1379 faceType[meshFaceId] =
1380 exp->GetGeom()->GetFace(j)->GetShapeType();
1381 }
1382 }
1383 }
1384
1385 // Add non-local periodic dofs to the map
1386 for (auto &pIt : periodicEdges)
1387 {
1388 for (i = 0; i < pIt.second.size(); ++i)
1389 {
1390 meshEdgeId2 = pIt.second[i].id;
1391 if (dofs[1].count(meshEdgeId2) == 0)
1392 {
1393 dofs[1][meshEdgeId2] = 1e6;
1394 }
1395 }
1396 }
1397 for (auto &pIt : periodicFaces)
1398 {
1399 for (i = 0; i < pIt.second.size(); ++i)
1400 {
1401 meshFaceId2 = pIt.second[i].id;
1402 if (faceModes[0].count(meshFaceId2) == 0)
1403 {
1404 faceModes[0][meshFaceId2] = 1e6;
1405 faceModes[1][meshFaceId2] = 1e6;
1406 }
1407 }
1408 }
1409
1410 // Now use information from all partitions to determine the correct
1411 // size
1412
1413 // edges
1414 Array<OneD, long> edgeId(dofs[1].size());
1415 Array<OneD, NekDouble> edgeDof(dofs[1].size());
1416 i = 0;
1417 for (auto &dofIt : dofs[1])
1418 {
1419 edgeId[i] = dofIt.first + 1;
1420 edgeDof[i++] = (NekDouble)dofIt.second;
1421 }
1422 Gs::gs_data *tmp = Gs::Init(edgeId, vRowComm, verbose);
1423 Gs::Gather(edgeDof, Gs::gs_min, tmp);
1424 Gs::Finalise(tmp);
1425 for (i = 0; i < dofs[1].size(); i++)
1426 {
1427 dofs[1][edgeId[i] - 1] = (int)(edgeDof[i] + 0.5);
1428 }
1429 // Periodic edges
1430 for (auto &pIt : periodicEdges)
1431 {
1432 meshEdgeId = pIt.first;
1433 for (i = 0; i < pIt.second.size(); ++i)
1434 {
1435 meshEdgeId2 = pIt.second[i].id;
1436 if (dofs[1][meshEdgeId2] < dofs[1][meshEdgeId])
1437 {
1438 dofs[1][meshEdgeId] = dofs[1][meshEdgeId2];
1439 }
1440 }
1441 }
1442 // faces
1443 Array<OneD, long> faceId(faceModes[0].size());
1444 Array<OneD, NekDouble> faceP(faceModes[0].size());
1445 Array<OneD, NekDouble> faceQ(faceModes[0].size());
1446
1447 i = 0;
1448 for (auto dofIt = faceModes[0].begin(), dofIt2 = faceModes[1].begin();
1449 dofIt != faceModes[0].end(); dofIt++, dofIt2++, i++)
1450 {
1451 faceId[i] = dofIt->first + 1;
1452 faceP[i] = (NekDouble)dofIt->second;
1453 faceQ[i] = (NekDouble)dofIt2->second;
1454 }
1455 Gs::gs_data *tmp2 = Gs::Init(faceId, vRowComm, verbose);
1456 Gs::Gather(faceP, Gs::gs_min, tmp2);
1457 Gs::Gather(faceQ, Gs::gs_min, tmp2);
1458 Gs::Finalise(tmp2);
1459 for (i = 0; i < faceModes[0].size(); i++)
1460 {
1461 faceModes[0][faceId[i] - 1] = (int)(faceP[i] + 0.5);
1462 faceModes[1][faceId[i] - 1] = (int)(faceQ[i] + 0.5);
1463 }
1464 // Periodic faces
1465 for (auto &pIt : periodicFaces)
1466 {
1467 meshFaceId = pIt.first;
1468 for (i = 0; i < pIt.second.size(); ++i)
1469 {
1470 meshFaceId2 = pIt.second[i].id;
1471 if (faceModes[0][meshFaceId2] < faceModes[0][meshFaceId])
1472 {
1473 faceModes[0][meshFaceId] = faceModes[0][meshFaceId2];
1474 }
1475 if (faceModes[1][meshFaceId2] < faceModes[1][meshFaceId])
1476 {
1477 faceModes[1][meshFaceId] = faceModes[1][meshFaceId2];
1478 }
1479 }
1480 }
1481 // Calculate number of dof in each face
1482 int P, Q;
1483 for (i = 0; i < faceModes[0].size(); i++)
1484 {
1485 P = faceModes[0][faceId[i] - 1];
1486 Q = faceModes[1][faceId[i] - 1];
1487 if (faceType[faceId[i] - 1] == LibUtilities::eQuadrilateral)
1488 {
1489 // Quad face
1490 dofs[2][faceId[i] - 1] =
1493 }
1494 else
1495 {
1496 // Tri face
1497 dofs[2][faceId[i] - 1] =
1500 }
1501 }
1502
1503 Array<OneD, const BndCond> bndCondVec(1, bndConditions);
1504
1505 // Note that nExtraDirichlet is not used in the logic below; it just
1506 // needs to be set so that the coupled solver in
1507 // IncNavierStokesSolver can work.
1508 int nExtraDirichlet;
1509 int mdswitch;
1510 m_session->LoadParameter("MDSwitch", mdswitch, 10);
1511
1512 int nGraphVerts = CreateGraph(
1513 locExp, bndCondExp, bndCondVec, checkIfSystemSingular, periodicVerts,
1514 periodicEdges, periodicFaces, graph, bottomUpGraph, extraDirVerts,
1515 extraDirEdges, firstNonDirGraphVertId, nExtraDirichlet, mdswitch);
1516
1517 /*
1518 * Set up an array which contains the offset information of the
1519 * different graph vertices.
1520 *
1521 * This basically means to identify to how many global degrees of
1522 * freedom the individual graph vertices correspond. Obviously,
1523 * the graph vertices corresponding to the mesh-vertices account
1524 * for a single global DOF. However, the graph vertices
1525 * corresponding to the element edges correspond to N-2 global DOF
1526 * where N is equal to the number of boundary modes on this edge.
1527 */
1528 Array<OneD, int> graphVertOffset(
1529 graph[0].size() + graph[1].size() + graph[2].size() + 1, 0);
1530
1531 graphVertOffset[0] = 0;
1532
1533 for (i = 0; i < locExpVector.size(); ++i)
1534 {
1535 exp = locExpVector[i];
1536
1537 for (j = 0; j < exp->GetNverts(); ++j)
1538 {
1539 meshVertId = exp->GetGeom()->GetVid(j);
1540 graphVertOffset[graph[0][meshVertId] + 1] = 1;
1541 }
1542
1543 for (j = 0; j < exp->GetGeom()->GetNumEdges(); ++j)
1544 {
1545 if (exp->GetGeom()->GetNumFaces()) // 3D version
1546 {
1547 nEdgeInteriorCoeffs =
1548 exp->as<LocalRegions::Expansion3D>()->GetEdgeNcoeffs(j) - 2;
1549 }
1550 else
1551 {
1552 nEdgeInteriorCoeffs = exp->GetTraceNcoeffs(j) - 2;
1553 }
1554 meshEdgeId = exp->GetGeom()->GetEid(j);
1555 graphVertOffset[graph[1][meshEdgeId] + 1] = dofs[1][meshEdgeId];
1556
1557 // Need a sign vector for modal expansions if nEdgeCoeffs
1558 // >=3 (not 4 because of variable order case)
1559 if (nEdgeInteriorCoeffs &&
1560 (exp->GetBasisType(0) == LibUtilities::eModified_A))
1561 {
1562 m_signChange = true;
1563 }
1564 }
1565
1566 for (j = 0; j < exp->GetGeom()->GetNumFaces(); ++j)
1567 {
1568 meshFaceId = exp->GetGeom()->GetFid(j);
1569 graphVertOffset[graph[2][meshFaceId] + 1] = dofs[2][meshFaceId];
1570 }
1571 }
1572
1573 for (i = 1; i < graphVertOffset.size(); i++)
1574 {
1575 graphVertOffset[i] += graphVertOffset[i - 1];
1576 }
1577
1578 // Allocate the proper amount of space for the class-data
1579 m_numLocalCoeffs = numLocalCoeffs;
1580 m_numGlobalDirBndCoeffs = graphVertOffset[firstNonDirGraphVertId];
1581 m_localToGlobalMap = Array<OneD, int>(m_numLocalCoeffs, -1);
1582 m_localToGlobalBndMap = Array<OneD, int>(m_numLocalBndCoeffs, -1);
1583 m_localToLocalBndMap = Array<OneD, int>(m_numLocalBndCoeffs, -1);
1585 Array<OneD, int>(m_numLocalCoeffs - m_numLocalBndCoeffs, -1);
1587 Array<OneD, int>(m_numLocalBndCondCoeffs, -1);
1588
1589 // If required, set up the sign-vector
1590 if (m_signChange)
1591 {
1592 m_localToGlobalSign = Array<OneD, NekDouble>(m_numLocalCoeffs, 1.0);
1594 Array<OneD, NekDouble>(m_numLocalBndCoeffs, 1.0);
1596 Array<OneD, NekDouble>(m_numLocalBndCondCoeffs, 1.0);
1597 }
1598
1600 m_numPatches = locExpVector.size();
1601 m_numLocalBndCoeffsPerPatch = Array<OneD, unsigned int>(m_numPatches);
1602 m_numLocalIntCoeffsPerPatch = Array<OneD, unsigned int>(m_numPatches);
1603 for (i = 0; i < m_numPatches; ++i)
1604 {
1606 (unsigned int)locExpVector[i]->NumBndryCoeffs();
1608 (unsigned int)locExpVector[i]->GetNcoeffs() -
1609 locExpVector[i]->NumBndryCoeffs();
1610 }
1611
1612 /**
1613 * STEP 6: Now, all ingredients are ready to set up the actual
1614 * local to global mapping.
1615 *
1616 * The remainder of the map consists of the element-interior
1617 * degrees of freedom. This leads to the block-diagonal submatrix
1618 * as each element-interior mode is globally orthogonal to modes
1619 * in all other elements.
1620 */
1621 cnt = 0;
1622
1623 // Loop over all the elements in the domain
1624 int cntbdry = 0;
1625 int cntint = 0;
1626 for (i = 0; i < locExpVector.size(); ++i)
1627 {
1628 exp = locExpVector[i];
1629 cnt = locExp.GetCoeff_Offset(i);
1630
1631 int nbdry = exp->NumBndryCoeffs();
1632 int nint = exp->GetNcoeffs() - nbdry;
1633
1634 Array<OneD, unsigned int> bmap(nbdry);
1635 Array<OneD, unsigned int> imap(nint);
1636
1637 exp->GetBoundaryMap(bmap);
1638 exp->GetInteriorMap(imap);
1639
1640 for (j = 0; j < nbdry; ++j)
1641 {
1642 m_localToLocalBndMap[cntbdry++] = cnt + bmap[j];
1643 }
1644
1645 for (j = 0; j < nint; ++j)
1646 {
1647 m_localToLocalIntMap[cntint++] = cnt + imap[j];
1648 }
1649
1650 for (j = 0; j < exp->GetNverts(); ++j)
1651 {
1652 meshVertId = exp->GetGeom()->GetVid(j);
1653
1654 // Set the global DOF for vertex j of element i
1655 m_localToGlobalMap[cnt + exp->GetVertexMap(j)] =
1656 graphVertOffset[graph[0][meshVertId]];
1657 }
1658
1659 for (j = 0; j < exp->GetGeom()->GetNumEdges(); ++j)
1660 {
1661 if (exp->GetGeom()->GetNumFaces())
1662 {
1663 nEdgeInteriorCoeffs =
1664 exp->as<LocalRegions::Expansion3D>()->GetEdgeNcoeffs(j) - 2;
1665 }
1666 else
1667 {
1668 nEdgeInteriorCoeffs = exp->GetTraceNcoeffs(j) - 2;
1669 }
1670 edgeOrient = exp->GetGeom()->GetEorient(j);
1671 meshEdgeId = exp->GetGeom()->GetEid(j);
1672
1673 // obtain the vertex id attached with one of the vertices of the
1674 // edge for variable P purposes
1675 auto meshEdgeVertId = exp->GetGeom()->GetEdge(j)->GetVid(0);
1676
1677 auto pIt = periodicEdges.find(meshEdgeId);
1678
1679 // See if this edge is periodic. If it is, then we map all
1680 // edges to the one with lowest ID, and align all
1681 // coefficients to this edge orientation.
1682 if (pIt != periodicEdges.end())
1683 {
1684 pair<int, StdRegions::Orientation> idOrient =
1685 DeterminePeriodicEdgeOrientId(meshEdgeId, edgeOrient,
1686 pIt->second);
1687 edgeOrient = idOrient.second;
1688 }
1689
1690 if (exp->GetGeom()->GetNumFaces())
1691 {
1692 exp->as<LocalRegions::Expansion3D>()
1693 ->GetEdgeInteriorToElementMap(j, edgeInteriorMap,
1694 edgeInteriorSign, edgeOrient);
1695 }
1696 else
1697 {
1698 exp->GetTraceInteriorToElementMap(j, edgeInteriorMap,
1699 edgeInteriorSign, edgeOrient);
1700 }
1701
1702 // Set the global DOF's for the interior modes of edge j
1703 for (k = 0; k < dofs[1][meshEdgeId]; ++k)
1704 {
1705 m_localToGlobalMap[cnt + edgeInteriorMap[k]] =
1706 graphVertOffset[graph[1][meshEdgeId]] + k;
1707 }
1708 for (k = dofs[1][meshEdgeId]; k < nEdgeInteriorCoeffs; ++k)
1709 {
1710 // set value to edge vertex on edge - just to id local - will be
1711 // zerod by sign
1712 m_localToGlobalMap[cnt + edgeInteriorMap[k]] =
1713 graphVertOffset[graph[0][meshEdgeVertId]];
1714 }
1715
1716 // Fill the sign vector if required
1717 if (m_signChange)
1718 {
1719 for (k = 0; k < dofs[1][meshEdgeId]; ++k)
1720 {
1721 m_localToGlobalSign[cnt + edgeInteriorMap[k]] =
1722 (NekDouble)edgeInteriorSign[k];
1723 }
1724 for (k = dofs[1][meshEdgeId]; k < nEdgeInteriorCoeffs; ++k)
1725 {
1726 m_localToGlobalSign[cnt + edgeInteriorMap[k]] = 0.0;
1727 }
1728 }
1729 }
1730
1731 for (j = 0; j < exp->GetGeom()->GetNumFaces(); ++j)
1732 {
1733 faceOrient = exp->GetGeom()->GetForient(j);
1734 meshFaceId = exp->GetGeom()->GetFid(j);
1735
1736 // obtain the vertex id attached with one of the vertices of the
1737 // face for variable P purposes
1738 auto meshFaceVertId = exp->GetGeom()->GetFace(j)->GetVid(0);
1739
1740 auto pIt = periodicFaces.find(meshFaceId);
1741
1742 if (pIt != periodicFaces.end() &&
1743 meshFaceId == min(meshFaceId, pIt->second[0].id))
1744 {
1745 faceOrient = DeterminePeriodicFaceOrient(faceOrient,
1746 pIt->second[0].orient);
1747 }
1748
1749 exp->GetTraceInteriorToElementMap(j, faceInteriorMap,
1750 faceInteriorSign, faceOrient);
1751
1752 // Set the global DOF's for the interior modes of face j
1753 exp->GetTraceNumModes(j, numModes0, numModes1, faceOrient);
1754 switch (faceType[meshFaceId])
1755 {
1757 {
1758 int kLoc = 0;
1759 k = 0;
1760 for (q = 2; q < numModes1; q++)
1761 {
1762 for (p = 2; p < numModes0; p++)
1763 {
1764 if ((p < faceModes[0][meshFaceId]) &&
1765 (q < faceModes[1][meshFaceId]))
1766 {
1767 m_localToGlobalMap[cnt +
1768 faceInteriorMap[kLoc]] =
1769 graphVertOffset[graph[2][meshFaceId]] + k;
1770 if (m_signChange)
1771 {
1773 faceInteriorMap[kLoc]] =
1774 (NekDouble)faceInteriorSign[kLoc];
1775 }
1776 k++;
1777 }
1778 else
1779 {
1780 // set value to edge vertex on face - just to id
1781 // local - will be zerod by sign
1782 m_localToGlobalMap[cnt +
1783 faceInteriorMap[kLoc]] =
1784 graphVertOffset[graph[0][meshFaceVertId]];
1785
1786 if (m_signChange)
1787 {
1789 faceInteriorMap[kLoc]] =
1790 0.0;
1791 }
1792 }
1793 kLoc++;
1794 }
1795 }
1796 }
1797 break;
1799 {
1800 int kLoc = 0;
1801 k = 0;
1802 for (p = 2; p < numModes0; p++)
1803 {
1804 for (q = 1; q < numModes1 - p; q++)
1805 {
1806 if ((p < faceModes[0][meshFaceId]) &&
1807 (p + q < faceModes[1][meshFaceId]))
1808 {
1809 m_localToGlobalMap[cnt +
1810 faceInteriorMap[kLoc]] =
1811 graphVertOffset[graph[2][meshFaceId]] + k;
1812 if (m_signChange)
1813 {
1815 faceInteriorMap[kLoc]] =
1816 (NekDouble)faceInteriorSign[kLoc];
1817 }
1818 k++;
1819 }
1820 else
1821 {
1822 // set value to edge vertex on face - just to id
1823 // local - will be zerod by sign
1824 m_localToGlobalMap[cnt +
1825 faceInteriorMap[kLoc]] =
1826 graphVertOffset[graph[0][meshFaceVertId]];
1827 if (m_signChange)
1828 {
1830 faceInteriorMap[kLoc]] =
1831 0.0;
1832 }
1833 }
1834 kLoc++;
1835 }
1836 }
1837 }
1838 break;
1839 default:
1840 ASSERTL0(false, "Shape not recognised");
1841 break;
1842 }
1843 }
1844 }
1845
1846 // Set up the mapping for the boundary conditions
1847 // Set up boundary mapping
1848 map<int, pair<int, int>> traceToElmtTraceMap;
1849 int id;
1850
1851 for (cnt = i = 0; i < locExpVector.size(); ++i)
1852 {
1853 exp = locExpVector[i];
1854
1855 for (j = 0; j < exp->GetNtraces(); ++j)
1856 {
1857 id = exp->GetGeom()->GetTid(j);
1858
1859 traceToElmtTraceMap[id] = pair<int, int>(i, j);
1860 }
1861 }
1862
1863 Array<OneD, unsigned int> maparray;
1864 Array<OneD, int> signarray;
1865 map<int, pair<int, NekDouble>> GloDirBndCoeffToLocalCoeff;
1866 set<int> CoeffOnDirTrace;
1867
1868 cnt = 0;
1869 int offset = 0;
1870 for (i = 0; i < bndCondExp.size(); i++)
1871 {
1872 set<int> foundExtraVerts, foundExtraEdges;
1873 for (j = 0; j < bndCondExp[i]->GetNumElmts(); j++)
1874 {
1875 bndExp = bndCondExp[i]->GetExp(j);
1876 cnt = offset + bndCondExp[i]->GetCoeff_Offset(j);
1877
1878 int id = bndExp->GetGeom()->GetGlobalID();
1879
1880 ASSERTL1(traceToElmtTraceMap.count(id) > 0,
1881 "Failed to find trace id");
1882
1883 int eid = traceToElmtTraceMap[id].first;
1884 int tid = traceToElmtTraceMap[id].second;
1885
1886 exp = locExpVector[eid];
1887 int dim = exp->GetShapeDimension();
1888
1889 if (dim == 1)
1890 {
1892 locExp.GetCoeff_Offset(eid) + exp->GetVertexMap(tid);
1893 }
1894 else
1895 {
1896 if (dim == 2)
1897 {
1898 exp->GetTraceToElementMap(tid, maparray, signarray,
1899 exp->GetGeom()->GetEorient(tid),
1900 bndExp->GetBasisNumModes(0));
1901 }
1902 else if (dim == 3)
1903 {
1904 exp->GetTraceToElementMap(tid, maparray, signarray,
1905 exp->GetGeom()->GetForient(tid),
1906 bndExp->GetBasisNumModes(0),
1907 bndExp->GetBasisNumModes(1));
1908 }
1909
1910 for (k = 0; k < bndExp->GetNcoeffs(); k++)
1911 {
1913 locExp.GetCoeff_Offset(eid) + maparray[k];
1914 if (m_signChange)
1915 {
1917 signarray[k];
1918 }
1919 }
1920 }
1921
1922 // we now need some information to work out how to
1923 // handle vertices and edges that are only just
1924 // touching a dirichlet boundary (and not the
1925 // whole edge/face)
1926
1927 for (k = 0; k < bndExp->GetNcoeffs(); k++)
1928 {
1929 int locid = m_bndCondCoeffsToLocalCoeffsMap[cnt + k];
1930 int gloid = m_localToGlobalMap[locid];
1931 NekDouble sign = 1.0;
1932
1933 if (m_signChange)
1934 {
1936 }
1937
1938 if (bndConditions[i]->GetBoundaryConditionType() ==
1940 {
1941 bool addid =
1942 (m_signChange && m_localToGlobalSign[locid] == 0)
1943 ? false
1944 : true;
1945
1946 // only add point if sign is +/- 1 since if zero it
1947 // belongs to a mode that is not used in variable p
1948 // expansion
1949 if (addid)
1950 {
1951 CoeffOnDirTrace.insert(locid);
1952
1953 // store the local id and sign from global id
1954 // back to local space;
1955 GloDirBndCoeffToLocalCoeff[gloid] =
1956 pair<int, NekDouble>(locid, sign);
1957 }
1958 }
1959 }
1960 }
1961 offset += bndCondExp[i]->GetNcoeffs();
1962 }
1963
1964 globalId = Vmath::Vmax(m_numLocalCoeffs, &m_localToGlobalMap[0], 1) + 1;
1965 m_numGlobalBndCoeffs = globalId;
1966
1967 // Set up a mapping list of Dirichlet Local Dofs that
1968 // arise due to one vertex or edge just touching a
1969 // Dirichlet boundary and need the value from another
1970 // local coeff that has been filled by the boundary
1971 // coeffs.
1972
1973 Array<OneD, NekDouble> gloParaDirBnd(m_numGlobalBndCoeffs, -1.0);
1974
1975 Array<OneD, unsigned int> bndmap;
1976 cnt = 0;
1977 for (i = 0; i < locExpVector.size(); ++i)
1978 {
1979 int gloid;
1980
1981 exp = locExpVector[i];
1982
1983 exp->GetBoundaryMap(bndmap);
1984
1985 for (j = 0; j < bndmap.size(); ++j)
1986 {
1987 k = cnt + bndmap[j];
1988
1989 // exclude if Dirichlet boundary already included in partition
1990 if (CoeffOnDirTrace.count(k) == 0)
1991 {
1992 gloid = m_localToGlobalMap[k];
1993
1994 if (gloid < m_numGlobalDirBndCoeffs) // point on Dir BC
1995 {
1996 if (GloDirBndCoeffToLocalCoeff.count(gloid))
1997 {
1998 int locid = GloDirBndCoeffToLocalCoeff[gloid].first;
1999 NekDouble sign = 1.0;
2000
2001 if (m_signChange)
2002 {
2003 sign = m_localToGlobalSign[locid] *
2005 }
2006
2007 ExtraDirDof DirDofs(k, locid, sign);
2008 // could make same `structure as extraDirDof
2009 m_copyLocalDirDofs.insert(DirDofs);
2010 }
2011 else // else could be on another parallel partition.
2012 {
2013 gloParaDirBnd[gloid] = gloid;
2014 }
2015 }
2016 }
2017 }
2018
2019 cnt += exp->GetNcoeffs();
2020 }
2021
2022 /*
2023 * The boundary condition mapping is generated from the same vertex
2024 * renumbering.
2025 */
2026 cnt = 0;
2027 for (i = 0; i < m_numLocalCoeffs; ++i)
2028 {
2029 if (m_localToGlobalMap[i] == -1)
2030 {
2031 m_localToGlobalMap[i] = globalId++;
2032 }
2033 else
2034 {
2035 if (m_signChange)
2036 {
2038 }
2040 }
2041 }
2042
2043 m_numGlobalCoeffs = globalId;
2044
2045 SetUpUniversalC0ContMap(locExp, periodicVerts, periodicEdges,
2046 periodicFaces);
2047
2048 // Now that universal map is setup reset gloParaDirBnd to
2049 // 0 if no point communicated or universal value of not
2050 // equal to -1.0
2051 for (i = 0; i < m_numGlobalBndCoeffs; ++i)
2052 {
2053 int gloid = gloParaDirBnd[i];
2054 if (gloid == -1)
2055 {
2056 gloParaDirBnd[i] = 0.0;
2057 }
2058 else
2059 {
2060 gloParaDirBnd[i] = m_globalToUniversalMap[gloid];
2061 }
2062 }
2063
2064 // Use parallel boundary communication to set parallel
2065 // dirichlet values on all processors Needs to be after
2066 // SetupUuniversialC0ContMap
2067 Gs::Gather(gloParaDirBnd, Gs::gs_max, m_bndGsh);
2068
2069 // copy global ids back to local values in partition to
2070 // initialise gs communicator.
2071 Array<OneD, long> paraDirBnd(m_numLocalCoeffs);
2072 for (i = 0; i < numLocalCoeffs; ++i)
2073 {
2074 paraDirBnd[i] = 0.0;
2075
2076 int id = m_localToGlobalMap[i];
2077
2078 if (id >= m_numGlobalDirBndCoeffs)
2079 {
2080 continue;
2081 }
2082
2083 paraDirBnd[i] = gloParaDirBnd[id];
2084
2085 if (gloParaDirBnd[id] > 0.0)
2086 {
2087 // gather any sign changes due to edge modes
2088 if (m_signChange)
2089 {
2090 if (m_localToGlobalSign[i] < 0)
2091 {
2092 m_parallelDirBndSign.insert(i);
2093 }
2094 }
2095 }
2096 }
2097
2098 m_dirBndGsh = Gs::Init(paraDirBnd, vRowComm, verbose);
2099
2100 // Set up the local to global map for the next level when using
2101 // multi-level static condensation
2106 nGraphVerts)
2107 {
2108 if (m_staticCondLevel < (bottomUpGraph->GetNlevels() - 1))
2109 {
2110 Array<OneD, int> vwgts_perm(graph[0].size() + graph[1].size() +
2111 graph[2].size() -
2112 firstNonDirGraphVertId);
2113
2114 for (i = 0; i < locExpVector.size(); ++i)
2115 {
2116 exp = locExpVector[i];
2117
2118 for (j = 0; j < exp->GetNverts(); ++j)
2119 {
2120 meshVertId = exp->GetGeom()->GetVid(j);
2121
2122 if (graph[0][meshVertId] >= firstNonDirGraphVertId)
2123 {
2124 vwgts_perm[graph[0][meshVertId] -
2125 firstNonDirGraphVertId] =
2126 dofs[0][meshVertId];
2127 }
2128 }
2129
2130 for (j = 0; j < exp->GetGeom()->GetNumEdges(); ++j)
2131 {
2132 meshEdgeId = exp->GetGeom()->GetEid(j);
2133
2134 if (graph[1][meshEdgeId] >= firstNonDirGraphVertId)
2135 {
2136 vwgts_perm[graph[1][meshEdgeId] -
2137 firstNonDirGraphVertId] =
2138 dofs[1][meshEdgeId];
2139 }
2140 }
2141
2142 for (j = 0; j < exp->GetGeom()->GetNumFaces(); ++j)
2143 {
2144 meshFaceId = exp->GetGeom()->GetFid(j);
2145
2146 if (graph[2][meshFaceId] >= firstNonDirGraphVertId)
2147 {
2148 vwgts_perm[graph[2][meshFaceId] -
2149 firstNonDirGraphVertId] =
2150 dofs[2][meshFaceId];
2151 }
2152 }
2153 }
2154
2155 bottomUpGraph->ExpandGraphWithVertexWeights(vwgts_perm);
2158 bottomUpGraph);
2159 }
2160 }
2161
2163
2164 // Add up hash values if parallel
2165 int hash = m_hash;
2166 vRowComm->AllReduce(hash, LibUtilities::ReduceSum);
2167 m_hash = hash;
2168
2171
2173}
#define ASSERTL0(condition, msg)
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
#define sign(a, b)
return the sign(b)*a
Definition Polylib.cpp:47
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)
std::set< int > m_parallelDirBndSign
Set indicating the local coeffs just touching parallel dirichlet boundary that have a sign change.
Array< OneD, int > m_localToGlobalMap
Integer map of local coeffs to global space.
void SetUpUniversalC0ContMap(const ExpList &locExp, const PeriodicMap &perVerts=NullPeriodicMap, const PeriodicMap &perEdges=NullPeriodicMap, const PeriodicMap &perFaces=NullPeriodicMap)
Array< OneD, NekDouble > m_localToGlobalSign
Integer sign of local coeffs to global space.
void CalculateFullSystemBandWidth()
Calculate the bandwith of the full matrix system.
std::set< ExtraDirDof > m_copyLocalDirDofs
Set indicating degrees of freedom which are Dirichlet but whose value is stored on another processor.
Array< OneD, int > m_globalToUniversalMap
Integer map of process coeffs to universal space.
int m_numLocalBndCondCoeffs
Number of local boundary condition coefficients.
GlobalSysSolnType m_solnType
The solution type of the global system.
int m_numLocalCoeffs
Total number of local coefficients.
Array< OneD, int > m_bndCondCoeffsToLocalCoeffsMap
Integer map of bnd cond coeffs to local coefficients.
bool m_signChange
Flag indicating if modes require sign reversal.
Array< OneD, int > m_localToLocalIntMap
Integer map of local boundary coeffs to local interior system numbering.
int m_numGlobalCoeffs
Total number of global coefficients.
void CalculateBndSystemBandWidth()
Calculates the bandwidth of the boundary system.
Array< OneD, NekDouble > m_localToGlobalBndSign
Integer sign of local boundary coeffs to global space.
Array< OneD, unsigned int > m_numLocalBndCoeffsPerPatch
The number of bnd dofs per patch.
LibUtilities::SessionReaderSharedPtr m_session
Session object.
int m_numLocalBndCoeffs
Number of local boundary coefficients.
AssemblyMapSharedPtr m_nextLevelLocalToGlobalMap
Map from the patches of the previous level to the patches of the current level.
int m_staticCondLevel
The level of recursion in the case of multi-level static condensation.
int m_numGlobalDirBndCoeffs
Number of Global Dirichlet Boundary Coefficients.
Array< OneD, unsigned int > m_numLocalIntCoeffsPerPatch
The number of int dofs per patch.
Array< OneD, int > m_localToGlobalBndMap
Integer map of local coeffs to global Boundary Dofs.
Gs::gs_data * m_dirBndGsh
gs gather communication to impose Dirhichlet BCs.
LibUtilities::CommSharedPtr m_comm
Communicator.
Array< OneD, int > m_localToLocalBndMap
Integer map of local boundary coeffs to local boundary system numbering.
Array< OneD, NekDouble > m_bndCondCoeffsToLocalCoeffsSign
Integer map of sign of bnd cond coeffs to local coefficients.
int m_numPatches
The number of patches (~elements) in the current level.
int m_numGlobalBndCoeffs
Total number of global boundary coefficients.
static gs_data * Init(const Nektar::Array< OneD, long > &pId, const LibUtilities::CommSharedPtr &pComm, bool verbose=true)
Initialise Gather-Scatter map.
Definition GsLib.hpp:190
static void Gather(Nektar::Array< OneD, NekDouble > pU, gs_op pOp, gs_data *pGsh, Nektar::Array< OneD, NekDouble > pBuffer=NullNekDouble1DArray)
Performs a gather-scatter operation of the provided values.
Definition GsLib.hpp:278
@ gs_max
Definition GsLib.hpp:63
@ gs_min
Definition GsLib.hpp:62
static void Finalise(gs_data *pGsh)
Deallocates the GSLib mapping data.
Definition GsLib.hpp:248
constexpr int getNumberOfBndCoefficients(int Na, int Nb)
constexpr int getNumberOfCoefficients(int Na, int Nb)
constexpr int getNumberOfBndCoefficients(int Na, int Nb)
constexpr int getNumberOfCoefficients(int Na, int Nb)
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition Comm.h:55
@ eModified_B
Principle Modified Functions .
Definition BasisType.h:49
@ eModified_C
Principle Modified Functions .
Definition BasisType.h:50
@ eModifiedPyr_C
Principle Modified Functions.
Definition BasisType.h:53
@ eModified_A
Principle Modified Functions .
Definition BasisType.h:48
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition Expansion.h:66
std::vector< ExpansionSharedPtr > ExpansionVector
Definition Expansion.h:68
std::shared_ptr< BottomUpSubStructuredGraph > BottomUpSubStructuredGraphSharedPtr
std::tuple< int, int, NekDouble > ExtraDirDof
std::vector< std::map< int, int > > DofGraph
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...
StdRegions::Orientation DeterminePeriodicFaceOrient(StdRegions::Orientation faceOrient, StdRegions::Orientation perFaceOrient)
Determine relative orientation between two faces.
std::vector< double > p(NPUPPER)
std::vector< double > q(NPUPPER *NPUPPER)
std::size_t hash_range(Iter first, Iter last)
Definition HashUtils.hpp:64
T Vmax(int n, const T *x, const int incx)
Return the maximum element in x – called vmax to avoid conflict with max.
Definition Vmath.hpp:644
scalarT< T > min(scalarT< T > lhs, scalarT< T > rhs)
Definition scalar.hpp:300

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), ASSERTL0, ASSERTL1, Nektar::MultiRegions::AssemblyMap::CalculateBndSystemBandWidth(), CalculateFullSystemBandWidth(), CreateGraph(), Nektar::MultiRegions::DeterminePeriodicEdgeOrientId(), Nektar::MultiRegions::DeterminePeriodicFaceOrient(), Nektar::MultiRegions::eDirectMultiLevelStaticCond, Nektar::SpatialDomains::eDirichlet, Nektar::MultiRegions::eIterativeMultiLevelStaticCond, Nektar::LibUtilities::eModified_A, Nektar::LibUtilities::eModified_B, Nektar::LibUtilities::eModified_C, Nektar::LibUtilities::eModifiedPyr_C, Nektar::MultiRegions::ePETScMultiLevelStaticCond, Nektar::LibUtilities::eQuadrilateral, Nektar::LibUtilities::eTriangle, Nektar::MultiRegions::eXxtMultiLevelStaticCond, Gs::Finalise(), Gs::Gather(), Nektar::MultiRegions::ExpList::GetCoeff_Offset(), Nektar::MultiRegions::ExpList::GetExp(), Nektar::LibUtilities::StdTriData::getNumberOfBndCoefficients(), Nektar::LibUtilities::StdQuadData::getNumberOfBndCoefficients(), Nektar::LibUtilities::StdTriData::getNumberOfCoefficients(), Nektar::LibUtilities::StdQuadData::getNumberOfCoefficients(), Nektar::StdRegions::StdExpansion::GetTraceNcoeffs(), Gs::gs_max, Gs::gs_min, Nektar::hash_range(), Gs::Init(), Nektar::MultiRegions::AssemblyMap::m_bndCondCoeffsToLocalCoeffsMap, Nektar::MultiRegions::AssemblyMap::m_bndCondCoeffsToLocalCoeffsSign, Nektar::MultiRegions::AssemblyMap::m_bndGsh, Nektar::MultiRegions::AssemblyMap::m_comm, m_copyLocalDirDofs, Nektar::MultiRegions::AssemblyMap::m_dirBndGsh, m_globalToUniversalMap, Nektar::MultiRegions::AssemblyMap::m_hash, Nektar::MultiRegions::AssemblyMap::m_localToGlobalBndMap, Nektar::MultiRegions::AssemblyMap::m_localToGlobalBndSign, m_localToGlobalMap, 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, m_numLocalBndCondCoeffs, Nektar::MultiRegions::AssemblyMap::m_numLocalCoeffs, Nektar::MultiRegions::AssemblyMap::m_numLocalIntCoeffsPerPatch, Nektar::MultiRegions::AssemblyMap::m_numPatches, m_parallelDirBndSign, Nektar::MultiRegions::AssemblyMap::m_session, Nektar::MultiRegions::AssemblyMap::m_signChange, Nektar::MultiRegions::AssemblyMap::m_solnType, Nektar::MultiRegions::AssemblyMap::m_staticCondLevel, tinysimd::min(), Nektar::LibUtilities::P, Nektar::LibUtilities::ReduceSum, SetInvMultiplicityWithSign(), SetUpUniversalC0ContMap(), sign, and Vmath::Vmax().

◆ ~AssemblyMapCG()

Nektar::MultiRegions::AssemblyMapCG::~AssemblyMapCG ( )
override

Member Function Documentation

◆ CalculateFullSystemBandWidth()

void Nektar::MultiRegions::AssemblyMapCG::CalculateFullSystemBandWidth ( )
protected

Calculate the bandwith of the full matrix system.

The bandwidth calculated here corresponds to what is referred to as half-bandwidth. If the elements of the matrix are designated as a_ij, it corresponds to the maximum value of |i-j| for non-zero a_ij. As a result, the value also corresponds to the number of sub- or super-diagonals.

The bandwith can be calculated elementally as it corresponds to the maximal elemental bandwith (i.e. the maximal difference in global DOF index for every element).

We caluclate here the bandwith of the full global system.

Definition at line 2687 of file AssemblyMapCG.cpp.

2688{
2689 int i, j;
2690 int cnt = 0;
2691 int locSize;
2692 int maxId;
2693 int minId;
2694 int bwidth = -1;
2695 for (i = 0; i < m_numPatches; ++i)
2696 {
2697 locSize =
2699 maxId = -1;
2700 minId = m_numLocalCoeffs + 1;
2701 for (j = 0; j < locSize; j++)
2702 {
2704 {
2705 if (m_localToGlobalMap[cnt + j] > maxId)
2706 {
2707 maxId = m_localToGlobalMap[cnt + j];
2708 }
2709
2710 if (m_localToGlobalMap[cnt + j] < minId)
2711 {
2712 minId = m_localToGlobalMap[cnt + j];
2713 }
2714 }
2715 }
2716 bwidth = (bwidth > (maxId - minId)) ? bwidth : (maxId - minId);
2717
2718 cnt += locSize;
2719 }
2720
2721 m_fullSystemBandWidth = bwidth;
2722}
int m_fullSystemBandWidth
Bandwith of the full matrix system (no static condensation).

References m_fullSystemBandWidth, m_localToGlobalMap, Nektar::MultiRegions::AssemblyMap::m_numGlobalDirBndCoeffs, Nektar::MultiRegions::AssemblyMap::m_numLocalBndCoeffsPerPatch, Nektar::MultiRegions::AssemblyMap::m_numLocalCoeffs, Nektar::MultiRegions::AssemblyMap::m_numLocalIntCoeffsPerPatch, and Nektar::MultiRegions::AssemblyMap::m_numPatches.

Referenced by AssemblyMapCG().

◆ CreateGraph()

int Nektar::MultiRegions::AssemblyMapCG::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 
)
protected
  • Count verts, edges, face and add up edges and face sizes
  • Periodic vertices
  • Periodic edges
  • Periodic faces

STEP 4: Fill the #graph[0] and #graph[1] with the optimal ordering from boost.

Definition at line 77 of file AssemblyMapCG.cpp.

85{
86 int graphVertId = 0;
87 int vMaxVertId = -1;
88 int i, j, k, l, cnt;
89 int meshVertId, meshEdgeId, meshFaceId;
90 int meshVertId2, meshEdgeId2;
91
93 const LocalRegions::ExpansionVector &locExpVector = *(locExp.GetExp());
94 LibUtilities::CommSharedPtr vRowComm = m_comm->GetRowComm();
95
97 m_systemSingular = checkIfSystemSingular;
98
99 for (i = 0; i < bndCondExp.size(); i++)
100 {
101 m_numLocalBndCondCoeffs += bndCondExp[i]->GetNcoeffs();
102
103 if (bndConditions[0][i]->GetBoundaryConditionType() ==
105 {
106 continue;
107 }
108
109 // Check to see if any value on boundary has Dirichlet
110 // value. note this is a vector to manage coupled
111 // solver but for scalar will just be a vector of size 11
112 cnt = 0;
113 for (k = 0; k < bndConditions.size(); ++k)
114 {
115 if (bndConditions[k][i]->GetBoundaryConditionType() ==
117 {
118 cnt++;
119 }
120 if (bndConditions[k][i]->GetBoundaryConditionType() !=
122 {
123 m_systemSingular = false;
124 }
125 }
126
127 // Find the maximum boundary vertex ID on this process. This is
128 // used later to pin a vertex if the system is singular.
129 for (j = 0; j < bndCondExp[i]->GetNumElmts(); ++j)
130 {
131 bndExp = bndCondExp[i]->GetExp(j)->as<LocalRegions::Expansion>();
132 for (k = 0; k < bndExp->GetNverts(); ++k)
133 {
134 if (vMaxVertId < bndExp->GetGeom()->GetVid(k))
135 {
136 vMaxVertId = bndExp->GetGeom()->GetVid(k);
137 }
138 }
139 }
140
141 // If all boundaries are Dirichlet fill in graph
142 if (cnt == bndConditions.size())
143 {
144 for (j = 0; j < bndCondExp[i]->GetNumElmts(); j++)
145 {
146 bndExp = bndCondExp[i]->GetExp(j);
147
148 for (k = 0; k < bndExp->GetNverts(); k++)
149 {
150 meshVertId = bndExp->GetGeom()->GetVid(k);
151 if (graph[0].count(meshVertId) == 0)
152 {
153 graph[0][meshVertId] = graphVertId++;
154 }
155 }
156
157 const int bndDim = bndExp->GetNumBases();
158 if (bndDim > 1)
159 {
160 for (k = 0; k < bndExp->GetNtraces(); k++)
161 {
162 meshEdgeId = bndExp->GetGeom()->GetEid(k);
163 if (graph[1].count(meshEdgeId) == 0)
164 {
165 graph[1][meshEdgeId] = graphVertId++;
166 }
167 }
168 }
169
170 // Possibility of a face in 3D or edge in 2D
171 meshFaceId = bndExp->GetGeom()->GetGlobalID();
172 if (graph[bndDim].count(meshFaceId) == 0)
173 {
174 graph[bndDim][meshFaceId] = graphVertId++;
175 }
176 m_numLocalDirBndCoeffs += bndExp->GetNcoeffs();
177 }
178 }
179 }
180
181 // Number of dirichlet edges and faces (not considering periodic
182 // BCs)
183 m_numDirEdges = graph[1].size();
184 m_numDirFaces = graph[2].size();
185
186 /*
187 * The purpose of this routine is to deal with those degrees of
188 * freedom that are Dirichlet, but do not have a local Dirichlet
189 * boundary condition expansion set.
190 *
191 * For example, in 2D, consider a triangulation of a square into two
192 * triangles. Now imagine one edge of the square is Dirichlet and
193 * the problem is run on two processors. On one processor, one
194 * triangle vertex is Dirichlet, but doesn't know this since the
195 * Dirichlet composite lives on the other processor.
196 *
197 * When the global linear system is solved therefore, there is an
198 * inconsistency that at best leads to an inaccurate answer or a
199 * divergence of the system.
200 *
201 * This routine identifies such cases for 2D, and also for 3D where
202 * e.g. edges may have the same problem (consider an extrusion of
203 * the case above, for example).
204 */
205
206 // Collate information on Dirichlet vertices from all processes
207 int n = vRowComm->GetSize();
208 int p = vRowComm->GetRank();
209
210 if (vRowComm->IsSerial())
211 {
212 // for FieldConvert Comm this is true and it resets
213 // parallel processing back to serial case
214 n = 1;
215 p = 0;
216 }
217 // At this point, graph only contains information from Dirichlet
218 // boundaries. Therefore make a global list of the vert and edge
219 // information on all processors.
220 Array<OneD, int> vertcounts(n, 0);
221 Array<OneD, int> vertoffsets(n, 0);
222 Array<OneD, int> edgecounts(n, 0);
223 Array<OneD, int> edgeoffsets(n, 0);
224 vertcounts[p] = graph[0].size();
225 edgecounts[p] = graph[1].size();
226 vRowComm->AllReduce(vertcounts, LibUtilities::ReduceSum);
227 vRowComm->AllReduce(edgecounts, LibUtilities::ReduceSum);
228
229 for (i = 1; i < n; ++i)
230 {
231 vertoffsets[i] = vertoffsets[i - 1] + vertcounts[i - 1];
232 edgeoffsets[i] = edgeoffsets[i - 1] + edgecounts[i - 1];
233 }
234
235 int nTotVerts = Vmath::Vsum(n, vertcounts, 1);
236 int nTotEdges = Vmath::Vsum(n, edgecounts, 1);
237
238 Array<OneD, int> vertlist(nTotVerts, 0);
239 Array<OneD, int> edgelist(nTotEdges, 0);
240
241 // construct list of global ids of global vertices
242 i = 0;
243 for (auto &it : graph[0])
244 {
245 vertlist[vertoffsets[p] + i++] = it.first;
246 }
247
248 // construct list of global ids of global edges
249 i = 0;
250 for (auto &it : graph[1])
251 {
252 edgelist[edgeoffsets[p] + i++] = it.first;
253 }
254 vRowComm->AllReduce(vertlist, LibUtilities::ReduceSum);
255 vRowComm->AllReduce(edgelist, LibUtilities::ReduceSum);
256
257 // Now we have a list of all Dirichlet vertices and edges on all
258 // processors.
259 nExtraDirichlet = 0;
260 map<int, int> extraDirVertIds, extraDirEdgeIds;
261
262 // Ensure Dirchlet vertices are consistently recorded between
263 // processes (e.g. Dirichlet region meets Neumann region across a
264 // partition boundary requires vertex on partition to be Dirichlet).
265 //
266 // To do this we look over all elements and vertices in local
267 // partition and see if they match the values stored in the vertlist
268 // from other processors and if so record the meshVertId/meshEdgeId
269 // and the processor it comes from.
270 for (i = 0; i < n; ++i)
271 {
272 if (i == p)
273 {
274 continue;
275 }
276
277 for (j = 0; j < locExpVector.size(); j++)
278 {
279 exp = locExpVector[j];
280
281 for (k = 0; k < exp->GetNverts(); k++)
282 {
283 meshVertId = exp->GetGeom()->GetVid(k);
284 if (graph[0].count(meshVertId) == 0)
285 {
286 for (l = 0; l < vertcounts[i]; ++l)
287 {
288 if (vertlist[vertoffsets[i] + l] == meshVertId)
289 {
290 extraDirVertIds[meshVertId] = i;
291 graph[0][meshVertId] = graphVertId++;
292 nExtraDirichlet++;
293 }
294 }
295 }
296 }
297
298 for (k = 0; k < exp->GetGeom()->GetNumEdges(); k++)
299 {
300 meshEdgeId = exp->GetGeom()->GetEid(k);
301 if (graph[1].count(meshEdgeId) == 0)
302 {
303 for (l = 0; l < edgecounts[i]; ++l)
304 {
305 if (edgelist[edgeoffsets[i] + l] == meshEdgeId)
306 {
307 extraDirEdgeIds[meshEdgeId] = i;
308 graph[1][meshEdgeId] = graphVertId++;
309 if (exp->GetGeom()->GetNumFaces())
310 {
311 nExtraDirichlet +=
312 exp->as<LocalRegions::Expansion3D>()
313 ->GetEdgeNcoeffs(k) -
314 2;
315 }
316 else
317 {
318 nExtraDirichlet += exp->GetTraceNcoeffs(k) - 2;
319 }
320 }
321 }
322 }
323 }
324 }
325 }
326
327 // Low Energy preconditioner needs to know how many extra Dirichlet
328 // edges are on this process so store map in array.
329 m_extraDirEdges = Array<OneD, int>(extraDirEdgeIds.size(), -1);
330 i = 0;
331 for (auto &it : extraDirEdgeIds)
332 {
333 meshEdgeId = it.first;
334 m_extraDirEdges[i++] = meshEdgeId;
335 }
336
337 // Now we have a list of all vertices and edges that are Dirichlet
338 // and not defined on the local partition as well as which processor
339 // they are stored on.
340 //
341 // Make a full list of all such entities on all processors and which
342 // processor they belong to.
343 for (i = 0; i < n; ++i)
344 {
345 vertcounts[i] = 0;
346 vertoffsets[i] = 0;
347 edgecounts[i] = 0;
348 edgeoffsets[i] = 0;
349 }
350
351 vertcounts[p] = extraDirVertIds.size();
352 edgecounts[p] = extraDirEdgeIds.size();
353 vRowComm->AllReduce(vertcounts, LibUtilities::ReduceSum);
354 vRowComm->AllReduce(edgecounts, LibUtilities::ReduceSum);
355 nTotVerts = Vmath::Vsum(n, vertcounts, 1);
356 nTotEdges = Vmath::Vsum(n, edgecounts, 1);
357
358 vertoffsets[0] = edgeoffsets[0] = 0;
359
360 for (i = 1; i < n; ++i)
361 {
362 vertoffsets[i] = vertoffsets[i - 1] + vertcounts[i - 1];
363 edgeoffsets[i] = edgeoffsets[i - 1] + edgecounts[i - 1];
364 }
365
366 Array<OneD, int> vertids(nTotVerts, 0);
367 Array<OneD, int> edgeids(nTotEdges, 0);
368 Array<OneD, int> vertprocs(nTotVerts, 0);
369 Array<OneD, int> edgeprocs(nTotEdges, 0);
370
371 i = 0;
372 for (auto &it : extraDirVertIds)
373 {
374 vertids[vertoffsets[p] + i] = it.first;
375 vertprocs[vertoffsets[p] + i] = it.second;
376 ++i;
377 }
378
379 i = 0;
380 for (auto &it : extraDirEdgeIds)
381 {
382 edgeids[edgeoffsets[p] + i] = it.first;
383 edgeprocs[edgeoffsets[p] + i] = it.second;
384 ++i;
385 }
386
387 vRowComm->AllReduce(vertids, LibUtilities::ReduceSum);
388 vRowComm->AllReduce(vertprocs, LibUtilities::ReduceSum);
389 vRowComm->AllReduce(edgeids, LibUtilities::ReduceSum);
390 vRowComm->AllReduce(edgeprocs, LibUtilities::ReduceSum);
391
392 // Set up list of vertices that need to be shared to other
393 // partitions
394 for (i = 0; i < nTotVerts; ++i)
395 {
396 if (p == vertprocs[i]) // rank = vertproc[i]
397 {
398 extraDirVerts.insert(vertids[i]);
399 }
400 }
401
402 // Set up list of edges that need to be shared to other partitions
403 for (i = 0; i < nTotEdges; ++i)
404 {
405 if (p == edgeprocs[i]) // rank = vertproc[i]
406 {
407 extraDirEdges.insert(edgeids[i]);
408 }
409 }
410
411 // Check between processes if the whole system is singular
412 int s = m_systemSingular ? 1 : 0;
413 vRowComm->AllReduce(s, LibUtilities::ReduceMin);
414 m_systemSingular = s == 1 ? true : false;
415
416 // Find the minimum boundary vertex ID on each process
417 Array<OneD, int> bcminvertid(n, 0);
418 bcminvertid[p] = vMaxVertId;
419 vRowComm->AllReduce(bcminvertid, LibUtilities::ReduceMax);
420
421 // Find the process rank with the minimum boundary vertex ID
422 int maxIdx = Vmath::Imax(n, bcminvertid, 1);
423
424 // If the system is singular, the process with the maximum
425 // number of BCs will set a Dirichlet vertex to make
426 // system non-singular. Note: we find the process with
427 // maximum boundary regions to ensure we do not try to set
428 // a Dirichlet vertex on a partition with no intersection
429 // with the boundary.
430 meshVertId = 0;
431
432 if (m_systemSingular && checkIfSystemSingular && maxIdx == p)
433 {
434 if (m_session->DefinesParameter("SingularVertex"))
435 {
436 m_session->LoadParameter("SingularVertex", meshVertId);
437 }
438 else if (vMaxVertId == -1)
439 {
440 // All boundaries are periodic.
441 meshVertId = locExpVector[0]->GetGeom()->GetVid(0);
442 }
443 else
444 {
445 // Set pinned vertex to that with minimum vertex ID to
446 // ensure consistency in parallel.
447 meshVertId = bcminvertid[p];
448 }
449
450 if (graph[0].count(meshVertId) == 0)
451 {
452 graph[0][meshVertId] = graphVertId++;
453 }
454 }
455
456 vRowComm->AllReduce(meshVertId, LibUtilities::ReduceSum);
457
458 // When running in parallel, we need to ensure that the singular
459 // mesh vertex is communicated to any periodic vertices, otherwise
460 // the system may diverge.
461 if (m_systemSingular && checkIfSystemSingular)
462 {
463 // Firstly, we check that no other processors have this
464 // vertex. If they do, then we mark the vertex as also being
465 // Dirichlet.
466 if (maxIdx != p)
467 {
468 for (i = 0; i < locExpVector.size(); ++i)
469 {
470 for (j = 0; j < locExpVector[i]->GetNverts(); ++j)
471 {
472 if (locExpVector[i]->GetGeom()->GetVid(j) != meshVertId)
473 {
474 continue;
475 }
476
477 if (graph[0].count(meshVertId) == 0)
478 {
479 graph[0][meshVertId] = graphVertId++;
480 }
481 }
482 }
483 }
484
485 // In the case that meshVertId is periodic with other vertices,
486 // this process and all other processes need to make sure that
487 // the periodic vertices are also marked as Dirichlet.
488 int gId;
489
490 // At least one process (maxBCidx) will have already associated
491 // a graphVertId with meshVertId. Others won't even have any of
492 // the vertices. The logic below is designed to handle both
493 // cases.
494 if (graph[0].count(meshVertId) == 0)
495 {
496 gId = -1;
497 }
498 else
499 {
500 gId = graph[0][meshVertId];
501 }
502
503 for (auto &pIt : periodicVerts)
504 {
505 // Either the vertex is local to this processor (in which
506 // case it will be in the pIt.first position) or else
507 // meshVertId might be contained within another processor's
508 // vertex list. The if statement below covers both cases. If
509 // we find it, set as Dirichlet with the vertex id gId.
510 if (pIt.first == meshVertId)
511 {
512 gId = gId < 0 ? graphVertId++ : gId;
513 graph[0][meshVertId] = gId;
514
515 for (i = 0; i < pIt.second.size(); ++i)
516 {
517 if (pIt.second[i].isLocal)
518 {
519 graph[0][pIt.second[i].id] = graph[0][meshVertId];
520 }
521 }
522 }
523 else
524 {
525 bool found = false;
526 for (i = 0; i < pIt.second.size(); ++i)
527 {
528 if (pIt.second[i].id == meshVertId)
529 {
530 found = true;
531 break;
532 }
533 }
534
535 if (found)
536 {
537 gId = gId < 0 ? graphVertId++ : gId;
538 graph[0][pIt.first] = gId;
539
540 for (i = 0; i < pIt.second.size(); ++i)
541 {
542 if (pIt.second[i].isLocal)
543 {
544 graph[0][pIt.second[i].id] = graph[0][pIt.first];
545 }
546 }
547 }
548 }
549 }
550 }
551
552 // Add extra dirichlet boundary conditions to count.
553 m_numLocalDirBndCoeffs += nExtraDirichlet;
554 firstNonDirGraphVertId = graphVertId;
555
556 typedef boost::adjacency_list<boost::setS, boost::vecS, boost::undirectedS>
557 BoostGraph;
558 BoostGraph boostGraphObj;
559
560 vector<map<int, int>> tempGraph(3);
561 map<int, int> vwgts_map;
562 Array<OneD, int> localVerts;
563 Array<OneD, int> localEdges;
564 Array<OneD, int> localFaces;
565
566 int tempGraphVertId = 0;
567 int localVertOffset = 0;
568 int localEdgeOffset = 0;
569 int localFaceOffset = 0;
570 int nTotalVerts = 0;
571 int nTotalEdges = 0;
572 int nTotalFaces = 0;
573 int nVerts;
574 int nEdges;
575 int nFaces;
576 int vertCnt;
577 int edgeCnt;
578 int faceCnt;
579
586
587 map<int, int> EdgeSize;
588 map<int, int> FaceSize;
589
590 /// - Count verts, edges, face and add up edges and face sizes
591 for (i = 0; i < locExpVector.size(); ++i)
592 {
593 exp = locExpVector[i];
594 nEdges = exp->GetGeom()->GetNumEdges();
595 nFaces = exp->GetGeom()->GetNumFaces();
596
597 nTotalVerts += exp->GetNverts();
598 nTotalEdges += nEdges;
599 nTotalFaces += nFaces;
600
601 for (j = 0; j < nEdges; ++j)
602 {
603 meshEdgeId = exp->GetGeom()->GetEid(j);
604 int nEdgeInt;
605
606 if (nFaces)
607 {
608 nEdgeInt =
609 exp->as<LocalRegions::Expansion3D>()->GetEdgeNcoeffs(j) - 2;
610 }
611 else
612 {
613 nEdgeInt = exp->GetTraceNcoeffs(j) - 2;
614 }
615
616 if (EdgeSize.count(meshEdgeId) > 0)
617 {
618 EdgeSize[meshEdgeId] = min(EdgeSize[meshEdgeId], nEdgeInt);
619 }
620 else
621 {
622 EdgeSize[meshEdgeId] = nEdgeInt;
623 }
624 }
625
626 faceCnt = 0;
627 for (j = 0; j < nFaces; ++j)
628 {
629 meshFaceId = exp->GetGeom()->GetFid(j);
630 if (FaceSize.count(meshFaceId) > 0)
631 {
632 FaceSize[meshFaceId] =
633 min(FaceSize[meshFaceId], exp->GetTraceIntNcoeffs(j));
634 }
635 else
636 {
637 FaceSize[meshFaceId] = exp->GetTraceIntNcoeffs(j);
638 }
639 FaceSize[meshFaceId] = exp->GetTraceIntNcoeffs(j);
640 }
641 }
642
643 /// - Periodic vertices
644 for (auto &pIt : periodicVerts)
645 {
646 meshVertId = pIt.first;
647
648 // This periodic vertex is joined to a Dirichlet condition.
649 if (graph[0].count(pIt.first) != 0)
650 {
651 for (i = 0; i < pIt.second.size(); ++i)
652 {
653 meshVertId2 = pIt.second[i].id;
654 if (graph[0].count(meshVertId2) == 0 && pIt.second[i].isLocal)
655 {
656 graph[0][meshVertId2] = graph[0][meshVertId];
657 }
658 }
659 continue;
660 }
661
662 // One of the attached vertices is Dirichlet.
663 bool isDirichlet = false;
664 for (i = 0; i < pIt.second.size(); ++i)
665 {
666 if (!pIt.second[i].isLocal)
667 {
668 continue;
669 }
670
671 meshVertId2 = pIt.second[i].id;
672 if (graph[0].count(meshVertId2) > 0)
673 {
674 isDirichlet = true;
675 break;
676 }
677 }
678
679 if (isDirichlet)
680 {
681 graph[0][meshVertId] = graph[0][pIt.second[i].id];
682
683 for (j = 0; j < pIt.second.size(); ++j)
684 {
685 meshVertId2 = pIt.second[i].id;
686 if (j == i || !pIt.second[j].isLocal ||
687 graph[0].count(meshVertId2) > 0)
688 {
689 continue;
690 }
691
692 graph[0][meshVertId2] = graph[0][pIt.second[i].id];
693 }
694
695 continue;
696 }
697
698 // Otherwise, see if a vertex ID has already been set.
699 for (i = 0; i < pIt.second.size(); ++i)
700 {
701 if (!pIt.second[i].isLocal)
702 {
703 continue;
704 }
705
706 if (tempGraph[0].count(pIt.second[i].id) > 0)
707 {
708 break;
709 }
710 }
711
712 if (i == pIt.second.size())
713 {
714 boost::add_vertex(boostGraphObj);
715 tempGraph[0][meshVertId] = tempGraphVertId++;
717 }
718 else
719 {
720 tempGraph[0][meshVertId] = tempGraph[0][pIt.second[i].id];
721 }
722 }
723
724 // Store the temporary graph vertex id's of all element edges and
725 // vertices in these 3 arrays below
726 localVerts = Array<OneD, int>(nTotalVerts, -1);
727 localEdges = Array<OneD, int>(nTotalEdges, -1);
728 localFaces = Array<OneD, int>(nTotalFaces, -1);
729
730 // Set up vertex numbering
731 for (i = 0; i < locExpVector.size(); ++i)
732 {
733 exp = locExpVector[i];
734 vertCnt = 0;
735 nVerts = exp->GetNverts();
736 for (j = 0; j < nVerts; ++j)
737 {
738 meshVertId = exp->GetGeom()->GetVid(j);
739 if (graph[0].count(meshVertId) == 0)
740 {
741 if (tempGraph[0].count(meshVertId) == 0)
742 {
743 boost::add_vertex(boostGraphObj);
744 tempGraph[0][meshVertId] = tempGraphVertId++;
746 }
747 localVerts[localVertOffset + vertCnt++] =
748 tempGraph[0][meshVertId];
749 vwgts_map[tempGraph[0][meshVertId]] = 1;
750 }
751 }
752
753 localVertOffset += nVerts;
754 }
755
756 /// - Periodic edges
757 for (auto &pIt : periodicEdges)
758 {
759 meshEdgeId = pIt.first;
760
761 // This periodic edge is joined to a Dirichlet condition.
762 if (graph[1].count(pIt.first) != 0)
763 {
764 for (i = 0; i < pIt.second.size(); ++i)
765 {
766 meshEdgeId2 = pIt.second[i].id;
767 if (graph[1].count(meshEdgeId2) == 0 && pIt.second[i].isLocal)
768 {
769 graph[1][meshEdgeId2] = graph[1][meshEdgeId];
770 }
771 }
772 continue;
773 }
774
775 // One of the attached edges is Dirichlet.
776 bool isDirichlet = false;
777 for (i = 0; i < pIt.second.size(); ++i)
778 {
779 if (!pIt.second[i].isLocal)
780 {
781 continue;
782 }
783
784 meshEdgeId2 = pIt.second[i].id;
785 if (graph[1].count(meshEdgeId2) > 0)
786 {
787 isDirichlet = true;
788 break;
789 }
790 }
791
792 if (isDirichlet)
793 {
794 graph[1][meshEdgeId] = graph[1][pIt.second[i].id];
795
796 for (j = 0; j < pIt.second.size(); ++j)
797 {
798 meshEdgeId2 = pIt.second[i].id;
799 if (j == i || !pIt.second[j].isLocal ||
800 graph[1].count(meshEdgeId2) > 0)
801 {
802 continue;
803 }
804
805 graph[1][meshEdgeId2] = graph[1][pIt.second[i].id];
806 }
807
808 continue;
809 }
810
811 // Otherwise, see if a edge ID has already been set.
812 for (i = 0; i < pIt.second.size(); ++i)
813 {
814 if (!pIt.second[i].isLocal)
815 {
816 continue;
817 }
818
819 if (tempGraph[1].count(pIt.second[i].id) > 0)
820 {
821 break;
822 }
823 }
824
825 if (i == pIt.second.size())
826 {
827 boost::add_vertex(boostGraphObj);
828 tempGraph[1][meshEdgeId] = tempGraphVertId++;
829 m_numNonDirEdgeModes += EdgeSize[meshEdgeId];
831 }
832 else
833 {
834 tempGraph[1][meshEdgeId] = tempGraph[1][pIt.second[i].id];
835 }
836 }
837
838 int nEdgeIntCoeffs, nFaceIntCoeffs;
839
840 // Set up edge numbering
841 for (i = 0; i < locExpVector.size(); ++i)
842 {
843 exp = locExpVector[i];
844 edgeCnt = 0;
845 nEdges = exp->GetGeom()->GetNumEdges();
846
847 for (j = 0; j < nEdges; ++j)
848 {
849 meshEdgeId = exp->GetGeom()->GetEid(j);
850 nEdgeIntCoeffs = EdgeSize[meshEdgeId];
851 if (graph[1].count(meshEdgeId) == 0)
852 {
853 if (tempGraph[1].count(meshEdgeId) == 0)
854 {
855 boost::add_vertex(boostGraphObj);
856 tempGraph[1][meshEdgeId] = tempGraphVertId++;
857 m_numNonDirEdgeModes += nEdgeIntCoeffs;
858
860 }
861 localEdges[localEdgeOffset + edgeCnt++] =
862 tempGraph[1][meshEdgeId];
863 vwgts_map[tempGraph[1][meshEdgeId]] = nEdgeIntCoeffs;
864 }
865 }
866
867 localEdgeOffset += nEdges;
868 }
869
870 /// - Periodic faces
871 for (auto &pIt : periodicFaces)
872 {
873 if (!pIt.second[0].isLocal)
874 {
875 // The face mapped to is on another process.
876 meshFaceId = pIt.first;
877 ASSERTL0(graph[2].count(meshFaceId) == 0,
878 "This periodic boundary edge has been specified before");
879 boost::add_vertex(boostGraphObj);
880 tempGraph[2][meshFaceId] = tempGraphVertId++;
881 nFaceIntCoeffs = FaceSize[meshFaceId];
882 m_numNonDirFaceModes += nFaceIntCoeffs;
884 }
885 else if (pIt.first < pIt.second[0].id)
886 {
887 ASSERTL0(graph[2].count(pIt.first) == 0,
888 "This periodic boundary face has been specified before");
889 ASSERTL0(graph[2].count(pIt.second[0].id) == 0,
890 "This periodic boundary face has been specified before");
891
892 boost::add_vertex(boostGraphObj);
893 tempGraph[2][pIt.first] = tempGraphVertId;
894 tempGraph[2][pIt.second[0].id] = tempGraphVertId++;
895 nFaceIntCoeffs = FaceSize[pIt.first];
896 m_numNonDirFaceModes += nFaceIntCoeffs;
898 }
899 }
900
901 // setup face numbering
902 for (i = 0; i < locExpVector.size(); ++i)
903 {
904 exp = locExpVector[i];
905 nFaces = exp->GetGeom()->GetNumFaces();
906 faceCnt = 0;
907 for (j = 0; j < nFaces; ++j)
908 {
909 nFaceIntCoeffs = exp->GetTraceIntNcoeffs(j);
910 meshFaceId = exp->GetGeom()->GetFid(j);
911 if (graph[2].count(meshFaceId) == 0)
912 {
913 if (tempGraph[2].count(meshFaceId) == 0)
914 {
915 boost::add_vertex(boostGraphObj);
916 tempGraph[2][meshFaceId] = tempGraphVertId++;
917 m_numNonDirFaceModes += nFaceIntCoeffs;
918
920 }
921 localFaces[localFaceOffset + faceCnt++] =
922 tempGraph[2][meshFaceId];
923 vwgts_map[tempGraph[2][meshFaceId]] = nFaceIntCoeffs;
924 }
925 }
926 m_numLocalBndCoeffs += exp->NumBndryCoeffs();
927
928 localFaceOffset += nFaces;
929 }
930
931 localVertOffset = 0;
932 localEdgeOffset = 0;
933 localFaceOffset = 0;
934 for (i = 0; i < locExpVector.size(); ++i)
935 {
936 exp = locExpVector[i];
937 nVerts = exp->GetNverts();
938 nEdges = exp->GetGeom()->GetNumEdges();
939 nFaces = exp->GetGeom()->GetNumFaces();
940
941 // Now loop over all local faces, edges and vertices of this
942 // element and define that all other faces, edges and verices of
943 // this element are adjacent to them.
944
945 // Vertices
946 for (j = 0; j < nVerts; j++)
947 {
948 if (localVerts[j + localVertOffset] == -1)
949 {
950 continue;
951 }
952 // associate to other vertices
953 for (k = j + 1; k < nVerts; k++)
954 {
955 if (localVerts[k + localVertOffset] == -1)
956 {
957 continue;
958 }
959
960 boost::add_edge((size_t)localVerts[j + localVertOffset],
961 (size_t)localVerts[k + localVertOffset],
962 boostGraphObj);
963 }
964 // associate to other edges
965 for (k = 0; k < nEdges; k++)
966 {
967 if (localEdges[k + localEdgeOffset] == -1)
968 {
969 continue;
970 }
971 boost::add_edge((size_t)localVerts[j + localVertOffset],
972 (size_t)localEdges[k + localEdgeOffset],
973 boostGraphObj);
974 }
975 // associate to other faces
976 for (k = 0; k < nFaces; k++)
977 {
978 if (localFaces[k + localFaceOffset] == -1)
979 {
980 continue;
981 }
982 boost::add_edge((size_t)localVerts[j + localVertOffset],
983 (size_t)localFaces[k + localFaceOffset],
984 boostGraphObj);
985 }
986 }
987
988 // Edges
989 for (j = 0; j < nEdges; j++)
990 {
991 if (localEdges[j + localEdgeOffset] == -1)
992 {
993 continue;
994 }
995 // Associate to other edges
996 for (k = j + 1; k < nEdges; k++)
997 {
998 if (localEdges[k + localEdgeOffset] == -1)
999 {
1000 continue;
1001 }
1002 boost::add_edge((size_t)localEdges[j + localEdgeOffset],
1003 (size_t)localEdges[k + localEdgeOffset],
1004 boostGraphObj);
1005 }
1006 // Associate to faces
1007 for (k = 0; k < nFaces; k++)
1008 {
1009 if (localFaces[k + localFaceOffset] == -1)
1010 {
1011 continue;
1012 }
1013 boost::add_edge((size_t)localEdges[j + localEdgeOffset],
1014 (size_t)localFaces[k + localFaceOffset],
1015 boostGraphObj);
1016 }
1017 }
1018
1019 // Faces
1020 for (j = 0; j < nFaces; j++)
1021 {
1022 if (localFaces[j + localFaceOffset] == -1)
1023 {
1024 continue;
1025 }
1026 // Associate to other faces
1027 for (k = j + 1; k < nFaces; k++)
1028 {
1029 if (localFaces[k + localFaceOffset] == -1)
1030 {
1031 continue;
1032 }
1033 boost::add_edge((size_t)localFaces[j + localFaceOffset],
1034 (size_t)localFaces[k + localFaceOffset],
1035 boostGraphObj);
1036 }
1037 }
1038
1039 localVertOffset += nVerts;
1040 localEdgeOffset += nEdges;
1041 localFaceOffset += nFaces;
1042 }
1043
1044 // Container to store vertices of the graph which correspond to
1045 // degrees of freedom along the boundary and periodic BCs.
1046 set<int> partVerts;
1047
1050 {
1051 vector<long> procVerts, procEdges, procFaces;
1052 set<int> foundVerts, foundEdges, foundFaces;
1053
1054 // Loop over element and construct the procVerts and procEdges
1055 // vectors, which store the geometry IDs of mesh vertices and
1056 // edges respectively which are local to this process.
1057 for (i = cnt = 0; i < locExpVector.size(); ++i)
1058 {
1059 int elmtid = i;
1060 exp = locExpVector[elmtid];
1061 for (j = 0; j < exp->GetNverts(); ++j)
1062 {
1063 int vid = exp->GetGeom()->GetVid(j) + 1;
1064 if (foundVerts.count(vid) == 0)
1065 {
1066 procVerts.push_back(vid);
1067 foundVerts.insert(vid);
1068 }
1069 }
1070
1071 for (j = 0; j < exp->GetGeom()->GetNumEdges(); ++j)
1072 {
1073 int eid = exp->GetGeom()->GetEid(j) + 1;
1074
1075 if (foundEdges.count(eid) == 0)
1076 {
1077 procEdges.push_back(eid);
1078 foundEdges.insert(eid);
1079 }
1080 }
1081
1082 for (j = 0; j < exp->GetGeom()->GetNumFaces(); ++j)
1083 {
1084 int fid = exp->GetGeom()->GetFid(j) + 1;
1085
1086 if (foundFaces.count(fid) == 0)
1087 {
1088 procFaces.push_back(fid);
1089 foundFaces.insert(fid);
1090 }
1091 }
1092 }
1093
1094 int unique_verts = foundVerts.size();
1095 int unique_edges = foundEdges.size();
1096 int unique_faces = foundFaces.size();
1097
1098 bool verbose = m_session->DefinesCmdLineArgument("verbose");
1099
1100 // Now construct temporary GS objects. These will be used to
1101 // populate the arrays tmp3 and tmp4 with the multiplicity of
1102 // the vertices and edges respectively to identify those
1103 // vertices and edges which are located on partition boundary.
1104 Array<OneD, long> vertArray(unique_verts, &procVerts[0]);
1105 Gs::gs_data *tmp1 = Gs::Init(vertArray, vRowComm, verbose);
1106 Array<OneD, NekDouble> tmp4(unique_verts, 1.0);
1107 Array<OneD, NekDouble> tmp5(unique_edges, 1.0);
1108 Array<OneD, NekDouble> tmp6(unique_faces, 1.0);
1109 Gs::Gather(tmp4, Gs::gs_add, tmp1);
1110 Gs::Finalise(tmp1);
1111
1112 if (unique_edges > 0)
1113 {
1114 Array<OneD, long> edgeArray(unique_edges, &procEdges[0]);
1115 Gs::gs_data *tmp2 = Gs::Init(edgeArray, vRowComm, verbose);
1116 Gs::Gather(tmp5, Gs::gs_add, tmp2);
1117 Gs::Finalise(tmp2);
1118 }
1119
1120 if (unique_faces > 0)
1121 {
1122 Array<OneD, long> faceArray(unique_faces, &procFaces[0]);
1123 Gs::gs_data *tmp3 = Gs::Init(faceArray, vRowComm, verbose);
1124 Gs::Gather(tmp6, Gs::gs_add, tmp3);
1125 Gs::Finalise(tmp3);
1126 }
1127
1128 // Finally, fill the partVerts set with all non-Dirichlet
1129 // vertices which lie on a partition boundary.
1130 for (i = 0; i < unique_verts; ++i)
1131 {
1132 if (tmp4[i] > 1.0)
1133 {
1134 if (graph[0].count(procVerts[i] - 1) == 0)
1135 {
1136 partVerts.insert(tempGraph[0][procVerts[i] - 1]);
1137 }
1138 }
1139 }
1140
1141 for (i = 0; i < unique_edges; ++i)
1142 {
1143 if (tmp5[i] > 1.0)
1144 {
1145 if (graph[1].count(procEdges[i] - 1) == 0)
1146 {
1147 partVerts.insert(tempGraph[1][procEdges[i] - 1]);
1148 }
1149 }
1150 }
1151
1152 for (i = 0; i < unique_faces; ++i)
1153 {
1154 if (tmp6[i] > 1.0)
1155 {
1156 if (graph[2].count(procFaces[i] - 1) == 0)
1157 {
1158 partVerts.insert(tempGraph[2][procFaces[i] - 1]);
1159 }
1160 }
1161 }
1162
1163 // Now fill with all vertices on periodic BCs
1164 for (auto &pIt : periodicVerts)
1165 {
1166 if (graph[0].count(pIt.first) == 0)
1167 {
1168 partVerts.insert(tempGraph[0][pIt.first]);
1169 }
1170 }
1171 for (auto &pIt : periodicEdges)
1172 {
1173 if (graph[1].count(pIt.first) == 0)
1174 {
1175 partVerts.insert(tempGraph[1][pIt.first]);
1176 }
1177 }
1178 for (auto &pIt : periodicFaces)
1179 {
1180 if (graph[2].count(pIt.first) == 0)
1181 {
1182 partVerts.insert(tempGraph[2][pIt.first]);
1183 }
1184 }
1185 }
1186
1187 int nGraphVerts = tempGraphVertId;
1188 Array<OneD, int> perm(nGraphVerts);
1189 Array<OneD, int> iperm(nGraphVerts);
1190
1191 if (nGraphVerts)
1192 {
1193 switch (m_solnType)
1194 {
1195 case eDirectFullMatrix:
1196 case eIterativeFull:
1198 case ePETScStaticCond:
1199 case ePETScFullMatrix:
1200 case eXxtFullMatrix:
1201 case eXxtStaticCond:
1202 {
1203 NoReordering(boostGraphObj, perm, iperm);
1204 break;
1205 }
1206
1207 case eDirectStaticCond:
1208 {
1209 CuthillMckeeReordering(boostGraphObj, perm, iperm);
1210 break;
1211 }
1212
1217 {
1218 MultiLevelBisectionReordering(boostGraphObj, perm, iperm,
1219 bottomUpGraph, partVerts,
1220 mdswitch);
1221 break;
1222 }
1223 default:
1224 {
1225 ASSERTL0(false,
1226 "Unrecognised solution type: " +
1227 std::string(GlobalSysSolnTypeMap[m_solnType]));
1228 }
1229 }
1230 }
1231
1232 // For parallel multi-level static condensation determine the lowest
1233 // static condensation level amongst processors.
1238 bottomUpGraph)
1239 {
1240 m_lowestStaticCondLevel = bottomUpGraph->GetNlevels() - 1;
1242 }
1243 else
1244 {
1246 }
1247
1248 /**
1249 * STEP 4: Fill the #graph[0] and
1250 * #graph[1] with the optimal ordering from boost.
1251 */
1252 for (auto &mapIt : tempGraph[0])
1253 {
1254 graph[0][mapIt.first] = iperm[mapIt.second] + graphVertId;
1255 }
1256 for (auto &mapIt : tempGraph[1])
1257 {
1258 graph[1][mapIt.first] = iperm[mapIt.second] + graphVertId;
1259 }
1260 for (auto &mapIt : tempGraph[2])
1261 {
1262 graph[2][mapIt.first] = iperm[mapIt.second] + graphVertId;
1263 }
1264
1265 return nGraphVerts;
1266}
int m_numNonDirVertexModes
Number of non Dirichlet vertex modes.
int m_numNonDirEdges
Number of Dirichlet edges.
Array< OneD, int > m_extraDirEdges
Extra dirichlet edges in parallel.
int m_numNonDirFaceModes
Number of non Dirichlet face modes.
int m_numNonDirEdgeModes
Number of non Dirichlet edge modes.
int m_numDirEdges
Number of Dirichlet edges.
int m_numDirFaces
Number of Dirichlet faces.
int m_numNonDirFaces
Number of Dirichlet faces.
int m_lowestStaticCondLevel
Lowest static condensation level.
int m_numLocalDirBndCoeffs
Number of Local Dirichlet Boundary Coefficients.
bool m_systemSingular
Flag indicating if the system is singular or not.
@ gs_add
Definition GsLib.hpp:60
void NoReordering(const BoostGraph &graph, Array< OneD, int > &perm, Array< OneD, int > &iperm)
void CuthillMckeeReordering(const BoostGraph &graph, Array< OneD, int > &perm, Array< OneD, int > &iperm)
void MultiLevelBisectionReordering(const BoostGraph &graph, Array< OneD, int > &perm, Array< OneD, int > &iperm, BottomUpSubStructuredGraphSharedPtr &substructgraph, std::set< int > partVerts, int mdswitch)
const char *const GlobalSysSolnTypeMap[]
T Vsum(int n, const T *x, const int incx)
Subtract return sum(x)
Definition Vmath.hpp:608
int Imax(int n, const T *x, const int incx)
Return the index of the maximum element in x.
Definition Vmath.hpp:623

References ASSERTL0, Nektar::MultiRegions::CuthillMckeeReordering(), Nektar::MultiRegions::eDirectFullMatrix, Nektar::MultiRegions::eDirectMultiLevelStaticCond, Nektar::MultiRegions::eDirectStaticCond, Nektar::SpatialDomains::eDirichlet, Nektar::MultiRegions::eIterativeFull, Nektar::MultiRegions::eIterativeMultiLevelStaticCond, Nektar::MultiRegions::eIterativeStaticCond, Nektar::SpatialDomains::eNeumann, Nektar::SpatialDomains::ePeriodic, Nektar::MultiRegions::ePETScFullMatrix, Nektar::MultiRegions::ePETScMultiLevelStaticCond, Nektar::MultiRegions::ePETScStaticCond, Nektar::MultiRegions::eXxtFullMatrix, Nektar::MultiRegions::eXxtMultiLevelStaticCond, Nektar::MultiRegions::eXxtStaticCond, Gs::Finalise(), Gs::Gather(), Nektar::MultiRegions::ExpList::GetExp(), Nektar::LocalRegions::Expansion::GetGeom(), Nektar::StdRegions::StdExpansion::GetTraceNcoeffs(), Nektar::SpatialDomains::Geometry::GetVid(), Nektar::MultiRegions::GlobalSysSolnTypeMap, Gs::gs_add, Vmath::Imax(), Gs::Init(), Nektar::MultiRegions::AssemblyMap::m_comm, m_extraDirEdges, Nektar::MultiRegions::AssemblyMap::m_lowestStaticCondLevel, m_numDirEdges, m_numDirFaces, Nektar::MultiRegions::AssemblyMap::m_numLocalBndCoeffs, m_numLocalBndCondCoeffs, Nektar::MultiRegions::AssemblyMap::m_numLocalDirBndCoeffs, m_numNonDirEdgeModes, m_numNonDirEdges, m_numNonDirFaceModes, m_numNonDirFaces, m_numNonDirVertexModes, Nektar::MultiRegions::AssemblyMap::m_session, Nektar::MultiRegions::AssemblyMap::m_solnType, Nektar::MultiRegions::AssemblyMap::m_systemSingular, tinysimd::min(), Nektar::MultiRegions::MultiLevelBisectionReordering(), Nektar::MultiRegions::NoReordering(), Nektar::LibUtilities::ReduceMax, Nektar::LibUtilities::ReduceMin, Nektar::LibUtilities::ReduceSum, and Vmath::Vsum().

Referenced by AssemblyMapCG(), and Nektar::CoupledLocalToGlobalC0ContMap::CoupledLocalToGlobalC0ContMap().

◆ GetCopyLocalDirDofs()

std::set< ExtraDirDof > & Nektar::MultiRegions::AssemblyMapCG::GetCopyLocalDirDofs ( )
inline

Definition at line 94 of file AssemblyMapCG.h.

95 {
96 return m_copyLocalDirDofs;
97 }

References m_copyLocalDirDofs.

◆ GetParallelDirBndSign()

std::set< int > & Nektar::MultiRegions::AssemblyMapCG::GetParallelDirBndSign ( )
inline

Definition at line 99 of file AssemblyMapCG.h.

100 {
102 }

References m_parallelDirBndSign.

◆ SetInvMultiplicityWithSign()

void Nektar::MultiRegions::AssemblyMapCG::SetInvMultiplicityWithSign ( void  )
private

Definition at line 2953 of file AssemblyMapCG.cpp.

2954{
2955 m_invMultiplicityWithSign = Array<OneD, NekDouble>(m_numLocalCoeffs, 0.0);
2956
2957 Array<OneD, NekDouble> l2gSign;
2958
2959 if (m_localToGlobalSign.size())
2960 {
2961 l2gSign = m_localToGlobalSign;
2962 }
2963 else // case that does not need to have sign array set up
2964 {
2965 l2gSign = Array<OneD, NekDouble>(m_numLocalCoeffs, 1.0);
2966 }
2967
2970 for (unsigned i = 0; i < m_numLocalCoeffs; ++i)
2971 {
2972 // for variable order mult might be near zero. All non-zero
2973 // values shoudl be one or bigger so large tolreance shoudl
2974 // be fine
2975 if (fabs(m_invMultiplicityWithSign[i]) < 0.1)
2976 {
2978 }
2979 else
2980 {
2982 }
2983 }
2984}
Array< OneD, NekDouble > m_invMultiplicityWithSign
Inverse of multiplicity with sign.
void Assemble(const Array< OneD, const NekDouble > &loc, Array< OneD, NekDouble > &global) const
void GlobalToLocal(const Array< OneD, const NekDouble > &global, Array< OneD, NekDouble > &loc) const

References Nektar::MultiRegions::AssemblyMap::Assemble(), Nektar::MultiRegions::AssemblyMap::GlobalToLocal(), m_invMultiplicityWithSign, m_localToGlobalSign, and Nektar::MultiRegions::AssemblyMap::m_numLocalCoeffs.

Referenced by AssemblyMapCG().

◆ SetUpUniversalC0ContMap()

void Nektar::MultiRegions::AssemblyMapCG::SetUpUniversalC0ContMap ( const ExpList locExp,
const PeriodicMap perVerts = NullPeriodicMap,
const PeriodicMap perEdges = NullPeriodicMap,
const PeriodicMap perFaces = NullPeriodicMap 
)
protected

Sets up the global to universal mapping of degrees of freedom across processors.

Definition at line 2292 of file AssemblyMapCG.cpp.

2296{
2298 int nVert = 0;
2299 int nEdge = 0;
2300 int nFace = 0;
2301 int maxEdgeDof = 0;
2302 int maxFaceDof = 0;
2303 int maxIntDof = 0;
2304 int dof = 0;
2305 int cnt;
2306 int i, j, k, l;
2307 int meshVertId;
2308 int meshEdgeId;
2309 int meshFaceId;
2310 int elementId;
2311 int vGlobalId;
2312 int maxBndGlobalId = 0;
2313 StdRegions::Orientation edgeOrient;
2314 StdRegions::Orientation faceOrient;
2315 Array<OneD, unsigned int> edgeInteriorMap;
2316 Array<OneD, int> edgeInteriorSign;
2317 Array<OneD, unsigned int> faceInteriorMap;
2318 Array<OneD, int> faceInteriorSign;
2319 Array<OneD, unsigned int> interiorMap;
2320
2321 const LocalRegions::ExpansionVector &locExpVector = *(locExp.GetExp());
2322 LibUtilities::CommSharedPtr vRowComm = m_comm->GetRowComm();
2323 const bool verbose = locExp.GetSession()->DefinesCmdLineArgument("verbose");
2324
2332
2333 // Loop over all the elements in the domain to gather mesh data
2334 for (i = 0; i < locExpVector.size(); ++i)
2335 {
2336 exp = locExpVector[i];
2337
2338 int nv = exp->GetNverts();
2339 int ne = exp->GetGeom()->GetNumEdges();
2340 int nf = exp->GetGeom()->GetNumFaces();
2341
2342 nVert += nv;
2343 nEdge += ne;
2344 nFace += nf;
2345
2346 // Loop over all edges (and vertices) of element i
2347 for (j = 0; j < ne; ++j)
2348 {
2349 if (nf)
2350 {
2351 dof =
2352 exp->as<LocalRegions::Expansion3D>()->GetEdgeNcoeffs(j) - 2;
2353 }
2354 else
2355 {
2356 dof = exp->GetTraceNcoeffs(j) - 2;
2357 }
2358
2359 maxEdgeDof = (dof > maxEdgeDof ? dof : maxEdgeDof);
2360 }
2361 for (j = 0; j < nf; ++j)
2362 {
2363 dof = exp->GetTraceIntNcoeffs(j);
2364 maxFaceDof = (dof > maxFaceDof ? dof : maxFaceDof);
2365 }
2366 exp->GetInteriorMap(interiorMap);
2367 dof = interiorMap.size();
2368 maxIntDof = (dof > maxIntDof ? dof : maxIntDof);
2369 }
2370
2371 // Tell other processes about how many dof we have
2372 vRowComm->AllReduce(nVert, LibUtilities::ReduceSum);
2373 vRowComm->AllReduce(nEdge, LibUtilities::ReduceSum);
2374 vRowComm->AllReduce(nFace, LibUtilities::ReduceSum);
2375 vRowComm->AllReduce(maxEdgeDof, LibUtilities::ReduceMax);
2376 vRowComm->AllReduce(maxFaceDof, LibUtilities::ReduceMax);
2377 vRowComm->AllReduce(maxIntDof, LibUtilities::ReduceMax);
2378
2379 // Assemble global to universal mapping for this process
2380 for (i = 0; i < locExpVector.size(); ++i)
2381 {
2382 exp = locExpVector[i];
2383 cnt = locExp.GetCoeff_Offset(i);
2384
2385 int nf = exp->GetGeom()->GetNumFaces();
2386
2387 // Loop over all vertices of element i
2388 for (j = 0; j < exp->GetNverts(); ++j)
2389 {
2390 meshVertId = exp->GetGeom()->GetVid(j);
2391 vGlobalId = m_localToGlobalMap[cnt + exp->GetVertexMap(j)];
2392
2393 auto pIt = perVerts.find(meshVertId);
2394 if (pIt != perVerts.end())
2395 {
2396 for (k = 0; k < pIt->second.size(); ++k)
2397 {
2398 meshVertId = min(meshVertId, pIt->second[k].id);
2399 }
2400 }
2401
2402 m_globalToUniversalMap[vGlobalId] = meshVertId + 1;
2403 m_globalToUniversalBndMap[vGlobalId] =
2404 m_globalToUniversalMap[vGlobalId];
2405 maxBndGlobalId =
2406 (vGlobalId > maxBndGlobalId ? vGlobalId : maxBndGlobalId);
2407 }
2408
2409 // Loop over all edges of element i
2410 for (j = 0; j < exp->GetGeom()->GetNumEdges(); ++j)
2411 {
2412 meshEdgeId = exp->GetGeom()->GetEid(j);
2413 auto pIt = perEdges.find(meshEdgeId);
2414 edgeOrient = exp->GetGeom()->GetEorient(j);
2415
2416 if (pIt != perEdges.end())
2417 {
2418 pair<int, StdRegions::Orientation> idOrient =
2419 DeterminePeriodicEdgeOrientId(meshEdgeId, edgeOrient,
2420 pIt->second);
2421 meshEdgeId = idOrient.first;
2422 edgeOrient = idOrient.second;
2423 }
2424
2425 if (nf) // 3D version
2426 {
2427 exp->as<LocalRegions::Expansion3D>()
2428 ->GetEdgeInteriorToElementMap(j, edgeInteriorMap,
2429 edgeInteriorSign, edgeOrient);
2430 dof =
2431 exp->as<LocalRegions::Expansion3D>()->GetEdgeNcoeffs(j) - 2;
2432 }
2433 else // 2D version
2434 {
2435 exp->GetTraceInteriorToElementMap(j, edgeInteriorMap,
2436 edgeInteriorSign, edgeOrient);
2437 dof = exp->GetTraceNcoeffs(j) - 2;
2438 }
2439
2440 // Set the global DOF's for the interior modes of edge j
2441 // for varP, ignore modes with sign == 0
2442 for (k = 0, l = 0; k < dof; ++k)
2443 {
2444 if (m_signChange)
2445 {
2446 if (m_localToGlobalSign[cnt + edgeInteriorMap[k]] == 0)
2447 {
2448 continue;
2449 }
2450 }
2451 vGlobalId = m_localToGlobalMap[cnt + edgeInteriorMap[k]];
2452 m_globalToUniversalMap[vGlobalId] =
2453 nVert + meshEdgeId * maxEdgeDof + l + 1;
2454 m_globalToUniversalBndMap[vGlobalId] =
2455 m_globalToUniversalMap[vGlobalId];
2456 maxBndGlobalId =
2457 (vGlobalId > maxBndGlobalId ? vGlobalId : maxBndGlobalId);
2458 l++;
2459 }
2460 }
2461
2462 // Loop over all faces of element i
2463 for (j = 0; j < exp->GetGeom()->GetNumFaces(); ++j)
2464 {
2465 faceOrient = exp->GetGeom()->GetForient(j);
2466
2467 meshFaceId = exp->GetGeom()->GetFid(j);
2468
2469 auto pIt = perFaces.find(meshFaceId);
2470 if (pIt != perFaces.end())
2471 {
2472 if (meshFaceId == min(meshFaceId, pIt->second[0].id))
2473 {
2474 faceOrient = DeterminePeriodicFaceOrient(
2475 faceOrient, pIt->second[0].orient);
2476 }
2477 meshFaceId = min(meshFaceId, pIt->second[0].id);
2478 }
2479
2480 exp->GetTraceInteriorToElementMap(j, faceInteriorMap,
2481 faceInteriorSign, faceOrient);
2482 dof = exp->GetTraceIntNcoeffs(j);
2483
2484 for (k = 0, l = 0; k < dof; ++k)
2485 {
2486 if (m_signChange)
2487 {
2488 if (m_localToGlobalSign[cnt + faceInteriorMap[k]] == 0)
2489 {
2490 continue;
2491 }
2492 }
2493 vGlobalId = m_localToGlobalMap[cnt + faceInteriorMap[k]];
2494 m_globalToUniversalMap[vGlobalId] = nVert + nEdge * maxEdgeDof +
2495 meshFaceId * maxFaceDof +
2496 l + 1;
2497 m_globalToUniversalBndMap[vGlobalId] =
2498 m_globalToUniversalMap[vGlobalId];
2499
2500 maxBndGlobalId =
2501 (vGlobalId > maxBndGlobalId ? vGlobalId : maxBndGlobalId);
2502 l++;
2503 }
2504 }
2505
2506 // Add interior DOFs to complete universal numbering
2507 exp->GetInteriorMap(interiorMap);
2508 dof = interiorMap.size();
2509 elementId = (exp->GetGeom())->GetGlobalID();
2510 for (k = 0; k < dof; ++k)
2511 {
2512 vGlobalId = m_localToGlobalMap[cnt + interiorMap[k]];
2513 m_globalToUniversalMap[vGlobalId] = nVert + nEdge * maxEdgeDof +
2514 nFace * maxFaceDof +
2515 elementId * maxIntDof + k + 1;
2516 }
2517 }
2518
2519 // Set up the GSLib universal assemble mapping
2520 // Internal DOF do not participate in any data
2521 // exchange, so we keep these set to the special GSLib id=0 so
2522 // they are ignored.
2526 for (unsigned int i = 0; i < m_numGlobalBndCoeffs; ++i)
2527 {
2528 tmp[i] = m_globalToUniversalMap[i];
2529 }
2530
2531 m_gsh = Gs::Init(tmp, vRowComm, verbose);
2532 m_bndGsh = Gs::Init(tmp2, vRowComm, verbose);
2533 Gs::Unique(tmp, vRowComm);
2534 for (unsigned int i = 0; i < m_numGlobalCoeffs; ++i)
2535 {
2536 m_globalToUniversalMapUnique[i] = (tmp[i] >= 0 ? 1 : 0);
2537 }
2538 for (unsigned int i = 0; i < m_numGlobalBndCoeffs; ++i)
2539 {
2540 m_globalToUniversalBndMapUnique[i] = (tmp2[i] >= 0 ? 1 : 0);
2541 }
2542}
Array< OneD, int > m_globalToUniversalMapUnique
Integer map of unique process coeffs to universal space (signed)
Array< OneD, int > m_globalToUniversalBndMap
Integer map of process coeffs to universal space.
Array< OneD, int > m_globalToUniversalBndMapUnique
Integer map of unique process coeffs to universal space (signed)
static void Unique(const Nektar::Array< OneD, long > &pId, const LibUtilities::CommSharedPtr &pComm)
Updates pId to negate all-but-one references to each universal ID.
Definition GsLib.hpp:225
void Zero(int n, T *x, const int incx)
Zero vector.
Definition Vmath.hpp:273

References Nektar::MultiRegions::DeterminePeriodicEdgeOrientId(), Nektar::MultiRegions::DeterminePeriodicFaceOrient(), Nektar::MultiRegions::ExpList::GetCoeff_Offset(), Nektar::MultiRegions::ExpList::GetExp(), Nektar::MultiRegions::ExpList::GetSession(), Nektar::StdRegions::StdExpansion::GetTraceInteriorToElementMap(), Nektar::StdRegions::StdExpansion::GetTraceNcoeffs(), Gs::Init(), Nektar::MultiRegions::AssemblyMap::m_bndGsh, Nektar::MultiRegions::AssemblyMap::m_comm, Nektar::MultiRegions::AssemblyMap::m_globalToUniversalBndMap, Nektar::MultiRegions::AssemblyMap::m_globalToUniversalBndMapUnique, m_globalToUniversalMap, m_globalToUniversalMapUnique, Nektar::MultiRegions::AssemblyMap::m_gsh, m_localToGlobalMap, m_localToGlobalSign, Nektar::MultiRegions::AssemblyMap::m_numGlobalBndCoeffs, Nektar::MultiRegions::AssemblyMap::m_numGlobalCoeffs, Nektar::MultiRegions::AssemblyMap::m_signChange, tinysimd::min(), Nektar::LibUtilities::ReduceMax, Nektar::LibUtilities::ReduceSum, Gs::Unique(), and Vmath::Zero().

Referenced by AssemblyMapCG().

◆ v_Assemble() [1/2]

void Nektar::MultiRegions::AssemblyMapCG::v_Assemble ( const Array< OneD, const NekDouble > &  loc,
Array< OneD, NekDouble > &  global 
) const
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2860 of file AssemblyMapCG.cpp.

2862{
2863 Array<OneD, const NekDouble> local;
2864 if (global.data() == loc.data())
2865 {
2866 local = Array<OneD, NekDouble>(m_numLocalCoeffs, loc.data());
2867 }
2868 else
2869 {
2870 local = loc; // create reference
2871 }
2872
2873 Vmath::Zero(m_numGlobalCoeffs, global.data(), 1);
2874
2875 if (m_signChange)
2876 {
2878 m_localToGlobalMap.data(), global.data());
2879 }
2880 else
2881 {
2882 Vmath::Assmb(m_numLocalCoeffs, local.data(), m_localToGlobalMap.data(),
2883 global.data());
2884 }
2885 UniversalAssemble(global);
2886}
void UniversalAssemble(Array< OneD, NekDouble > &pGlobal) const
void Assmb(int n, const T *x, const int *y, T *z)
Assemble z[y[i]] += x[i]; z should be zero'd first.
Definition Vmath.hpp:577

References Vmath::Assmb(), m_localToGlobalMap, m_localToGlobalSign, Nektar::MultiRegions::AssemblyMap::m_numGlobalCoeffs, Nektar::MultiRegions::AssemblyMap::m_numLocalCoeffs, Nektar::MultiRegions::AssemblyMap::m_signChange, Nektar::MultiRegions::AssemblyMap::UniversalAssemble(), and Vmath::Zero().

◆ v_Assemble() [2/2]

void Nektar::MultiRegions::AssemblyMapCG::v_Assemble ( const NekVector< NekDouble > &  loc,
NekVector< NekDouble > &  global 
) const
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2888 of file AssemblyMapCG.cpp.

2890{
2891 Assemble(loc.GetPtr(), global.GetPtr());
2892}
Array< OneD, DataType > & GetPtr()

References Nektar::MultiRegions::AssemblyMap::Assemble(), and Nektar::NekVector< DataType >::GetPtr().

◆ v_AvgAssemble()

void Nektar::MultiRegions::AssemblyMapCG::v_AvgAssemble ( const Array< OneD, const NekDouble > &  loc,
Array< OneD, NekDouble > &  global,
bool  useComm 
) const
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2835 of file AssemblyMapCG.cpp.

2838{
2839 Array<OneD, const NekDouble> local;
2840 if (global.data() == loc.data())
2841 {
2842 local = Array<OneD, NekDouble>(m_numLocalCoeffs, loc.data());
2843 }
2844 else
2845 {
2846 local = loc; // create reference
2847 }
2848
2849 Vmath::Zero(m_numGlobalCoeffs, global.data(), 1);
2850
2852 local.data(), m_localToGlobalMap.data(), global.data());
2853
2854 if (useComm)
2855 {
2856 UniversalAssemble(global);
2857 }
2858}

References Vmath::Assmb(), m_invMultiplicityWithSign, m_localToGlobalMap, Nektar::MultiRegions::AssemblyMap::m_numGlobalCoeffs, Nektar::MultiRegions::AssemblyMap::m_numLocalCoeffs, Nektar::MultiRegions::AssemblyMap::UniversalAssemble(), and Vmath::Zero().

◆ v_GetExtraDirEdges()

const Array< OneD, const int > & Nektar::MultiRegions::AssemblyMapCG::v_GetExtraDirEdges ( )
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2948 of file AssemblyMapCG.cpp.

2949{
2950 return m_extraDirEdges;
2951}

References m_extraDirEdges.

◆ v_GetFullSystemBandWidth()

int Nektar::MultiRegions::AssemblyMapCG::v_GetFullSystemBandWidth ( ) const
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2908 of file AssemblyMapCG.cpp.

2909{
2910 return m_fullSystemBandWidth;
2911}

References m_fullSystemBandWidth.

◆ v_GetGlobalToUniversalMap() [1/2]

const Array< OneD, const int > & Nektar::MultiRegions::AssemblyMapCG::v_GetGlobalToUniversalMap ( void  )
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2744 of file AssemblyMapCG.cpp.

2745{
2747}

References m_globalToUniversalMap.

◆ v_GetGlobalToUniversalMap() [2/2]

int Nektar::MultiRegions::AssemblyMapCG::v_GetGlobalToUniversalMap ( const int  i) const
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2729 of file AssemblyMapCG.cpp.

2730{
2731 return m_globalToUniversalMap[i];
2732}

References m_globalToUniversalMap.

◆ v_GetGlobalToUniversalMapUnique() [1/2]

const Array< OneD, const int > & Nektar::MultiRegions::AssemblyMapCG::v_GetGlobalToUniversalMapUnique ( void  )
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2749 of file AssemblyMapCG.cpp.

2751{
2753}

References m_globalToUniversalMapUnique.

◆ v_GetGlobalToUniversalMapUnique() [2/2]

int Nektar::MultiRegions::AssemblyMapCG::v_GetGlobalToUniversalMapUnique ( const int  i) const
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2734 of file AssemblyMapCG.cpp.

2735{
2737}

References m_globalToUniversalMapUnique.

◆ v_GetLocalToGlobalMap() [1/2]

const Array< OneD, const int > & Nektar::MultiRegions::AssemblyMapCG::v_GetLocalToGlobalMap ( void  )
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2739 of file AssemblyMapCG.cpp.

2740{
2741 return m_localToGlobalMap;
2742}

References m_localToGlobalMap.

◆ v_GetLocalToGlobalMap() [2/2]

int Nektar::MultiRegions::AssemblyMapCG::v_GetLocalToGlobalMap ( const int  i) const
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2724 of file AssemblyMapCG.cpp.

2725{
2726 return m_localToGlobalMap[i];
2727}

References m_localToGlobalMap.

◆ v_GetLocalToGlobalSign() [1/2]

const Array< OneD, NekDouble > & Nektar::MultiRegions::AssemblyMapCG::v_GetLocalToGlobalSign ( ) const
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2767 of file AssemblyMapCG.cpp.

2768{
2769 return m_localToGlobalSign;
2770}

References m_localToGlobalSign.

◆ v_GetLocalToGlobalSign() [2/2]

NekDouble Nektar::MultiRegions::AssemblyMapCG::v_GetLocalToGlobalSign ( const int  i) const
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2755 of file AssemblyMapCG.cpp.

2756{
2757 if (m_signChange)
2758 {
2759 return m_localToGlobalSign[i];
2760 }
2761 else
2762 {
2763 return 1.0;
2764 }
2765}

References m_localToGlobalSign, and Nektar::MultiRegions::AssemblyMap::m_signChange.

◆ v_GetNumDirEdges()

int Nektar::MultiRegions::AssemblyMapCG::v_GetNumDirEdges ( ) const
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2928 of file AssemblyMapCG.cpp.

2929{
2930 return m_numDirEdges;
2931}

References m_numDirEdges.

◆ v_GetNumDirFaces()

int Nektar::MultiRegions::AssemblyMapCG::v_GetNumDirFaces ( ) const
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2933 of file AssemblyMapCG.cpp.

2934{
2935 return m_numDirFaces;
2936}

References m_numDirFaces.

◆ v_GetNumNonDirEdgeModes()

int Nektar::MultiRegions::AssemblyMapCG::v_GetNumNonDirEdgeModes ( ) const
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2918 of file AssemblyMapCG.cpp.

2919{
2920 return m_numNonDirEdgeModes;
2921}

References m_numNonDirEdgeModes.

◆ v_GetNumNonDirEdges()

int Nektar::MultiRegions::AssemblyMapCG::v_GetNumNonDirEdges ( ) const
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2938 of file AssemblyMapCG.cpp.

2939{
2940 return m_numNonDirEdges;
2941}

References m_numNonDirEdges.

◆ v_GetNumNonDirFaceModes()

int Nektar::MultiRegions::AssemblyMapCG::v_GetNumNonDirFaceModes ( ) const
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2923 of file AssemblyMapCG.cpp.

2924{
2925 return m_numNonDirFaceModes;
2926}

References m_numNonDirFaceModes.

◆ v_GetNumNonDirFaces()

int Nektar::MultiRegions::AssemblyMapCG::v_GetNumNonDirFaces ( ) const
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2943 of file AssemblyMapCG.cpp.

2944{
2945 return m_numNonDirFaces;
2946}

References m_numNonDirFaces.

◆ v_GetNumNonDirVertexModes()

int Nektar::MultiRegions::AssemblyMapCG::v_GetNumNonDirVertexModes ( ) const
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2913 of file AssemblyMapCG.cpp.

2914{
2916}

References m_numNonDirVertexModes.

◆ v_GlobalToLocal() [1/2]

void Nektar::MultiRegions::AssemblyMapCG::v_GlobalToLocal ( const Array< OneD, const NekDouble > &  global,
Array< OneD, NekDouble > &  loc 
) const
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2804 of file AssemblyMapCG.cpp.

2806{
2807 Array<OneD, const NekDouble> glo;
2808 if (global.data() == loc.data())
2809 {
2810 glo = Array<OneD, NekDouble>(m_numGlobalCoeffs, global.data());
2811 }
2812 else
2813 {
2814 glo = global; // create reference
2815 }
2816
2817 if (m_signChange)
2818 {
2820 m_localToGlobalMap.data(), loc.data());
2821 }
2822 else
2823 {
2825 loc.data());
2826 }
2827}
void Gathr(I n, const T *x, const I *y, T *z)
Gather vector z[i] = x[y[i]].
Definition Vmath.hpp:507

References Vmath::Gathr(), m_localToGlobalMap, m_localToGlobalSign, Nektar::MultiRegions::AssemblyMap::m_numGlobalCoeffs, Nektar::MultiRegions::AssemblyMap::m_numLocalCoeffs, and Nektar::MultiRegions::AssemblyMap::m_signChange.

◆ v_GlobalToLocal() [2/2]

void Nektar::MultiRegions::AssemblyMapCG::v_GlobalToLocal ( const NekVector< NekDouble > &  global,
NekVector< NekDouble > &  loc 
) const
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2829 of file AssemblyMapCG.cpp.

2831{
2832 GlobalToLocal(global.GetPtr(), loc.GetPtr());
2833}

References Nektar::NekVector< DataType >::GetPtr(), and Nektar::MultiRegions::AssemblyMap::GlobalToLocal().

◆ v_LinearSpaceMap()

AssemblyMapSharedPtr Nektar::MultiRegions::AssemblyMapCG::v_LinearSpaceMap ( const ExpList locexp,
GlobalSysSolnType  solnType 
)
overrideprotectedvirtual

Construct an AssemblyMapCG object which corresponds to the linear space of the current object.

This function is used to create a linear-space assembly map, which is then used in the linear space preconditioner in the conjugate gradient solve.

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2552 of file AssemblyMapCG.cpp.

2554{
2555 AssemblyMapCGSharedPtr returnval;
2556
2557 int i, j;
2558 int nverts = 0;
2559 const std::shared_ptr<LocalRegions::ExpansionVector> exp = locexp.GetExp();
2560 int nelmts = exp->size();
2561 const bool verbose = locexp.GetSession()->DefinesCmdLineArgument("verbose");
2562
2563 // Get Default Map and turn off any searched values.
2565 m_session, locexp.GetComm());
2566 returnval->m_solnType = solnType;
2567 returnval->m_preconType = "Null";
2568 returnval->m_maxStaticCondLevel = 0;
2569 returnval->m_signChange = false;
2570 returnval->m_comm = m_comm;
2571
2572 // Count the number of vertices
2573 for (i = 0; i < nelmts; ++i)
2574 {
2575 nverts += (*exp)[i]->GetNverts();
2576 }
2577
2578 returnval->m_numLocalCoeffs = nverts;
2579 returnval->m_localToGlobalMap = Array<OneD, int>(nverts, -1);
2580
2581 // Store original global ids in this map
2582 returnval->m_localToGlobalBndMap = Array<OneD, int>(nverts, -1);
2583
2584 int cnt = 0;
2585 int cnt1 = 0;
2586 Array<OneD, int> GlobCoeffs(m_numGlobalCoeffs, -1);
2587
2588 // Set up local to global map;
2589 for (i = 0; i < nelmts; ++i)
2590 {
2591 for (j = 0; j < (*exp)[i]->GetNverts(); ++j)
2592 {
2593 returnval->m_localToGlobalMap[cnt] =
2594 returnval->m_localToGlobalBndMap[cnt] =
2595 m_localToGlobalMap[cnt1 + (*exp)[i]->GetVertexMap(j, true)];
2596 GlobCoeffs[returnval->m_localToGlobalMap[cnt]] = 1;
2597
2598 // Set up numLocalDirBndCoeffs
2599 if ((returnval->m_localToGlobalMap[cnt]) < m_numGlobalDirBndCoeffs)
2600 {
2601 returnval->m_numLocalDirBndCoeffs++;
2602 }
2603 cnt++;
2604 }
2605 cnt1 += (*exp)[i]->GetNcoeffs();
2606 }
2607
2608 cnt = 0;
2609 // Reset global numbering and count number of dofs
2610 for (i = 0; i < m_numGlobalCoeffs; ++i)
2611 {
2612 if (GlobCoeffs[i] != -1)
2613 {
2614 GlobCoeffs[i] = cnt++;
2615 }
2616 }
2617
2618 // Set up number of globalCoeffs;
2619 returnval->m_numGlobalCoeffs = cnt;
2620
2621 // Set up number of global Dirichlet boundary coefficients
2622 for (i = 0; i < m_numGlobalDirBndCoeffs; ++i)
2623 {
2624 if (GlobCoeffs[i] != -1)
2625 {
2626 returnval->m_numGlobalDirBndCoeffs++;
2627 }
2628 }
2629
2630 // Set up global to universal map
2631 if (m_globalToUniversalMap.size())
2632 {
2634 m_session->GetComm()->GetRowComm();
2635 int nglocoeffs = returnval->m_numGlobalCoeffs;
2636 returnval->m_globalToUniversalMap = Array<OneD, int>(nglocoeffs);
2637 returnval->m_globalToUniversalMapUnique = Array<OneD, int>(nglocoeffs);
2638
2639 // Reset local to global map and setup universal map
2640 for (i = 0; i < nverts; ++i)
2641 {
2642 cnt = returnval->m_localToGlobalMap[i];
2643 returnval->m_localToGlobalMap[i] = GlobCoeffs[cnt];
2644
2645 returnval->m_globalToUniversalMap[GlobCoeffs[cnt]] =
2647 }
2648
2649 Nektar::Array<OneD, long> tmp(nglocoeffs);
2650 Vmath::Zero(nglocoeffs, tmp, 1);
2651 for (unsigned int i = 0; i < nglocoeffs; ++i)
2652 {
2653 tmp[i] = returnval->m_globalToUniversalMap[i];
2654 }
2655 returnval->m_gsh = Gs::Init(tmp, vRowComm, verbose);
2656 Gs::Unique(tmp, vRowComm);
2657 for (unsigned int i = 0; i < nglocoeffs; ++i)
2658 {
2659 returnval->m_globalToUniversalMapUnique[i] = (tmp[i] >= 0 ? 1 : 0);
2660 }
2661 }
2662 else // not sure this option is ever needed.
2663 {
2664 for (i = 0; i < nverts; ++i)
2665 {
2666 cnt = returnval->m_localToGlobalMap[i];
2667 returnval->m_localToGlobalMap[i] = GlobCoeffs[cnt];
2668 }
2669 }
2670
2671 return returnval;
2672}
std::shared_ptr< AssemblyMapCG > AssemblyMapCGSharedPtr

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), Nektar::MultiRegions::ExpList::GetComm(), Nektar::MultiRegions::ExpList::GetExp(), Nektar::MultiRegions::ExpList::GetSession(), Gs::Init(), Nektar::MultiRegions::AssemblyMap::m_comm, m_globalToUniversalMap, m_localToGlobalMap, Nektar::MultiRegions::AssemblyMap::m_numGlobalCoeffs, Nektar::MultiRegions::AssemblyMap::m_numGlobalDirBndCoeffs, Nektar::MultiRegions::AssemblyMap::m_session, Gs::Unique(), and Vmath::Zero().

◆ v_LocalToGlobal()

void Nektar::MultiRegions::AssemblyMapCG::v_LocalToGlobal ( const Array< OneD, const NekDouble > &  loc,
Array< OneD, NekDouble > &  global,
bool  useComm 
) const
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2772 of file AssemblyMapCG.cpp.

2775{
2776 Array<OneD, const NekDouble> local;
2777 if (global.data() == loc.data())
2778 {
2779 local = Array<OneD, NekDouble>(m_numLocalCoeffs, loc.data());
2780 }
2781 else
2782 {
2783 local = loc; // create reference
2784 }
2785
2786 if (m_signChange)
2787 {
2789 m_localToGlobalMap.data(), global.data());
2790 }
2791 else
2792 {
2793 Vmath::Scatr(m_numLocalCoeffs, local.data(), m_localToGlobalMap.data(),
2794 global.data());
2795 }
2796
2797 // ensure all values are unique by calling a max
2798 if (useComm)
2799 {
2800 Gs::Gather(global, Gs::gs_max, m_gsh);
2801 }
2802}
void Scatr(int n, const T *x, const int *y, T *z)
Scatter vector z[y[i]] = x[i].
Definition Vmath.hpp:539

References Gs::Gather(), Gs::gs_max, Nektar::MultiRegions::AssemblyMap::m_gsh, m_localToGlobalMap, m_localToGlobalSign, Nektar::MultiRegions::AssemblyMap::m_numLocalCoeffs, Nektar::MultiRegions::AssemblyMap::m_signChange, and Vmath::Scatr().

◆ v_UniversalAssemble() [1/2]

void Nektar::MultiRegions::AssemblyMapCG::v_UniversalAssemble ( Array< OneD, NekDouble > &  pGlobal) const
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2894 of file AssemblyMapCG.cpp.

2895{
2896 Gs::Gather(pGlobal, Gs::gs_add, m_gsh);
2897}

References Gs::Gather(), Gs::gs_add, and Nektar::MultiRegions::AssemblyMap::m_gsh.

◆ v_UniversalAssemble() [2/2]

void Nektar::MultiRegions::AssemblyMapCG::v_UniversalAssemble ( Array< OneD, NekDouble > &  pGlobal,
int  offset 
) const
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::AssemblyMap.

Definition at line 2899 of file AssemblyMapCG.cpp.

2901{
2902 Array<OneD, NekDouble> tmp(offset);
2903 Vmath::Vcopy(offset, pGlobal, 1, tmp, 1);
2904 UniversalAssemble(pGlobal);
2905 Vmath::Vcopy(offset, tmp, 1, pGlobal, 1);
2906}
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition Vmath.hpp:825

References Nektar::MultiRegions::AssemblyMap::UniversalAssemble(), and Vmath::Vcopy().

Member Data Documentation

◆ m_copyLocalDirDofs

std::set<ExtraDirDof> Nektar::MultiRegions::AssemblyMapCG::m_copyLocalDirDofs
protected

Set indicating degrees of freedom which are Dirichlet but whose value is stored on another processor.

Definition at line 141 of file AssemblyMapCG.h.

Referenced by AssemblyMapCG(), and GetCopyLocalDirDofs().

◆ m_extraDirEdges

Array<OneD, int> Nektar::MultiRegions::AssemblyMapCG::m_extraDirEdges
protected

Extra dirichlet edges in parallel.

Definition at line 134 of file AssemblyMapCG.h.

Referenced by CreateGraph(), and v_GetExtraDirEdges().

◆ m_fullSystemBandWidth

int Nektar::MultiRegions::AssemblyMapCG::m_fullSystemBandWidth
protected

Bandwith of the full matrix system (no static condensation).

Definition at line 112 of file AssemblyMapCG.h.

Referenced by CalculateFullSystemBandWidth(), and v_GetFullSystemBandWidth().

◆ m_globalToUniversalMap

Array<OneD, int> Nektar::MultiRegions::AssemblyMapCG::m_globalToUniversalMap
protected

◆ m_globalToUniversalMapUnique

Array<OneD, int> Nektar::MultiRegions::AssemblyMapCG::m_globalToUniversalMapUnique
protected

Integer map of unique process coeffs to universal space (signed)

Definition at line 116 of file AssemblyMapCG.h.

Referenced by Nektar::CoupledAssemblyMap::CoupledAssemblyMap(), SetUpUniversalC0ContMap(), v_GetGlobalToUniversalMapUnique(), and v_GetGlobalToUniversalMapUnique().

◆ m_invMultiplicityWithSign

Array<OneD, NekDouble> Nektar::MultiRegions::AssemblyMapCG::m_invMultiplicityWithSign
protected

Inverse of multiplicity with sign.

Definition at line 110 of file AssemblyMapCG.h.

Referenced by SetInvMultiplicityWithSign(), and v_AvgAssemble().

◆ m_localToGlobalMap

Array<OneD, int> Nektar::MultiRegions::AssemblyMapCG::m_localToGlobalMap
protected

◆ m_localToGlobalSign

Array<OneD, NekDouble> Nektar::MultiRegions::AssemblyMapCG::m_localToGlobalSign
protected

◆ m_maxStaticCondLevel

int Nektar::MultiRegions::AssemblyMapCG::m_maxStaticCondLevel
protected

Maximum static condensation level.

Definition at line 138 of file AssemblyMapCG.h.

Referenced by AssemblyMapCG().

◆ m_numDirEdges

int Nektar::MultiRegions::AssemblyMapCG::m_numDirEdges
protected

Number of Dirichlet edges.

Definition at line 124 of file AssemblyMapCG.h.

Referenced by CreateGraph(), and v_GetNumDirEdges().

◆ m_numDirFaces

int Nektar::MultiRegions::AssemblyMapCG::m_numDirFaces
protected

Number of Dirichlet faces.

Definition at line 126 of file AssemblyMapCG.h.

Referenced by CreateGraph(), and v_GetNumDirFaces().

◆ m_numLocalBndCondCoeffs

int Nektar::MultiRegions::AssemblyMapCG::m_numLocalBndCondCoeffs
protected

Number of local boundary condition coefficients.

Definition at line 132 of file AssemblyMapCG.h.

Referenced by AssemblyMapCG(), and CreateGraph().

◆ m_numLocDirBndCondDofs

int Nektar::MultiRegions::AssemblyMapCG::m_numLocDirBndCondDofs
protected

Number of local boundary condition degrees of freedom.

Definition at line 136 of file AssemblyMapCG.h.

◆ m_numNonDirEdgeModes

int Nektar::MultiRegions::AssemblyMapCG::m_numNonDirEdgeModes
protected

Number of non Dirichlet edge modes.

Definition at line 120 of file AssemblyMapCG.h.

Referenced by CreateGraph(), and v_GetNumNonDirEdgeModes().

◆ m_numNonDirEdges

int Nektar::MultiRegions::AssemblyMapCG::m_numNonDirEdges
protected

Number of Dirichlet edges.

Definition at line 128 of file AssemblyMapCG.h.

Referenced by CreateGraph(), and v_GetNumNonDirEdges().

◆ m_numNonDirFaceModes

int Nektar::MultiRegions::AssemblyMapCG::m_numNonDirFaceModes
protected

Number of non Dirichlet face modes.

Definition at line 122 of file AssemblyMapCG.h.

Referenced by CreateGraph(), and v_GetNumNonDirFaceModes().

◆ m_numNonDirFaces

int Nektar::MultiRegions::AssemblyMapCG::m_numNonDirFaces
protected

Number of Dirichlet faces.

Definition at line 130 of file AssemblyMapCG.h.

Referenced by CreateGraph(), and v_GetNumNonDirFaces().

◆ m_numNonDirVertexModes

int Nektar::MultiRegions::AssemblyMapCG::m_numNonDirVertexModes
protected

Number of non Dirichlet vertex modes.

Definition at line 118 of file AssemblyMapCG.h.

Referenced by CreateGraph(), and v_GetNumNonDirVertexModes().

◆ m_parallelDirBndSign

std::set<int> Nektar::MultiRegions::AssemblyMapCG::m_parallelDirBndSign
protected

Set indicating the local coeffs just touching parallel dirichlet boundary that have a sign change.

Definition at line 144 of file AssemblyMapCG.h.

Referenced by AssemblyMapCG(), and GetParallelDirBndSign().