48#ifndef _ZOLTAN2_ALGND_HPP_
49#define _ZOLTAN2_ALGND_HPP_
84template <
typename Adapter>
96 const RCP<const Environment> mEnv;
97 const RCP<const Comm<int> > mProblemComm;
99 std::string mPartitionMethod;
101 const RCP<GraphModel<typename Adapter::base_adapter_t> > mGraphModel;
102 const RCP<const typename Adapter::base_adapter_t> mBaseInputAdapter;
104 void getBoundLayer(part_t levelIndx,
const std::vector<part_t> &partMap,
105 const part_t * parts,
106 const std::set<lno_t> &excVerts,
107 lno_t &bigraphNumS, lno_t &bigraphNumT, lno_t &bigraphNumE,
108 std::vector<lno_t> &bigraphCRSRowPtr, std::vector<lno_t> &bigraphCRSCols,
109 std::vector<lno_t> &bigraphVMapU, std::vector<lno_t> &bigraphVMapV);
111 void buildPartTree(part_t level, std::vector<part_t> &levIndx,
113 const std::vector<part_t> &permPartNums,
114 const std::vector<part_t> &splitRangeBeg,
115 const std::vector<part_t> &splitRangeEnd,
116 const std::vector<part_t> &treeVertParents,
117 std::vector<part_t> &sepLevels,
118 std::vector<std::set<part_t> > &sepParts1, std::vector<std::set<part_t> > &sepParts2,
121 part_t *sepTreeView, std::vector<std::pair<part_t,part_t> > &treeIndxToSepLev);
123 void fillSolutionIperm(
const part_t *parts,
const std::set<lno_t> &sepVerts,
124 const std::vector<std::vector< std::set<lno_t> > > & sepVertsByLevel,
125 const std::vector<std::pair<part_t,part_t> > &treeIndxToSepLev,
126 lno_t * ipermView, lno_t *sepRangeView);
128 void getIdsOfPart(
const part_t *parts, part_t targetPart,
const std::set<lno_t> &idsToExcl,
129 std::set<lno_t> &outIds);
134 AlgND(
const RCP<const Environment> &env_,
135 const RCP<
const Comm<int> > &problemComm_,
138 const RCP<const typename Adapter::base_adapter_t> baseInputAdapter_
140 :mEnv(env_), mProblemComm(problemComm_), mPartitionMethod(
"rcb"),
141 mGraphModel(gModel_),
142 mBaseInputAdapter(baseInputAdapter_)
144#ifndef INCLUDE_ZOLTAN2_EXPERIMENTAL
148 if(mProblemComm->getSize()!=1)
154 const Teuchos::ParameterList &pl = mEnv->getParameters();
155 const Teuchos::ParameterEntry *pe;
158 pe = pl.getEntryPtr(
"edge_separator_method");
162 mPartitionMethod = pe->getValue<std::string>(&mPartitionMethod);
176 RCP<Teuchos::StringValidator> es_method_Validator =
177 Teuchos::rcp(
new Teuchos::StringValidator(Teuchos::tuple<std::string>(
"rcb",
"phg")));
179 pl.set(
"edge_separator_method",
"rcb",
"ND ordering - Edge separator method", es_method_Validator);
187template <
typename Adapter>
191 throw std::logic_error(
"AlgND does not support global ordering.");
199template <
typename Adapter>
212 Teuchos::ParameterList partParams;
214 part_t numParts = mEnv->getParameters().template get<part_t>(
"num_global_parts");
216 partParams.set(
"num_global_parts", numParts);
219 partParams.set(
"keep_partition_tree",
true);
223 Teuchos::ParameterList &zparams = partParams.sublist(
"zoltan_parameters",
false);
224 zparams.set(
"LB_METHOD", mPartitionMethod);
230 const RCP<const Environment> partEnv = rcp(
new Zoltan2::Environment(partParams,this->mEnv->comm_));
235 RCP<AlgZoltan<Adapter> > algZoltan = rcp(
new AlgZoltan<Adapter>(partEnv, mProblemComm, this->mBaseInputAdapter));
237 RCP<PartitioningSolution<Adapter> > partSoln;
242 algZoltan->partition(partSoln);
244 size_t numGlobalParts = partSoln->getTargetGlobalNumberOfParts();
246 const part_t *parts = partSoln->getPartListView();
260 assert(partSoln->isPartitioningTreeBinary()==
true);
265 part_t numTreeVerts = 0;
266 std::vector<part_t> permPartNums;
268 std::vector<part_t> splitRangeBeg;
269 std::vector<part_t> splitRangeEnd;
270 std::vector<part_t> treeVertParents;
272 partSoln->getPartitionTree(numTreeVerts,permPartNums,splitRangeBeg,
273 splitRangeEnd,treeVertParents);
287 std::vector<part_t> levInds;
289 std::vector<part_t> sepLevels;
290 std::vector<std::set<part_t> > sepParts1;
291 std::vector<std::set<part_t> > sepParts2;
293 std::vector<std::pair<part_t,part_t> > treeIndxToSepLev(treeVertParents.size());
298 part_t *sepTreeView = solution_->getSeparatorTreeView();
300 part_t sepTreeIndx= treeVertParents.size()-1;
302 sepTreeView[sepTreeIndx]=-1;
304 buildPartTree(0, levInds, numTreeVerts, permPartNums, splitRangeBeg, splitRangeEnd, treeVertParents,
305 sepLevels, sepParts1, sepParts2, maxLevel, sepTreeIndx,sepTreeView,treeIndxToSepLev);
307 solution_->setHaveSeparatorTree(
true);
323 part_t numSeparators = sepLevels.size();
332 part_t numLevels = maxLevel+1;
334 std::vector<std::vector<part_t> > partLevelMap(numLevels,std::vector<part_t>(numGlobalParts));
336 std::vector<part_t> sepsInLev(numLevels,0);
338 for(part_t i=0;i<numSeparators;i++)
340 part_t level = sepLevels[i];
342 for(
typename std::set<part_t>::const_iterator iter = sepParts1[i].begin();
343 iter!=sepParts1[i].end();++iter)
345 partLevelMap[level][*iter] = 2*sepsInLev[level];
349 for(
typename std::set<part_t>::const_iterator iter = sepParts2[i].begin();
350 iter!=sepParts2[i].end();++iter)
352 partLevelMap[level][*iter] = 2*sepsInLev[level]+1;
362 std::set<lno_t> sepVerts;
363 std::vector<std::vector< std::set<lno_t> > > sepVertsByLevel(numLevels);
370 for(part_t level=0;level<numLevels;level++)
372 sepVertsByLevel[level].resize(sepsInLev[level]);
374 for(part_t levIndx=0;levIndx<sepsInLev[level];levIndx++)
380 lno_t bigraphNumU=0, bigraphNumV=0;
382 std::vector<lno_t> bigraphVMapU;
383 std::vector<lno_t> bigraphVMapV;
385 std::vector<lno_t> bigraphCRSRowPtr;
386 std::vector<lno_t> bigraphCRSCols;
389 getBoundLayer(levIndx, partLevelMap[level], parts, sepVerts,
390 bigraphNumU,bigraphNumV,bigraphNumE,
391 bigraphCRSRowPtr, bigraphCRSCols,
392 bigraphVMapU,bigraphVMapV);
426 assert(bigraphNumV>0);
428 Matcher<lno_t> bpMatch(bigraphCRSRowPtr.data(), bigraphCRSCols.data(), bigraphNumU, bigraphNumV, bigraphNumE);
438 std::vector<lno_t> VC;
440 bpMatch.
getVCfromMatching(bigraphCRSRowPtr,bigraphCRSCols,vertUMatches,vertVMatches,
441 bigraphVMapU,bigraphVMapV,VC);
443 for(
size_t i=0;i<VC.size();i++)
445 sepVerts.insert(VC[i]);
447 sepVertsByLevel[level][levIndx].insert(VC[i]);
460 lno_t *ipermView = solution_->getPermutationView(inverse);
461 lno_t *sepRangeView = solution_->getSeparatorRangeView();
463 fillSolutionIperm(parts, sepVerts,sepVertsByLevel,treeIndxToSepLev,ipermView, sepRangeView);
465 solution_->setHaveInverse(
true);
466 solution_->setHaveSeparatorRange(
true);
472 std::cout <<
"Separators: " << std::endl;
474 part_t nLevels = sepVertsByLevel.size();
475 for(part_t level=0;level<nLevels;level++)
478 part_t nSepsOnLev = sepVertsByLevel[level].size();
480 for(part_t levIndx=0;levIndx<nSepsOnLev;levIndx++)
482 std::cout <<
" Separator " << level <<
" " << levIndx <<
": ";
484 typename std::set<lno_t>::const_iterator iterS;
485 for (iterS=sepVertsByLevel[level][levIndx].begin();iterS!=sepVertsByLevel[level][levIndx].end();++iterS)
487 std::cout << *iterS <<
" ";
489 std::cout << std::endl;
525template <
typename Adapter>
528 const std::set<lno_t> &excVerts,
530 std::vector<lno_t> &bigraphCRSRowPtr, std::vector<lno_t> &bigraphCRSCols,
531 std::vector<lno_t> &bigraphVMapS, std::vector<lno_t> &bigraphVMapT)
533 typedef typename Adapter::offset_t offset_t;
536 lno_t numVerts = mGraphModel->getLocalNumVertices();
540 ArrayView< const gno_t > eIDs;
541 ArrayView< const offset_t > vOffsets;
542 ArrayView< input_t > wgts;
554 mGraphModel->getEdgeList(eIDs, vOffsets, wgts);
560 std::map<lno_t,std::set<lno_t> > bigraphEs;
561 std::set<lno_t> vSetS;
562 std::set<lno_t> vSetT;
566 for(
lno_t v1=0;v1<numVerts;v1++)
569 part_t vpart1 = partMap[parts[v1]];
571 bool correctBL = (vpart1 >= 2*levelIndx && vpart1 < 2*(levelIndx+1) );
581 if(excVerts.find(v1)!=excVerts.end())
588 for(offset_t j=vOffsets[v1];j<vOffsets[v1+1];j++)
593 part_t vpart2 = partMap[parts[v2]];
595 correctBL = (vpart2 >= 2*levelIndx && vpart2 < 2*(levelIndx+1) );
605 if(excVerts.find(v2)!=excVerts.end())
610 if ( vpart1 != vpart2 )
618 if(bigraphEs.find(v1)==bigraphEs.end())
620 bigraphEs[v1] = std::set<lno_t>();
622 bigraphEs[v1].insert(v2);
639 bigraphNumS = vSetS.size();
640 bigraphNumT = vSetT.size();
646 bigraphVMapS.resize(bigraphNumS);
648 std::map<lno_t,lno_t> glob2LocTMap;
651 for(
typename std::set<lno_t>::const_iterator iter=vSetS.begin(); iter!=vSetS.end(); ++iter)
653 bigraphVMapS[indx] = *iter;
658 bigraphVMapT.resize(bigraphNumT);
660 for(
typename std::set<lno_t>::const_iterator iter=vSetT.begin();iter!=vSetT.end();++iter)
662 bigraphVMapT[indx] = *iter;
663 glob2LocTMap[*iter]=indx;
672 bigraphCRSRowPtr.resize(bigraphNumS+1);
673 bigraphCRSCols.resize(bigraphNumE);
679 bigraphCRSRowPtr[0]=0;
683 typename std::map<lno_t,std::set<lno_t> >::const_iterator iterM;
684 for (iterM=bigraphEs.begin();iterM!=bigraphEs.end();++iterM)
686 bigraphCRSRowPtr[rownum+1] = bigraphCRSRowPtr[rownum] + (*iterM).second.size();
688 for(
typename std::set<lno_t>::const_iterator iter=(*iterM).second.begin(); iter!=(*iterM).second.end(); ++iter)
690 bigraphCRSCols[nzIndx] = glob2LocTMap[(*iter)];
704template <
typename Adapter>
706buildPartTree(
part_t level, std::vector<part_t> &levIndx,
708 const std::vector<part_t> &permPartNums,
709 const std::vector<part_t> &splitRangeBeg,
710 const std::vector<part_t> &splitRangeEnd,
711 const std::vector<part_t> &treeVertParents,
712 std::vector<part_t> &sepLevels,
713 std::vector<std::set<part_t> > &sepParts1, std::vector<std::set<part_t> > &sepParts2,
715 part_t *sepTreeView,std::vector<std::pair<part_t,part_t> > &treeIndxToSepLev)
724 typename std::vector<part_t>::const_iterator iter;
725 std::vector<part_t> inds;
727 for(iter=treeVertParents.begin(); iter!=treeVertParents.end(); ++iter)
741 assert(inds.size()==2 || inds.size()==0);
748 if((
part_t)levIndx.size() < level+1)
750 levIndx.push_back(0);
759 treeIndxToSepLev[gIndx].first = level;
760 treeIndxToSepLev[gIndx].second = levIndx[level];
765 sepLevels.push_back(level);
767 sepParts1.push_back(std::set<part_t>());
768 typename std::vector<std::set<part_t> >::iterator setIter = sepParts1.end();
771 for(
part_t k=splitRangeBeg[v0]; k<splitRangeEnd[v0]; k++)
773 (*setIter).insert(permPartNums[k]);
777 sepParts2.push_back(std::set<part_t>());
778 setIter = sepParts2.end();
781 for(
part_t k=splitRangeBeg[v1]; k<splitRangeEnd[v1]; k++)
783 (*setIter).insert(permPartNums[k]);
786 part_t parentNode = gIndx;
788 sepTreeView[gIndx] = parentNode;
791 buildPartTree(level+1, levIndx,v0,
792 permPartNums, splitRangeBeg, splitRangeEnd, treeVertParents,
793 sepLevels, sepParts1, sepParts2,
795 gIndx,sepTreeView,treeIndxToSepLev);
803 sepTreeView[gIndx] = parentNode;
805 buildPartTree(level+1, levIndx, v1,
806 permPartNums, splitRangeBeg, splitRangeEnd, treeVertParents,
807 sepLevels, sepParts1, sepParts2,
809 gIndx, sepTreeView,treeIndxToSepLev);
820 treeIndxToSepLev[gIndx].first = -1;
821 treeIndxToSepLev[gIndx].second = permPartNums[splitRangeBeg[startV]];
834template <
typename Adapter>
836fillSolutionIperm(
const part_t *parts,
const std::set<lno_t> &sepVerts,
837 const std::vector<std::vector< std::set<lno_t> > > & sepVertsByLevel,
838 const std::vector<std::pair<part_t,part_t> > &treeIndxToSepLev,
842 lno_t sepRangeIndx=0;
843 sepRangeView[sepRangeIndx] = 0;
845 for(
size_t i=0; i<treeIndxToSepLev.size();i++)
847 part_t lev = treeIndxToSepLev[i].first;
853 std::set<lno_t> idSet;
854 getIdsOfPart(parts,treeIndxToSepLev[i].second,sepVerts,idSet);
856 for(
typename std::set<lno_t>::const_iterator setIter=idSet.begin(); setIter != idSet.end();
859 ipermView[permIndx]=*setIter;
862 sepRangeView[sepRangeIndx+1]=sepRangeView[sepRangeIndx]+idSet.size();
872 const std::set<lno_t> &idSet = sepVertsByLevel[lev][treeIndxToSepLev[i].second];
874 for(
typename std::set<lno_t>::const_iterator setIter=idSet.begin();
875 setIter != idSet.end(); ++setIter)
877 ipermView[permIndx]=*setIter;
880 sepRangeView[sepRangeIndx+1]=sepRangeView[sepRangeIndx]+idSet.size();
893template <
typename Adapter>
895getIdsOfPart(
const part_t *parts,
part_t targetPart,
const std::set<lno_t> &idsToExcl,
896 std::set<lno_t> &outIds)
898 size_t numVerts = mGraphModel->getLocalNumVertices();
900 for(
size_t i=0; i<numVerts; i++)
902 if(parts[i]==targetPart && idsToExcl.find(i)==idsToExcl.end())
interface to the Zoltan package
#define Z2_THROW_SERIAL(mystr)
Throw an error when code is run on more than one processor.
#define Z2_THROW_EXPERIMENTAL(mystr)
Throw an error when experimental code is requested but not compiled.
Defines the IdentifierModel interface.
Defines the PartitioningSolution class.
int localOrder(const RCP< LocalOrderingSolution< lno_t > > &solution_)
Ordering method.
AlgND(const RCP< const Environment > &env_, const RCP< const Comm< int > > &problemComm_, const RCP< GraphModel< typename Adapter::base_adapter_t > > &gModel_, const RCP< CoordinateModel< typename Adapter::base_adapter_t > > &cModel_, const RCP< const typename Adapter::base_adapter_t > baseInputAdapter_)
static void getValidParameters(ParameterList &pl)
Set up validators specific to this algorithm
int globalOrder(const RCP< GlobalOrderingSolution< gno_t > > &solution_)
Ordering method.
Algorithm defines the base class for all algorithms.
This class provides geometric coordinates with optional weights to the Zoltan2 algorithm.
The user parameters, debug, timing and memory profiling output objects, and error checking methods.
GraphModel defines the interface required for graph models.
An implementation of the Matcher interface that operates on Epetra matrices and Graphs.
const std::vector< LO > & getVertexVMatches()
const std::vector< LO > & getVertexUMatches()
void getVCfromMatching(const std::vector< LO > &bigraphCRSRowPtr, std::vector< LO > &bigraphCRSCols, const std::vector< LO > &vertUMatches, const std::vector< LO > &vertVMatches, const std::vector< LO > &bigraphVMapU, const std::vector< LO > &bigraphVMapV, std::vector< LO > &VC)
LO match()
Computes the maximum cardinality matching.
A PartitioningSolution is a solution to a partitioning problem.
The StridedData class manages lists of weights or coordinates.
map_t::local_ordinal_type lno_t
map_t::global_ordinal_type gno_t
Created by mbenlioglu on Aug 31, 2020.
@ DETAILED_STATUS
sub-steps, each method's entry and exit
SparseMatrixAdapter_t::part_t part_t