Feature: Rewrite of GGI comms on AMG agglomeration
This commit is contained in:
parent
c076f28ce1
commit
3143f456cc
17 changed files with 501 additions and 279 deletions
|
@ -950,6 +950,7 @@ Foam::BlockMatrixAgglomeration<Type>::restrictMatrix() const
|
||||||
AMGInterface::New
|
AMGInterface::New
|
||||||
(
|
(
|
||||||
coarseAddrPtr(),
|
coarseAddrPtr(),
|
||||||
|
coarseInterfaces,
|
||||||
fineInterface,
|
fineInterface,
|
||||||
fineInterface.interfaceInternalField(agglomIndex_),
|
fineInterface.interfaceInternalField(agglomIndex_),
|
||||||
fineInterfaceAddr[intI]
|
fineInterfaceAddr[intI]
|
||||||
|
|
|
@ -292,6 +292,7 @@ void Foam::GAMGAgglomeration::agglomerateLduAddressing
|
||||||
AMGInterface::New
|
AMGInterface::New
|
||||||
(
|
(
|
||||||
meshLevels_[fineLevelIndex],
|
meshLevels_[fineLevelIndex],
|
||||||
|
coarseInterfaces,
|
||||||
fineInterfaces[inti],
|
fineInterfaces[inti],
|
||||||
fineInterfaces[inti].interfaceInternalField
|
fineInterfaces[inti].interfaceInternalField
|
||||||
(
|
(
|
||||||
|
|
|
@ -129,12 +129,14 @@ public:
|
||||||
lduInterface,
|
lduInterface,
|
||||||
(
|
(
|
||||||
const lduPrimitiveMesh& lduMesh,
|
const lduPrimitiveMesh& lduMesh,
|
||||||
|
const lduInterfacePtrsList& coarseInterfaces,
|
||||||
const lduInterface& fineInterface,
|
const lduInterface& fineInterface,
|
||||||
const labelField& localRestrictAddressing,
|
const labelField& localRestrictAddressing,
|
||||||
const labelField& neighbourRestrictAddressing
|
const labelField& neighbourRestrictAddressing
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
lduMesh,
|
lduMesh,
|
||||||
|
coarseInterfaces,
|
||||||
fineInterface,
|
fineInterface,
|
||||||
localRestrictAddressing,
|
localRestrictAddressing,
|
||||||
neighbourRestrictAddressing
|
neighbourRestrictAddressing
|
||||||
|
@ -149,6 +151,7 @@ public:
|
||||||
static autoPtr<AMGInterface> New
|
static autoPtr<AMGInterface> New
|
||||||
(
|
(
|
||||||
const lduPrimitiveMesh& lduMesh,
|
const lduPrimitiveMesh& lduMesh,
|
||||||
|
const lduInterfacePtrsList& coarseInterfaces,
|
||||||
const lduInterface& fineInterface,
|
const lduInterface& fineInterface,
|
||||||
const labelField& localRestrictAddressing,
|
const labelField& localRestrictAddressing,
|
||||||
const labelField& neighbourRestrictAddressing
|
const labelField& neighbourRestrictAddressing
|
||||||
|
@ -165,6 +168,11 @@ public:
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
virtual ~AMGInterface()
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
// Access
|
// Access
|
||||||
|
|
|
@ -32,6 +32,7 @@ License
|
||||||
Foam::autoPtr<Foam::AMGInterface> Foam::AMGInterface::New
|
Foam::autoPtr<Foam::AMGInterface> Foam::AMGInterface::New
|
||||||
(
|
(
|
||||||
const lduPrimitiveMesh& lduMesh,
|
const lduPrimitiveMesh& lduMesh,
|
||||||
|
const lduInterfacePtrsList& coarseInterfaces,
|
||||||
const lduInterface& fineInterface,
|
const lduInterface& fineInterface,
|
||||||
const labelField& localRestrictAddressing,
|
const labelField& localRestrictAddressing,
|
||||||
const labelField& neighbourRestrictAddressing
|
const labelField& neighbourRestrictAddressing
|
||||||
|
@ -46,11 +47,14 @@ Foam::autoPtr<Foam::AMGInterface> Foam::AMGInterface::New
|
||||||
{
|
{
|
||||||
FatalErrorIn
|
FatalErrorIn
|
||||||
(
|
(
|
||||||
"AMGInterface::New"
|
"AMGInterface::New\n"
|
||||||
"(const lduPrimitiveMesh& lduMesh,"
|
"(\n"
|
||||||
"const lduInterface& fineInterface,"
|
" const lduPrimitiveMesh& lduMesh,\n"
|
||||||
"const labelField& localRestrictAddressing,"
|
" const lduInterfacePtrsList& coarseInterfaces,\n"
|
||||||
"const labelField& neighbourRestrictAddressing)"
|
" const lduInterface& fineInterface,\n"
|
||||||
|
" const labelField& localRestrictAddressing,\n"
|
||||||
|
" const labelField& neighbourRestrictAddressing\n"
|
||||||
|
")"
|
||||||
) << "Unknown AMGInterface type " << coupleType << ".\n"
|
) << "Unknown AMGInterface type " << coupleType << ".\n"
|
||||||
<< "Valid AMGInterface types are :"
|
<< "Valid AMGInterface types are :"
|
||||||
<< lduInterfaceConstructorTablePtr_->sortedToc()
|
<< lduInterfaceConstructorTablePtr_->sortedToc()
|
||||||
|
@ -62,6 +66,7 @@ Foam::autoPtr<Foam::AMGInterface> Foam::AMGInterface::New
|
||||||
cstrIter()
|
cstrIter()
|
||||||
(
|
(
|
||||||
lduMesh,
|
lduMesh,
|
||||||
|
coarseInterfaces,
|
||||||
fineInterface,
|
fineInterface,
|
||||||
localRestrictAddressing,
|
localRestrictAddressing,
|
||||||
neighbourRestrictAddressing
|
neighbourRestrictAddressing
|
||||||
|
|
|
@ -45,6 +45,7 @@ namespace Foam
|
||||||
Foam::cyclicAMGInterface::cyclicAMGInterface
|
Foam::cyclicAMGInterface::cyclicAMGInterface
|
||||||
(
|
(
|
||||||
const lduPrimitiveMesh& lduMesh,
|
const lduPrimitiveMesh& lduMesh,
|
||||||
|
const lduInterfacePtrsList& coarseInterfaces,
|
||||||
const lduInterface& fineInterface,
|
const lduInterface& fineInterface,
|
||||||
const labelField& localRestrictAddressing,
|
const labelField& localRestrictAddressing,
|
||||||
const labelField& neighbourRestrictAddressing
|
const labelField& neighbourRestrictAddressing
|
||||||
|
|
|
@ -81,6 +81,7 @@ public:
|
||||||
cyclicAMGInterface
|
cyclicAMGInterface
|
||||||
(
|
(
|
||||||
const lduPrimitiveMesh& lduMesh,
|
const lduPrimitiveMesh& lduMesh,
|
||||||
|
const lduInterfacePtrsList& coarseInterfaces,
|
||||||
const lduInterface& fineInterface,
|
const lduInterface& fineInterface,
|
||||||
const labelField& localRestrictAddressing,
|
const labelField& localRestrictAddressing,
|
||||||
const labelField& neighbourRestrictAddressing
|
const labelField& neighbourRestrictAddressing
|
||||||
|
|
|
@ -45,6 +45,7 @@ namespace Foam
|
||||||
Foam::cyclicGGIAMGInterface::cyclicGGIAMGInterface
|
Foam::cyclicGGIAMGInterface::cyclicGGIAMGInterface
|
||||||
(
|
(
|
||||||
const lduPrimitiveMesh& lduMesh,
|
const lduPrimitiveMesh& lduMesh,
|
||||||
|
const lduInterfacePtrsList& coarseInterfaces,
|
||||||
const lduInterface& fineInterface,
|
const lduInterface& fineInterface,
|
||||||
const labelField& localRestrictAddressing,
|
const labelField& localRestrictAddressing,
|
||||||
const labelField& neighbourRestrictAddressing
|
const labelField& neighbourRestrictAddressing
|
||||||
|
@ -53,6 +54,7 @@ Foam::cyclicGGIAMGInterface::cyclicGGIAMGInterface
|
||||||
ggiAMGInterface
|
ggiAMGInterface
|
||||||
(
|
(
|
||||||
lduMesh,
|
lduMesh,
|
||||||
|
coarseInterfaces,
|
||||||
fineInterface,
|
fineInterface,
|
||||||
localRestrictAddressing,
|
localRestrictAddressing,
|
||||||
neighbourRestrictAddressing
|
neighbourRestrictAddressing
|
||||||
|
|
|
@ -67,6 +67,7 @@ public:
|
||||||
cyclicGGIAMGInterface
|
cyclicGGIAMGInterface
|
||||||
(
|
(
|
||||||
const lduPrimitiveMesh& lduMesh,
|
const lduPrimitiveMesh& lduMesh,
|
||||||
|
const lduInterfacePtrsList& coarseInterfaces,
|
||||||
const lduInterface& fineInterface,
|
const lduInterface& fineInterface,
|
||||||
const labelField& localRestrictAddressing,
|
const labelField& localRestrictAddressing,
|
||||||
const labelField& neighbourRestrictAddressing
|
const labelField& neighbourRestrictAddressing
|
||||||
|
|
|
@ -192,6 +192,7 @@ void Foam::ggiAMGInterface::initFastReduce() const
|
||||||
Foam::ggiAMGInterface::ggiAMGInterface
|
Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
(
|
(
|
||||||
const lduPrimitiveMesh& lduMesh,
|
const lduPrimitiveMesh& lduMesh,
|
||||||
|
const lduInterfacePtrsList& coarseInterfaces,
|
||||||
const lduInterface& fineInterface,
|
const lduInterface& fineInterface,
|
||||||
const labelField& localRestrictAddressing,
|
const labelField& localRestrictAddressing,
|
||||||
const labelField& neighbourRestrictAddressing
|
const labelField& neighbourRestrictAddressing
|
||||||
|
@ -201,107 +202,87 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
fineGgiInterface_(refCast<const ggiLduInterface>(fineInterface)),
|
fineGgiInterface_(refCast<const ggiLduInterface>(fineInterface)),
|
||||||
zoneSize_(0),
|
zoneSize_(0),
|
||||||
zoneAddressing_(),
|
zoneAddressing_(),
|
||||||
|
procMasterFaces_(),
|
||||||
mapPtr_(NULL)
|
mapPtr_(NULL)
|
||||||
{
|
{
|
||||||
// Note.
|
// New algorithm will assemble local clusters on the master side and
|
||||||
// Signalling in global clustering requires me to recognise clustering
|
// create zone ordering by collecting all faces (coarse pairs) from proc0,
|
||||||
// from separate processors as separate. In the first phase, this will be
|
|
||||||
// used to recognise cluster from each processor as separate and in the
|
|
||||||
// second phase it will be used to filter local processor faces from
|
|
||||||
// the global patch.
|
|
||||||
// Currently, I am calculating unique cluster index as:
|
|
||||||
//
|
|
||||||
// id = cluster + procOffset*myProcID
|
|
||||||
// With procOffset = 1 million, this should be sufficient for 2000 CPUs
|
|
||||||
// with 2 million coarse cells each. For larger numbers, I need a
|
|
||||||
// larger max int, which can be changed on request
|
|
||||||
// HJ, 1/Apr/2009
|
|
||||||
|
|
||||||
// New algorithm will assemble local clusters and then create a global
|
|
||||||
// zone ordering by collecting all faces (coarse pairs) from proc0,
|
|
||||||
// followed by proc 1 etc. This avoids global communication and allows
|
// followed by proc 1 etc. This avoids global communication and allows
|
||||||
// each processor only to perform the analysis on locally created coarse
|
// each processor only to perform the analysis on locally created coarse
|
||||||
// faces
|
// faces
|
||||||
// HJ, 13/Jun/2016
|
// HJ, 13/Jun/2016
|
||||||
|
|
||||||
// To help with analysis, expand the local and neighbour addressing
|
// Note: local addressing contains only local faces
|
||||||
// to full zone size
|
const labelList& fineZa = fineGgiInterface_.zoneAddressing();
|
||||||
labelField localExpandAddressing(fineGgiInterface_.zoneSize(), 0);
|
|
||||||
|
|
||||||
// Memory management, local
|
|
||||||
{
|
|
||||||
const labelList& addr = fineGgiInterface_.zoneAddressing();
|
|
||||||
|
|
||||||
forAll (addr, i)
|
|
||||||
{
|
|
||||||
localExpandAddressing[addr[i]] =
|
|
||||||
localRestrictAddressing[i] + procOffset*Pstream::myProcNo();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removed global reduce. Only local faces will be analysed.
|
|
||||||
// HJ, 13/Jun/2016
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create addressing for neighbour faces. Note: expandAddrToZone will
|
// Create addressing for neighbour faces. Note: expandAddrToZone will
|
||||||
// expand the addressing to zone size. HJ, 13/Jun/2016
|
// expand the addressing to zone size, including communications.
|
||||||
labelField neighbourExpandAddressing
|
// Faces which are not used locally will be marked by NaNs
|
||||||
(
|
// HJ, 13/Jun/2016
|
||||||
fineGgiInterface_.shadowInterface().interfaceSize()
|
labelField neighbourExpandAddressing = neighbourRestrictAddressing;
|
||||||
);
|
|
||||||
|
|
||||||
// Fill local cluster ID with a combination of a local ID and processor
|
|
||||||
// offset
|
|
||||||
// Memory management, neighbour
|
|
||||||
{
|
|
||||||
forAll (neighbourExpandAddressing, i)
|
|
||||||
{
|
|
||||||
neighbourExpandAddressing[i] =
|
|
||||||
neighbourRestrictAddressing[i]
|
|
||||||
+ procOffset*Pstream::myProcNo();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expand neighbour side to get all the data required from other
|
// Expand neighbour side to get all the data required from other
|
||||||
// processors. Note: neigbour is now the size of remote zone
|
// processors.
|
||||||
|
// Note: neigbour is now the size of remote zone
|
||||||
fineGgiInterface_.shadowInterface().expandAddrToZone
|
fineGgiInterface_.shadowInterface().expandAddrToZone
|
||||||
(
|
(
|
||||||
neighbourExpandAddressing
|
neighbourExpandAddressing
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
// DEBUG: Check that all sizes are at zone size.
|
// Create addressing for neighbour processors. Note: expandAddrToZone will
|
||||||
Info<< "Sizes check: local zone size "
|
// expand the addressing to zone size. HJ, 13/Jun/2016
|
||||||
<< fineGgiInterface_.zoneSize()
|
labelField neighbourExpandProc
|
||||||
<< " " << localExpandAddressing << nl
|
(
|
||||||
<< "shadow zone size "
|
fineGgiInterface_.shadowInterface().interfaceSize(),
|
||||||
<< fineGgiInterface_.shadowInterface().zoneSize()
|
Pstream::myProcNo()
|
||||||
<< " " << neighbourExpandAddressing
|
);
|
||||||
<< endl;
|
|
||||||
|
|
||||||
|
// Expand neighbour side to get all the data required from other
|
||||||
|
// processors.
|
||||||
|
// Note: neigbour is now the size of remote zone
|
||||||
|
fineGgiInterface_.shadowInterface().expandAddrToZone
|
||||||
|
(
|
||||||
|
neighbourExpandProc
|
||||||
|
);
|
||||||
|
|
||||||
// Note: neighbourExpandAddressing will be filled with NaNs for faces which
|
// Note: neighbourExpandAddressing and neighbourExpandProc
|
||||||
// not local
|
// will be filled with NaNs for faces which are not local
|
||||||
|
|
||||||
Info<< "End of reduce" << endl;
|
|
||||||
// Make a lookup table of entries for owner/neighbour.
|
// Make a lookup table of entries for owner/neighbour.
|
||||||
// All sizes are guessed at the size of fine interface
|
// All sizes are guessed at the size of fine interface
|
||||||
// HJ, 19/Feb/2009
|
// HJ, 19/Feb/2009
|
||||||
|
|
||||||
HashTable<SLList<label>, label, Hash<label> > neighboursTable
|
// Note: Guessing size of HashTable to fine interface size
|
||||||
|
|
||||||
|
// Coded neighbour index. Note: using long int to simplify encoding
|
||||||
|
// HJ, 1/Aug/2016
|
||||||
|
HashTable<SLList<long>, long, Hash<long> > neighboursTable
|
||||||
(
|
(
|
||||||
fineGgiInterface_.interfaceSize()
|
Foam::max(128, fineGgiInterface_.interfaceSize()/4)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Table of face-sets to be agglomerated
|
// Neignbour processor index
|
||||||
|
HashTable<SLList<label>, label, Hash<label> > nbrsProcTable
|
||||||
|
(
|
||||||
|
Foam::max(128, fineGgiInterface_.interfaceSize()/4)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Neighbour face-faces addressing for a face with split neighbours
|
||||||
HashTable<SLList<SLList<label> >, label, Hash<label> > faceFaceTable
|
HashTable<SLList<SLList<label> >, label, Hash<label> > faceFaceTable
|
||||||
(
|
(
|
||||||
fineGgiInterface_.interfaceSize()
|
Foam::max(128, fineGgiInterface_.interfaceSize()/4)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Table of face-sets weights to be agglomerated
|
HashTable<SLList<SLList<label> >, label, Hash<label> > faceFaceNbrTable
|
||||||
|
(
|
||||||
|
Foam::max(128, fineGgiInterface_.interfaceSize()/4)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Neighbour face-faces weights for a face with split neighbours
|
||||||
HashTable<SLList<SLList<scalar> >, label, Hash<label> >
|
HashTable<SLList<SLList<scalar> >, label, Hash<label> >
|
||||||
faceFaceWeightsTable
|
faceFaceWeightsTable
|
||||||
(
|
(
|
||||||
fineGgiInterface_.interfaceSize()
|
Foam::max(128, fineGgiInterface_.interfaceSize()/4)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Count the number of coarse faces
|
// Count the number of coarse faces
|
||||||
|
@ -318,12 +299,6 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
const labelListList& fineAddr = fineGgiInterface_.addressing();
|
const labelListList& fineAddr = fineGgiInterface_.addressing();
|
||||||
const scalarListList& fineWeights = fineGgiInterface_.weights();
|
const scalarListList& fineWeights = fineGgiInterface_.weights();
|
||||||
|
|
||||||
// Note: cluster only locally live faces
|
|
||||||
// HJ, 13/Jun/2016
|
|
||||||
|
|
||||||
// This addressing defines which faces from zone are local
|
|
||||||
const labelList& fineZa = fineGgiInterface_.zoneAddressing();
|
|
||||||
|
|
||||||
// Perform analysis only for local faces
|
// Perform analysis only for local faces
|
||||||
// HJ, 22/Jun/2016
|
// HJ, 22/Jun/2016
|
||||||
forAll (fineZa, fineZaI)
|
forAll (fineZa, fineZaI)
|
||||||
|
@ -336,8 +311,27 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
|
|
||||||
forAll (curFineNbrs, nbrI)
|
forAll (curFineNbrs, nbrI)
|
||||||
{
|
{
|
||||||
label curMaster = -1;
|
long curMaster = -1;
|
||||||
label curSlave = -1;
|
label curMasterProc = -1;
|
||||||
|
long curSlave = -1;
|
||||||
|
label curSlaveProc = -1;
|
||||||
|
|
||||||
|
// Note. Signalling in global clustering requires
|
||||||
|
// me to recognise clustering from separate
|
||||||
|
// processors as separate. In the first phase,
|
||||||
|
// this will be used to recognise cluster from
|
||||||
|
// each processor as separate and in the second
|
||||||
|
// phase it will be used to filter local processor
|
||||||
|
// faces from the global patch. Currently, I am
|
||||||
|
// calculating unique cluster index as:
|
||||||
|
//
|
||||||
|
// id = cluster + procOffset*myProcID
|
||||||
|
//
|
||||||
|
// With procOffset = 1 million, this should be
|
||||||
|
// sufficient for 2000 CPUs with 2 million coarse
|
||||||
|
// cells each. For larger numbers, I need a
|
||||||
|
// larger max int, which can be changed on request
|
||||||
|
// HJ, 1/Apr/2009
|
||||||
|
|
||||||
// My label = ffI
|
// My label = ffI
|
||||||
// Nbr label = nnI
|
// Nbr label = nnI
|
||||||
|
@ -347,39 +341,62 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
if (fineGgiInterface_.master())
|
if (fineGgiInterface_.master())
|
||||||
{
|
{
|
||||||
// Master side
|
// Master side
|
||||||
curMaster = localExpandAddressing[ffI];
|
curMaster = localRestrictAddressing[fineZaI];
|
||||||
|
curMasterProc = Pstream::myProcNo();
|
||||||
curSlave = neighbourExpandAddressing[nnI];
|
curSlave = neighbourExpandAddressing[nnI];
|
||||||
|
curSlaveProc = neighbourExpandProc[nnI];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Slave side
|
|
||||||
curMaster = neighbourExpandAddressing[nnI];
|
curMaster = neighbourExpandAddressing[nnI];
|
||||||
curSlave = localExpandAddressing[ffI];
|
curMasterProc = neighbourExpandProc[nnI];
|
||||||
|
curSlave = localRestrictAddressing[fineZaI];
|
||||||
|
curSlaveProc = Pstream::myProcNo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Code in current master and slave
|
||||||
|
curMaster += procOffset*curMasterProc;
|
||||||
|
curSlave += procOffset*curSlaveProc;
|
||||||
|
|
||||||
// Look for the master cell. If it has already got a face,
|
// Look for the master cell. If it has already got a face,
|
||||||
// add the coefficient to the face. If not, create a new
|
// add the coefficient to the face. If not, create a new
|
||||||
// face.
|
// face
|
||||||
if (neighboursTable.found(curMaster))
|
if (neighboursTable.found(curMaster))
|
||||||
{
|
{
|
||||||
|
// This master side face already exists
|
||||||
|
|
||||||
// Check all current neighbours to see if the current
|
// Check all current neighbours to see if the current
|
||||||
// slave already exists. If so, add the coefficient.
|
// slave already exists. If so, add the coefficient.
|
||||||
|
|
||||||
SLList<label>& curNbrs = neighboursTable.find(curMaster)();
|
SLList<long>& curNbrs =
|
||||||
|
neighboursTable.find(curMaster)();
|
||||||
|
|
||||||
|
SLList<label>& curNbrsProc =
|
||||||
|
nbrsProcTable.find(curMaster)();
|
||||||
|
|
||||||
SLList<SLList<label> >& curFaceFaces =
|
SLList<SLList<label> >& curFaceFaces =
|
||||||
faceFaceTable.find(curMaster)();
|
faceFaceTable.find(curMaster)();
|
||||||
|
|
||||||
|
SLList<SLList<label> >& curFaceFaceNbrs =
|
||||||
|
faceFaceNbrTable.find(curMaster)();
|
||||||
|
|
||||||
SLList<SLList<scalar> >& curFaceWeights =
|
SLList<SLList<scalar> >& curFaceWeights =
|
||||||
faceFaceWeightsTable.find(curMaster)();
|
faceFaceWeightsTable.find(curMaster)();
|
||||||
|
|
||||||
|
// Search for coded neighbour
|
||||||
bool nbrFound = false;
|
bool nbrFound = false;
|
||||||
|
|
||||||
SLList<label>::iterator nbrsIter = curNbrs.begin();
|
SLList<long>::iterator nbrsIter = curNbrs.begin();
|
||||||
|
|
||||||
|
SLList<label>::iterator nbrsProcIter =
|
||||||
|
curNbrsProc.begin();
|
||||||
|
|
||||||
SLList<SLList<label> >::iterator faceFacesIter =
|
SLList<SLList<label> >::iterator faceFacesIter =
|
||||||
curFaceFaces.begin();
|
curFaceFaces.begin();
|
||||||
|
|
||||||
|
SLList<SLList<label> >::iterator faceFaceNbrsIter =
|
||||||
|
curFaceFaceNbrs.begin();
|
||||||
|
|
||||||
SLList<SLList<scalar> >::iterator faceFaceWeightsIter =
|
SLList<SLList<scalar> >::iterator faceFaceWeightsIter =
|
||||||
curFaceWeights.begin();
|
curFaceWeights.begin();
|
||||||
|
|
||||||
|
@ -387,9 +404,13 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
(
|
(
|
||||||
;
|
;
|
||||||
nbrsIter != curNbrs.end()
|
nbrsIter != curNbrs.end()
|
||||||
|
&& nbrsProcIter != curNbrsProc.end()
|
||||||
&& faceFacesIter != curFaceFaces.end()
|
&& faceFacesIter != curFaceFaces.end()
|
||||||
|
&& faceFaceNbrsIter != curFaceFaceNbrs.end()
|
||||||
&& faceFaceWeightsIter != curFaceWeights.end();
|
&& faceFaceWeightsIter != curFaceWeights.end();
|
||||||
++nbrsIter, ++faceFacesIter, ++faceFaceWeightsIter
|
++nbrsIter, ++nbrsProcIter,
|
||||||
|
++faceFacesIter, ++faceFaceNbrsIter,
|
||||||
|
++faceFaceWeightsIter
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Check neighbour slave
|
// Check neighbour slave
|
||||||
|
@ -397,6 +418,7 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
{
|
{
|
||||||
nbrFound = true;
|
nbrFound = true;
|
||||||
faceFacesIter().append(ffI);
|
faceFacesIter().append(ffI);
|
||||||
|
faceFaceNbrsIter().append(nbrI);
|
||||||
faceFaceWeightsIter().append(curNW);
|
faceFaceWeightsIter().append(curNW);
|
||||||
|
|
||||||
// New agglomeration pair found in already
|
// New agglomeration pair found in already
|
||||||
|
@ -410,7 +432,9 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
if (!nbrFound)
|
if (!nbrFound)
|
||||||
{
|
{
|
||||||
curNbrs.append(curSlave);
|
curNbrs.append(curSlave);
|
||||||
|
curNbrsProc.append(curSlaveProc);
|
||||||
curFaceFaces.append(SLList<label>(ffI));
|
curFaceFaces.append(SLList<label>(ffI));
|
||||||
|
curFaceFaceNbrs.append(SLList<label>(nbrI));
|
||||||
curFaceWeights.append(SLList<scalar>(curNW));
|
curFaceWeights.append(SLList<scalar>(curNW));
|
||||||
|
|
||||||
// New coarse face created for an existing master
|
// New coarse face created for an existing master
|
||||||
|
@ -420,9 +444,20 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// This master has got no neighbours yet. Add a neighbour
|
// This master has got no neighbours yet.
|
||||||
// and a coefficient, thus creating a new face
|
// Add a neighbour, proc and a coefficient as a
|
||||||
neighboursTable.insert(curMaster, SLList<label>(curSlave));
|
// new list, thus creating a new face
|
||||||
|
neighboursTable.insert
|
||||||
|
(
|
||||||
|
curMaster,
|
||||||
|
SLList<long>(curSlave)
|
||||||
|
);
|
||||||
|
|
||||||
|
nbrsProcTable.insert
|
||||||
|
(
|
||||||
|
curMaster,
|
||||||
|
SLList<label>(curSlaveProc)
|
||||||
|
);
|
||||||
|
|
||||||
faceFaceTable.insert
|
faceFaceTable.insert
|
||||||
(
|
(
|
||||||
|
@ -430,6 +465,12 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
SLList<SLList<label> >(SLList<label>(ffI))
|
SLList<SLList<label> >(SLList<label>(ffI))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
faceFaceNbrTable.insert
|
||||||
|
(
|
||||||
|
curMaster,
|
||||||
|
SLList<SLList<label> >(SLList<label>(nbrI))
|
||||||
|
);
|
||||||
|
|
||||||
faceFaceWeightsTable.insert
|
faceFaceWeightsTable.insert
|
||||||
(
|
(
|
||||||
curMaster,
|
curMaster,
|
||||||
|
@ -446,8 +487,7 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Coarse level, addressing is stored in faceCells
|
// Coarse level, addressing is stored in faceCells
|
||||||
// This addressing defines whicf faces from zone are local
|
// This addressing defines which faces from zone are local
|
||||||
const labelList& fineZa = fineGgiInterface_.zoneAddressing();
|
|
||||||
|
|
||||||
// Perform analysis only for local faces
|
// Perform analysis only for local faces
|
||||||
// HJ, 22/Jun/2016
|
// HJ, 22/Jun/2016
|
||||||
|
@ -456,48 +496,85 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
// Get the local face (from zone) to analyse
|
// Get the local face (from zone) to analyse
|
||||||
const label ffI = fineZa[fineZaI];
|
const label ffI = fineZa[fineZaI];
|
||||||
|
|
||||||
label curMaster = -1;
|
long curMaster = -1;
|
||||||
label curSlave = -1;
|
label curMasterProc = -1;
|
||||||
|
long curSlave = -1;
|
||||||
|
label curSlaveProc = -1;
|
||||||
|
|
||||||
// Do switching on master/slave indices based on the
|
// Note. Signalling in global clustering requires
|
||||||
// owner/neighbour of the processor index such that
|
// me to recognise clustering from separate
|
||||||
// both sides get the same answer.
|
// processors as separate. In the first phase,
|
||||||
if (master())
|
// this will be used to recognise cluster from
|
||||||
|
// each processor as separate and in the second
|
||||||
|
// phase it will be used to filter local processor
|
||||||
|
// faces from the global patch. Currently, I am
|
||||||
|
// calculating unique cluster index as:
|
||||||
|
//
|
||||||
|
// id = cluster + procOffset*myProcID
|
||||||
|
//
|
||||||
|
// With procOffset = 1 million, this should be
|
||||||
|
// sufficient for 2000 CPUs with 2 million coarse
|
||||||
|
// cells each. For larger numbers, I need a
|
||||||
|
// larger max int, which can be changed on request
|
||||||
|
// HJ, 1/Apr/2009
|
||||||
|
|
||||||
|
if (fineGgiInterface_.master())
|
||||||
{
|
{
|
||||||
// Master side
|
// Master side
|
||||||
curMaster = localExpandAddressing[ffI];
|
curMaster = localRestrictAddressing[fineZaI];
|
||||||
|
curMasterProc = Pstream::myProcNo();
|
||||||
curSlave = neighbourExpandAddressing[ffI];
|
curSlave = neighbourExpandAddressing[ffI];
|
||||||
|
curSlaveProc = neighbourExpandProc[ffI];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Slave side
|
|
||||||
curMaster = neighbourExpandAddressing[ffI];
|
curMaster = neighbourExpandAddressing[ffI];
|
||||||
curSlave = localExpandAddressing[ffI];
|
curMasterProc = neighbourExpandProc[ffI];
|
||||||
|
curSlave = localRestrictAddressing[fineZaI];
|
||||||
|
curSlaveProc = Pstream::myProcNo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Code in current master and slave
|
||||||
|
curMaster += procOffset*curMasterProc;
|
||||||
|
curSlave += procOffset*curSlaveProc;
|
||||||
|
|
||||||
// Look for the master cell. If it has already got a face,
|
// Look for the master cell. If it has already got a face,
|
||||||
// add the coefficient to the face. If not, create a new face.
|
// add the coefficient to the face. If not, create a new face.
|
||||||
if (neighboursTable.found(curMaster))
|
if (neighboursTable.found(curMaster))
|
||||||
{
|
{
|
||||||
|
// This master side face already exists
|
||||||
|
|
||||||
// Check all current neighbours to see if the current slave
|
// Check all current neighbours to see if the current slave
|
||||||
// already exists and if so, add the fine face
|
// already exists and if so, add the fine face
|
||||||
// to the agglomeration.
|
// to the agglomeration.
|
||||||
|
|
||||||
SLList<label>& curNbrs = neighboursTable.find(curMaster)();
|
SLList<long>& curNbrs = neighboursTable.find(curMaster)();
|
||||||
|
|
||||||
|
SLList<label>& curNbrsProc =
|
||||||
|
nbrsProcTable.find(curMaster)();
|
||||||
|
|
||||||
SLList<SLList<label> >& curFaceFaces =
|
SLList<SLList<label> >& curFaceFaces =
|
||||||
faceFaceTable.find(curMaster)();
|
faceFaceTable.find(curMaster)();
|
||||||
|
|
||||||
|
SLList<SLList<label> >& curFaceFaceNbrs =
|
||||||
|
faceFaceNbrTable.find(curMaster)();
|
||||||
|
|
||||||
SLList<SLList<scalar> >& curFaceWeights =
|
SLList<SLList<scalar> >& curFaceWeights =
|
||||||
faceFaceWeightsTable.find(curMaster)();
|
faceFaceWeightsTable.find(curMaster)();
|
||||||
|
|
||||||
bool nbrFound = false;
|
bool nbrFound = false;
|
||||||
|
|
||||||
SLList<label>::iterator nbrsIter = curNbrs.begin();
|
SLList<long>::iterator nbrsIter = curNbrs.begin();
|
||||||
|
|
||||||
|
SLList<label>::iterator nbrsProcIter =
|
||||||
|
curNbrsProc.begin();
|
||||||
|
|
||||||
SLList<SLList<label> >::iterator faceFacesIter =
|
SLList<SLList<label> >::iterator faceFacesIter =
|
||||||
curFaceFaces.begin();
|
curFaceFaces.begin();
|
||||||
|
|
||||||
|
SLList<SLList<label> >::iterator faceFaceNbrsIter =
|
||||||
|
curFaceFaceNbrs.begin();
|
||||||
|
|
||||||
SLList<SLList<scalar> >::iterator faceFaceWeightsIter =
|
SLList<SLList<scalar> >::iterator faceFaceWeightsIter =
|
||||||
curFaceWeights.begin();
|
curFaceWeights.begin();
|
||||||
|
|
||||||
|
@ -506,8 +583,10 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
;
|
;
|
||||||
nbrsIter != curNbrs.end()
|
nbrsIter != curNbrs.end()
|
||||||
&& faceFacesIter != curFaceFaces.end()
|
&& faceFacesIter != curFaceFaces.end()
|
||||||
|
&& faceFaceNbrsIter != curFaceFaceNbrs.end()
|
||||||
&& faceFaceWeightsIter != curFaceWeights.end();
|
&& faceFaceWeightsIter != curFaceWeights.end();
|
||||||
++nbrsIter, ++faceFacesIter, ++faceFaceWeightsIter
|
++nbrsIter, ++nbrsProcIter,
|
||||||
|
++faceFacesIter, ++faceFaceNbrsIter, ++faceFaceWeightsIter
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Check neighbour slave
|
// Check neighbour slave
|
||||||
|
@ -515,12 +594,15 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
{
|
{
|
||||||
nbrFound = true;
|
nbrFound = true;
|
||||||
faceFacesIter().append(ffI);
|
faceFacesIter().append(ffI);
|
||||||
|
// Add dummy nbr
|
||||||
|
faceFaceNbrsIter().append(0);
|
||||||
// Add dummy weight
|
// Add dummy weight
|
||||||
faceFaceWeightsIter().append(1.0);
|
faceFaceWeightsIter().append(1.0);
|
||||||
|
|
||||||
// New agglomeration pair found in already
|
// New agglomeration pair found in already
|
||||||
// existing pair
|
// existing pair
|
||||||
nAgglomPairs++;
|
nAgglomPairs++;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -528,7 +610,10 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
if (!nbrFound)
|
if (!nbrFound)
|
||||||
{
|
{
|
||||||
curNbrs.append(curSlave);
|
curNbrs.append(curSlave);
|
||||||
|
curNbrsProc.append(curSlaveProc);
|
||||||
curFaceFaces.append(SLList<label>(ffI));
|
curFaceFaces.append(SLList<label>(ffI));
|
||||||
|
// Add dummy nbr
|
||||||
|
curFaceFaceNbrs.append(SLList<label>(0));
|
||||||
// Add dummy weight
|
// Add dummy weight
|
||||||
curFaceWeights.append(SLList<scalar>(1.0));
|
curFaceWeights.append(SLList<scalar>(1.0));
|
||||||
|
|
||||||
|
@ -541,7 +626,17 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
{
|
{
|
||||||
// This master has got no neighbours yet. Add a neighbour
|
// This master has got no neighbours yet. Add a neighbour
|
||||||
// and a coefficient, thus creating a new face
|
// and a coefficient, thus creating a new face
|
||||||
neighboursTable.insert(curMaster, SLList<label>(curSlave));
|
neighboursTable.insert
|
||||||
|
(
|
||||||
|
curMaster,
|
||||||
|
SLList<long>(curSlave)
|
||||||
|
);
|
||||||
|
|
||||||
|
nbrsProcTable.insert
|
||||||
|
(
|
||||||
|
curMaster,
|
||||||
|
SLList<label>(curSlaveProc)
|
||||||
|
);
|
||||||
|
|
||||||
faceFaceTable.insert
|
faceFaceTable.insert
|
||||||
(
|
(
|
||||||
|
@ -549,6 +644,13 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
SLList<SLList<label> >(SLList<label>(ffI))
|
SLList<SLList<label> >(SLList<label>(ffI))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Add dummy nbr
|
||||||
|
faceFaceNbrTable.insert
|
||||||
|
(
|
||||||
|
curMaster,
|
||||||
|
SLList<SLList<label> >(SLList<label>(0))
|
||||||
|
);
|
||||||
|
|
||||||
// Add dummy weight
|
// Add dummy weight
|
||||||
faceFaceWeightsTable.insert
|
faceFaceWeightsTable.insert
|
||||||
(
|
(
|
||||||
|
@ -561,29 +663,29 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
nAgglomPairs++;
|
nAgglomPairs++;
|
||||||
}
|
}
|
||||||
} // end for all fine faces
|
} // end for all fine faces
|
||||||
}
|
} // end of else in fine level (coarse level)
|
||||||
|
|
||||||
|
// Since only local faces are analysed, lists can now be resized
|
||||||
|
faceCells_.setSize(nCoarseFaces, -1);
|
||||||
|
fineAddressing_.setSize(nAgglomPairs, -1);
|
||||||
|
restrictAddressing_.setSize(nAgglomPairs, -1);
|
||||||
|
restrictWeights_.setSize(nAgglomPairs);
|
||||||
|
|
||||||
// In order to assemble the coarse global face zone, find out
|
// In order to assemble the coarse global face zone, find out
|
||||||
// how many faces have been created on each processor.
|
// how many faces have been created on each processor.
|
||||||
// Note that masters and slaves both count faces so we will only ask master
|
// Note that masters and slaves both count faces so we will
|
||||||
// sizes to count
|
// only ask master sizes to count
|
||||||
labelList nCoarseFacesPerProc(Pstream::nProcs(), 0);
|
labelList nCoarseFacesPerProc(Pstream::nProcs(), 0);
|
||||||
|
|
||||||
if (master())
|
|
||||||
{
|
|
||||||
nCoarseFacesPerProc[Pstream::myProcNo()] = nCoarseFaces;
|
nCoarseFacesPerProc[Pstream::myProcNo()] = nCoarseFaces;
|
||||||
}
|
|
||||||
|
|
||||||
reduce(nCoarseFacesPerProc, sumOp<labelList>());
|
reduce(nCoarseFacesPerProc, sumOp<labelList>());
|
||||||
|
|
||||||
Info<< "Number of faces per processor: " << nCoarseFacesPerProc
|
|
||||||
<< endl;
|
|
||||||
|
|
||||||
// Coarse global face zone is assembled by adding all faces from proc0,
|
// Coarse global face zone is assembled by adding all faces from proc0,
|
||||||
// followed by all faces from proc1 etc.
|
// followed by all faces from proc1 etc.
|
||||||
// Therefore, on procN, my master offset
|
// Therefore, on procN, my master offset
|
||||||
// will be equal to the sum of numbers of coarse faces on all processors
|
// will be equal to the sum of numbers of coarse faces on all
|
||||||
// before mine
|
// processors before mine
|
||||||
// HJ, 13/Jun/2016
|
// HJ, 13/Jun/2016
|
||||||
|
|
||||||
label coarseGlobalFaceOffset = 0;
|
label coarseGlobalFaceOffset = 0;
|
||||||
|
@ -593,38 +695,42 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
coarseGlobalFaceOffset += nCoarseFacesPerProc[i];
|
coarseGlobalFaceOffset += nCoarseFacesPerProc[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
Pout<< "coarseGlobalFaceOffset: " << coarseGlobalFaceOffset << endl;
|
// Grab zone size and create zone addressing
|
||||||
|
zoneSize_ = sum(nCoarseFacesPerProc);
|
||||||
|
|
||||||
Info<< "End of contents assembly" << endl;
|
zoneAddressing_.setSize(nCoarseFaces);
|
||||||
labelField masterFaceCells(nCoarseFaces, -1);
|
|
||||||
labelField masterZoneAddressing(nCoarseFaces, -1);
|
|
||||||
labelField masterFineAddressing(nCoarseFaces, -1);
|
|
||||||
labelField masterRestrictAddressing(nAgglomPairs, -1);
|
|
||||||
scalarField masterRestrictWeights(nAgglomPairs);
|
|
||||||
|
|
||||||
// Note: in multiple agglomeration
|
// Both master and slave have done agglomeration, but only master
|
||||||
|
// will construct the global faces index.
|
||||||
labelList contents = neighboursTable.toc();
|
// To avoid searching, master will prepare a list of global face
|
||||||
|
// indices that appear on each processor in order and communicate them
|
||||||
|
// to the slave
|
||||||
|
// The slave will then know which is the next global face from which
|
||||||
|
// processor and pick them out in the same order
|
||||||
|
|
||||||
// Global faces shall be assembled by the increasing label of master
|
// Global faces shall be assembled by the increasing label of master
|
||||||
// cluster ID.
|
// cluster ID.
|
||||||
|
List<long> contents = neighboursTable.toc();
|
||||||
|
|
||||||
// Sort makes sure the order is identical on both sides.
|
// Sort makes sure the order is identical on both sides.
|
||||||
// HJ, 20/Feb/2009 and 6/Jun/2016
|
// HJ, 20/Feb/2009 and 6/Jun/2016
|
||||||
sort(contents);
|
sort(contents);
|
||||||
|
|
||||||
// Grab zone size and create zone addressing
|
// Note: Restriction is done on master side only because this is where
|
||||||
zoneSize_ = sum(nCoarseFacesPerProc);
|
// the local zone is created. HJ, 1/Aug/2016
|
||||||
Info<< "zoneSize_: " << zoneSize_ << endl;
|
if (master())
|
||||||
|
{
|
||||||
// Note:
|
// Note:
|
||||||
// When I am agglomerating the master, I know faces are stacked up in order
|
// When I am agglomerating the master, faces are stacked up in order
|
||||||
// but on the slave side, all I know is the master cluster index and
|
// but on the slave side, all I know is the master cluster index and
|
||||||
// not a master coarse face index. Therefore:
|
// not a master coarse face index. Therefore:
|
||||||
// - master needs to be agglomerated first
|
// - master needs to be agglomerated first
|
||||||
// - once master is agglomerated, I need to signal to the slave side
|
// - once master is agglomerated, I need to signal to the slave side
|
||||||
// the global coarse face zone index
|
// the global coarse face zone index
|
||||||
|
|
||||||
|
// For each new global face created on master proc,
|
||||||
|
// record its index under the slave proc array
|
||||||
|
List<SLList<label> > procMasterFacesLL(Pstream::nProcs());
|
||||||
|
|
||||||
// Note: zone addressing will be assembled only for local clusters
|
// Note: zone addressing will be assembled only for local clusters
|
||||||
// using the coarseGlobalFaceOffset
|
// using the coarseGlobalFaceOffset
|
||||||
|
@ -636,20 +742,19 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
nAgglomPairs = 0;
|
nAgglomPairs = 0;
|
||||||
|
|
||||||
// Note:
|
// Note:
|
||||||
// Since clustering has now happened only on local faces, addressing and
|
// Since clustering has now happened only on local faces,
|
||||||
// all other array work on local indices and not on the coarse global zone
|
// addressing and all other array work on local indices and
|
||||||
|
// not on the coarse global zone
|
||||||
// HJ, 13/Jun/2016
|
// HJ, 13/Jun/2016
|
||||||
|
|
||||||
// Establish zone addressing on the master side and communicate
|
|
||||||
// it to the shadow
|
|
||||||
|
|
||||||
// On master side, the owner addressing is stored in table of contents
|
// On master side, the owner addressing is stored in table of contents
|
||||||
forAll (contents, masterI)
|
forAll (contents, masterI)
|
||||||
{
|
{
|
||||||
SLList<label>& curNbrs =
|
SLList<long>& curNbrs =
|
||||||
neighboursTable.find(contents[masterI])();
|
neighboursTable.find(contents[masterI])();
|
||||||
|
|
||||||
// Note: neighbour processor index is irrelevant. HJ, 1/Apr/2009
|
SLList<label>& curNbrsProc =
|
||||||
|
nbrsProcTable.find(contents[masterI])();
|
||||||
|
|
||||||
SLList<SLList<label> >& curFaceFaces =
|
SLList<SLList<label> >& curFaceFaces =
|
||||||
faceFaceTable.find(contents[masterI])();
|
faceFaceTable.find(contents[masterI])();
|
||||||
|
@ -657,7 +762,11 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
SLList<SLList<scalar> >& curFaceWeights =
|
SLList<SLList<scalar> >& curFaceWeights =
|
||||||
faceFaceWeightsTable.find(contents[masterI])();
|
faceFaceWeightsTable.find(contents[masterI])();
|
||||||
|
|
||||||
SLList<label>::iterator nbrsIter = curNbrs.begin();
|
SLList<long>::iterator nbrsIter = curNbrs.begin();
|
||||||
|
|
||||||
|
SLList<label>::iterator nbrsProcIter =
|
||||||
|
curNbrsProc.begin();
|
||||||
|
|
||||||
SLList<SLList<label> >::iterator faceFacesIter =
|
SLList<SLList<label> >::iterator faceFacesIter =
|
||||||
curFaceFaces.begin();
|
curFaceFaces.begin();
|
||||||
|
|
||||||
|
@ -668,28 +777,39 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
(
|
(
|
||||||
;
|
;
|
||||||
nbrsIter != curNbrs.end()
|
nbrsIter != curNbrs.end()
|
||||||
|
&& nbrsProcIter != curNbrsProc.end()
|
||||||
&& faceFacesIter != curFaceFaces.end()
|
&& faceFacesIter != curFaceFaces.end()
|
||||||
&& faceFaceWeightsIter != curFaceWeights.end();
|
&& faceFaceWeightsIter != curFaceWeights.end();
|
||||||
++nbrsIter, ++faceFacesIter, ++faceFaceWeightsIter
|
++nbrsIter, ++nbrsProcIter,
|
||||||
|
++faceFacesIter, ++faceFaceWeightsIter
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Check if master is on local processor: no longer needed,
|
// Check if master is on local processor: no longer needed,
|
||||||
// as only local processor is being searched. HJ, 13/Jun/2016
|
// as only local processor is being searched. HJ, 13/Jun/2016
|
||||||
|
|
||||||
// Record that this face belongs locally
|
// Get faces and weights
|
||||||
// Use offset to indicate its position in the list
|
|
||||||
masterZoneAddressing[nProcFaces] =
|
|
||||||
nProcFaces + coarseGlobalFaceOffset;
|
|
||||||
|
|
||||||
masterFaceCells[nProcFaces] =
|
|
||||||
contents[masterI] - procOffset*Pstream::myProcNo();
|
|
||||||
|
|
||||||
SLList<label>::iterator facesIter =
|
SLList<label>::iterator facesIter =
|
||||||
faceFacesIter().begin();
|
faceFacesIter().begin();
|
||||||
|
|
||||||
SLList<scalar>::iterator weightsIter =
|
SLList<scalar>::iterator weightsIter =
|
||||||
faceFaceWeightsIter().begin();
|
faceFaceWeightsIter().begin();
|
||||||
|
|
||||||
|
// Record that this face belongs locally
|
||||||
|
// Use offset to indicate its position in the list
|
||||||
|
zoneAddressing_[nProcFaces] =
|
||||||
|
nProcFaces + coarseGlobalFaceOffset;
|
||||||
|
|
||||||
|
// Record master cluster index
|
||||||
|
faceCells_[nProcFaces] =
|
||||||
|
contents[masterI] - procOffset*Pstream::myProcNo();
|
||||||
|
|
||||||
|
// Record global processor face
|
||||||
|
procMasterFacesLL[nbrsProcIter()].append
|
||||||
|
(
|
||||||
|
nProcFaces + coarseGlobalFaceOffset
|
||||||
|
);
|
||||||
|
|
||||||
|
// Collect agglomeration data
|
||||||
for
|
for
|
||||||
(
|
(
|
||||||
;
|
;
|
||||||
|
@ -698,12 +818,14 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
++facesIter, ++weightsIter
|
++facesIter, ++weightsIter
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
masterFineAddressing[nAgglomPairs] = facesIter();
|
fineAddressing_[nAgglomPairs] = facesIter();
|
||||||
|
|
||||||
// Master processor zone face is calculated from
|
// Master processor zone face is calculated from
|
||||||
masterRestrictAddressing[nAgglomPairs] =
|
// global offset
|
||||||
|
restrictAddressing_[nAgglomPairs] =
|
||||||
nProcFaces + coarseGlobalFaceOffset;
|
nProcFaces + coarseGlobalFaceOffset;
|
||||||
masterRestrictWeights[nAgglomPairs] = weightsIter();
|
|
||||||
|
restrictWeights_[nAgglomPairs] = weightsIter();
|
||||||
nAgglomPairs++;
|
nAgglomPairs++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -711,56 +833,85 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resize arrays: not all of ggi is used locally
|
// No need to resize arrays only local faces are used
|
||||||
masterFaceCells.setSize(nProcFaces);
|
// HJ, 1/Aug/2016
|
||||||
masterZoneAddressing.setSize(nProcFaces);
|
|
||||||
|
|
||||||
masterFineAddressing.setSize(nAgglomPairs);
|
// Re-pack singly linked list of processor master faces
|
||||||
masterRestrictAddressing.setSize(nAgglomPairs);
|
// and pass to other processors
|
||||||
masterRestrictWeights.setSize(nAgglomPairs);
|
|
||||||
|
|
||||||
// Note: Both master and slave have done the same agglomeration up to here
|
// First index: master proc
|
||||||
|
// Second index: slave proc
|
||||||
|
// List contents: global faces in order
|
||||||
|
labelListListList crissCrossList(Pstream::nProcs());
|
||||||
|
|
||||||
if (master())
|
labelListList& crissList = crissCrossList[Pstream::myProcNo()];
|
||||||
|
|
||||||
|
crissList.setSize(Pstream::nProcs());
|
||||||
|
|
||||||
|
forAll (crissList, procI)
|
||||||
{
|
{
|
||||||
// Master has completed the clustering
|
crissList[procI] = procMasterFacesLL[procI];
|
||||||
faceCells_ = masterFaceCells;
|
|
||||||
zoneAddressing_ = masterZoneAddressing;
|
|
||||||
fineAddressing_ = masterFineAddressing;
|
|
||||||
restrictAddressing_ = masterRestrictAddressing;
|
|
||||||
restrictWeights_ = masterRestrictWeights;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Pstream::gatherList(crissCrossList);
|
||||||
|
Pstream::scatterList(crissCrossList);
|
||||||
|
|
||||||
|
procMasterFaces_.setSize(Pstream::nProcs());
|
||||||
|
|
||||||
|
forAll (procMasterFaces_, procI)
|
||||||
|
{
|
||||||
|
procMasterFaces_[procI] =
|
||||||
|
crissCrossList[procI][Pstream::myProcNo()];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Agglomerate slave
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Note: shadowRestrictAddressing contains the
|
|
||||||
|
|
||||||
// Note: zone addressing will be assembled only for local clusters
|
// Note: zone addressing will be assembled only for local clusters
|
||||||
// using the coarseGlobalFaceOffset
|
// using the coarseGlobalFaceOffset
|
||||||
// HJ, 13/Jun/2016
|
// HJ, 13/Jun/2016
|
||||||
label nProcFaces = 0;
|
label nProcFaces = 0;
|
||||||
|
|
||||||
|
// Get master side procMasterFaces
|
||||||
|
// Note: this needs to be picked up from coarse interfaces rather than
|
||||||
|
// the matrix, as the coarse matrix assembly is not complete yet.
|
||||||
|
// Further, master has got a lower index in the list, meaning that
|
||||||
|
// it has already completed the assembly
|
||||||
|
const ggiAMGInterface& shadowGGI =
|
||||||
|
refCast<const ggiAMGInterface>(coarseInterfaces[shadowIndex()]);
|
||||||
|
|
||||||
|
const labelListList& masterProcMasterFaces =
|
||||||
|
shadowGGI.procMasterFaces();
|
||||||
|
|
||||||
// Reset face counter for re-use
|
// Reset face counter for re-use
|
||||||
nCoarseFaces = 0;
|
nCoarseFaces = 0;
|
||||||
nAgglomPairs = 0;
|
nAgglomPairs = 0;
|
||||||
|
|
||||||
|
// Count how many global faces are used for each proc on the other side
|
||||||
|
labelList npmf(Pstream::nProcs(), 0);
|
||||||
|
|
||||||
// On slave side, the owner addressing is stored in linked lists
|
// On slave side, the owner addressing is stored in linked lists
|
||||||
forAll (contents, masterI)
|
forAll (contents, masterI)
|
||||||
{
|
{
|
||||||
// Note: master processor index is irrelevant. HJ, 1/Apr/2009
|
SLList<long>& curNbrs = neighboursTable.find(contents[masterI])();
|
||||||
|
|
||||||
SLList<label>& curNbrs = neighboursTable.find(contents[masterI])();
|
|
||||||
|
|
||||||
SLList<SLList<label> >& curFaceFaces =
|
SLList<SLList<label> >& curFaceFaces =
|
||||||
faceFaceTable.find(contents[masterI])();
|
faceFaceTable.find(contents[masterI])();
|
||||||
|
|
||||||
|
SLList<SLList<label> >& curFaceFaceNbrs =
|
||||||
|
faceFaceNbrTable.find(contents[masterI])();
|
||||||
|
|
||||||
SLList<SLList<scalar> >& curFaceWeights =
|
SLList<SLList<scalar> >& curFaceWeights =
|
||||||
faceFaceWeightsTable.find(contents[masterI])();
|
faceFaceWeightsTable.find(contents[masterI])();
|
||||||
|
|
||||||
SLList<label>::iterator nbrsIter = curNbrs.begin();
|
SLList<long>::iterator nbrsIter = curNbrs.begin();
|
||||||
|
|
||||||
SLList<SLList<label> >::iterator faceFacesIter =
|
SLList<SLList<label> >::iterator faceFacesIter =
|
||||||
curFaceFaces.begin();
|
curFaceFaces.begin();
|
||||||
|
|
||||||
|
SLList<SLList<label> >::iterator faceFaceNbrsIter =
|
||||||
|
curFaceFaceNbrs.begin();
|
||||||
|
|
||||||
SLList<SLList<scalar> >::iterator faceFaceWeightsIter =
|
SLList<SLList<scalar> >::iterator faceFaceWeightsIter =
|
||||||
curFaceWeights.begin();
|
curFaceWeights.begin();
|
||||||
|
|
||||||
|
@ -769,28 +920,52 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
;
|
;
|
||||||
nbrsIter != curNbrs.end()
|
nbrsIter != curNbrs.end()
|
||||||
&& faceFacesIter != curFaceFaces.end()
|
&& faceFacesIter != curFaceFaces.end()
|
||||||
|
&& faceFaceNbrsIter != curFaceFaceNbrs.end()
|
||||||
&& faceFaceWeightsIter != curFaceWeights.end();
|
&& faceFaceWeightsIter != curFaceWeights.end();
|
||||||
++nbrsIter, ++faceFacesIter, ++faceFaceWeightsIter
|
++nbrsIter, ++faceFacesIter, ++faceFaceNbrsIter,
|
||||||
|
++faceFaceWeightsIter
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Check if the face is on local processor: no longer needed,
|
// Check if the face is on local processor: no longer needed,
|
||||||
// as only local processor is being searched. HJ, 13/Jun/2016
|
// as only local processor is being searched. HJ, 13/Jun/2016
|
||||||
|
|
||||||
// Record that this face belongs locally.
|
|
||||||
|
|
||||||
//HJ, HERE: I need to find out the global face index for the face that was created from the master side
|
|
||||||
|
|
||||||
zoneAddressing_[nProcFaces] = nCoarseFaces;
|
|
||||||
faceCells_[nProcFaces] =
|
|
||||||
nbrsIter() - procOffset*Pstream::myProcNo();
|
|
||||||
nProcFaces++;
|
|
||||||
|
|
||||||
SLList<label>::iterator facesIter =
|
SLList<label>::iterator facesIter =
|
||||||
faceFacesIter().begin();
|
faceFacesIter().begin();
|
||||||
|
|
||||||
|
SLList<label>::iterator faceNbrsIter =
|
||||||
|
faceFaceNbrsIter().begin();
|
||||||
|
|
||||||
SLList<scalar>::iterator weightsIter =
|
SLList<scalar>::iterator weightsIter =
|
||||||
faceFaceWeightsIter().begin();
|
faceFaceWeightsIter().begin();
|
||||||
|
|
||||||
|
// Find neighbour proc index from the first face
|
||||||
|
// on the other side
|
||||||
|
label nbrProc;
|
||||||
|
|
||||||
|
if (fineGgiInterface_.fineLevel())
|
||||||
|
{
|
||||||
|
const labelListList& fineAddr =
|
||||||
|
fineGgiInterface_.addressing();
|
||||||
|
|
||||||
|
nbrProc = neighbourExpandProc
|
||||||
|
[fineAddr[facesIter()][faceNbrsIter()]];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nbrProc = neighbourExpandProc[facesIter()];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read coarse face index
|
||||||
|
const label coarseFace =
|
||||||
|
masterProcMasterFaces[nbrProc][npmf[nbrProc]];
|
||||||
|
|
||||||
|
// and mark it as used
|
||||||
|
npmf[nbrProc]++;
|
||||||
|
|
||||||
|
zoneAddressing_[nProcFaces] = coarseFace;
|
||||||
|
faceCells_[nProcFaces] =
|
||||||
|
nbrsIter() - procOffset*Pstream::myProcNo();
|
||||||
|
|
||||||
for
|
for
|
||||||
(
|
(
|
||||||
;
|
;
|
||||||
|
@ -800,19 +975,15 @@ Foam::ggiAMGInterface::ggiAMGInterface
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
fineAddressing_[nAgglomPairs] = facesIter();
|
fineAddressing_[nAgglomPairs] = facesIter();
|
||||||
restrictAddressing_[nAgglomPairs] = nCoarseFaces;
|
restrictAddressing_[nAgglomPairs] = coarseFace;
|
||||||
restrictWeights_[nAgglomPairs] = weightsIter();
|
restrictWeights_[nAgglomPairs] = weightsIter();
|
||||||
|
|
||||||
nAgglomPairs++;
|
nAgglomPairs++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resize arrays: not all of ggi is used locally
|
nProcFaces++;
|
||||||
faceCells_.setSize(nProcFaces);
|
}
|
||||||
zoneAddressing_.setSize(nProcFaces);
|
}
|
||||||
fineAddressing_.setSize(nAgglomPairs);
|
|
||||||
restrictAddressing_.setSize(nAgglomPairs);
|
|
||||||
restrictWeights_.setSize(nAgglomPairs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -934,6 +1105,21 @@ bool Foam::ggiAMGInterface::localParallel() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::labelListList& Foam::ggiAMGInterface::procMasterFaces() const
|
||||||
|
{
|
||||||
|
if (!master())
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"const labelListList& ggiGAMGInterface::procMasterFaces() const"
|
||||||
|
) << "Requester procMasterFaces from a slave. This is not allowed"
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
return procMasterFaces_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const Foam::mapDistribute& Foam::ggiAMGInterface::map() const
|
const Foam::mapDistribute& Foam::ggiAMGInterface::map() const
|
||||||
{
|
{
|
||||||
if (!mapPtr_)
|
if (!mapPtr_)
|
||||||
|
|
|
@ -68,6 +68,11 @@ class ggiAMGInterface
|
||||||
//- Zone addressing
|
//- Zone addressing
|
||||||
labelList zoneAddressing_;
|
labelList zoneAddressing_;
|
||||||
|
|
||||||
|
//- Processor master faces
|
||||||
|
// Per-processor insertion list of local faces into global zone
|
||||||
|
// The list is created on the master side and passed onto the slave
|
||||||
|
// to allow the slave to insert faces in the same order
|
||||||
|
labelListList procMasterFaces_;
|
||||||
|
|
||||||
// Parallel communication
|
// Parallel communication
|
||||||
|
|
||||||
|
@ -110,14 +115,14 @@ public:
|
||||||
ggiAMGInterface
|
ggiAMGInterface
|
||||||
(
|
(
|
||||||
const lduPrimitiveMesh& lduMesh,
|
const lduPrimitiveMesh& lduMesh,
|
||||||
|
const lduInterfacePtrsList& coarseInterfaces,
|
||||||
const lduInterface& fineInterface,
|
const lduInterface& fineInterface,
|
||||||
const labelField& localRestrictAddressing,
|
const labelField& localRestrictAddressing,
|
||||||
const labelField& neighbourRestrictAddressing
|
const labelField& neighbourRestrictAddressing
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// Destructor
|
//- Destructor
|
||||||
|
|
||||||
virtual ~ggiAMGInterface();
|
virtual ~ggiAMGInterface();
|
||||||
|
|
||||||
|
|
||||||
|
@ -240,6 +245,9 @@ public:
|
||||||
//- Is the patch localised on a single processor
|
//- Is the patch localised on a single processor
|
||||||
virtual bool localParallel() const;
|
virtual bool localParallel() const;
|
||||||
|
|
||||||
|
//- Processor master face insertion list
|
||||||
|
const labelListList& procMasterFaces() const;
|
||||||
|
|
||||||
//- Return weights
|
//- Return weights
|
||||||
virtual const scalarListList& weights() const;
|
virtual const scalarListList& weights() const;
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@ namespace Foam
|
||||||
Foam::mixingPlaneAMGInterface::mixingPlaneAMGInterface
|
Foam::mixingPlaneAMGInterface::mixingPlaneAMGInterface
|
||||||
(
|
(
|
||||||
const lduPrimitiveMesh& lduMesh,
|
const lduPrimitiveMesh& lduMesh,
|
||||||
|
const lduInterfacePtrsList& coarseInterfaces,
|
||||||
const lduInterface& fineInterface,
|
const lduInterface& fineInterface,
|
||||||
const labelField& localRestrictAddressing,
|
const labelField& localRestrictAddressing,
|
||||||
const labelField& neighbourRestrictAddressing
|
const labelField& neighbourRestrictAddressing
|
||||||
|
|
|
@ -93,6 +93,7 @@ public:
|
||||||
mixingPlaneAMGInterface
|
mixingPlaneAMGInterface
|
||||||
(
|
(
|
||||||
const lduPrimitiveMesh& lduMesh,
|
const lduPrimitiveMesh& lduMesh,
|
||||||
|
const lduInterfacePtrsList& coarseInterfaces,
|
||||||
const lduInterface& fineInterface,
|
const lduInterface& fineInterface,
|
||||||
const labelField& localRestrictAddressing,
|
const labelField& localRestrictAddressing,
|
||||||
const labelField& neighbourRestrictAddressing
|
const labelField& neighbourRestrictAddressing
|
||||||
|
|
|
@ -45,6 +45,7 @@ namespace Foam
|
||||||
Foam::processorAMGInterface::processorAMGInterface
|
Foam::processorAMGInterface::processorAMGInterface
|
||||||
(
|
(
|
||||||
const lduPrimitiveMesh& lduMesh,
|
const lduPrimitiveMesh& lduMesh,
|
||||||
|
const lduInterfacePtrsList& coarseInterfaces,
|
||||||
const lduInterface& fineInterface,
|
const lduInterface& fineInterface,
|
||||||
const labelField& localRestrictAddressing,
|
const labelField& localRestrictAddressing,
|
||||||
const labelField& neighbourRestrictAddressing
|
const labelField& neighbourRestrictAddressing
|
||||||
|
|
|
@ -81,6 +81,7 @@ public:
|
||||||
processorAMGInterface
|
processorAMGInterface
|
||||||
(
|
(
|
||||||
const lduPrimitiveMesh& lduMesh,
|
const lduPrimitiveMesh& lduMesh,
|
||||||
|
const lduInterfacePtrsList& coarseInterfaces,
|
||||||
const lduInterface& fineInterface,
|
const lduInterface& fineInterface,
|
||||||
const labelField& localRestrictAddressing,
|
const labelField& localRestrictAddressing,
|
||||||
const labelField& neighbourRestrictAddressing
|
const labelField& neighbourRestrictAddressing
|
||||||
|
|
|
@ -45,6 +45,7 @@ namespace Foam
|
||||||
Foam::regionCoupleAMGInterface::regionCoupleAMGInterface
|
Foam::regionCoupleAMGInterface::regionCoupleAMGInterface
|
||||||
(
|
(
|
||||||
const lduPrimitiveMesh& lduMesh,
|
const lduPrimitiveMesh& lduMesh,
|
||||||
|
const lduInterfacePtrsList& coarseInterfaces,
|
||||||
const lduInterface& fineInterface,
|
const lduInterface& fineInterface,
|
||||||
const labelField& localRestrictAddressing,
|
const labelField& localRestrictAddressing,
|
||||||
const labelField& neighbourRestrictAddressing
|
const labelField& neighbourRestrictAddressing
|
||||||
|
@ -53,6 +54,7 @@ Foam::regionCoupleAMGInterface::regionCoupleAMGInterface
|
||||||
ggiAMGInterface
|
ggiAMGInterface
|
||||||
(
|
(
|
||||||
lduMesh,
|
lduMesh,
|
||||||
|
coarseInterfaces,
|
||||||
fineInterface,
|
fineInterface,
|
||||||
localRestrictAddressing,
|
localRestrictAddressing,
|
||||||
neighbourRestrictAddressing
|
neighbourRestrictAddressing
|
||||||
|
|
|
@ -73,6 +73,7 @@ public:
|
||||||
regionCoupleAMGInterface
|
regionCoupleAMGInterface
|
||||||
(
|
(
|
||||||
const lduPrimitiveMesh& lduMesh,
|
const lduPrimitiveMesh& lduMesh,
|
||||||
|
const lduInterfacePtrsList& coarseInterfaces,
|
||||||
const lduInterface& fineInterface,
|
const lduInterface& fineInterface,
|
||||||
const labelField& localRestrictAddressing,
|
const labelField& localRestrictAddressing,
|
||||||
const labelField& neighbourRestrictAddressing
|
const labelField& neighbourRestrictAddressing
|
||||||
|
|
|
@ -648,6 +648,7 @@ Foam::autoPtr<Foam::amgMatrix> Foam::pamgPolicy::restrictMatrix
|
||||||
AMGInterface::New
|
AMGInterface::New
|
||||||
(
|
(
|
||||||
*coarseAddrPtr,
|
*coarseAddrPtr,
|
||||||
|
coarseInterfaces,
|
||||||
fineInterface,
|
fineInterface,
|
||||||
fineInterface.interfaceInternalField(child_),
|
fineInterface.interfaceInternalField(child_),
|
||||||
fineInterfaceAddr[intI]
|
fineInterfaceAddr[intI]
|
||||||
|
|
Reference in a new issue