48 #ifndef _ZOLTAN2_ALGND_HPP_ 49 #define _ZOLTAN2_ALGND_HPP_ 83 template <
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);
187 template <
typename Adapter>
191 throw std::logic_error(
"AlgND does not support global ordering.");
199 template <
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);
431 const std::vector<lno_t> &vertUMatches = bpMatch.getVertexUMatches();
432 const std::vector<lno_t> &vertVMatches = bpMatch.getVertexVMatches();
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;
525 template <
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)];
704 template <
typename Adapter>
705 void AlgND<Adapter>::
706 buildPartTree(
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]];
834 template <
typename Adapter>
835 void AlgND<Adapter>::
836 fillSolutionIperm(
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();
893 template <
typename Adapter>
894 void AlgND<Adapter>::
895 getIdsOfPart(
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())
Created by mbenlioglu on Aug 31, 2020.
#define Z2_THROW_SERIAL(mystr)
Throw an error when code is run on more than one processor.
LO match()
Computes the maximum cardinality matching.
interface to the Zoltan package
map_t::global_ordinal_type gno_t
Defines the PartitioningSolution class.
An implementation of the Matcher interface that operates on Epetra matrices and Graphs.
sub-steps, each method's entry and exit
static void getValidParameters(ParameterList &pl)
Set up validators specific to this algorithm
int globalOrder(const RCP< GlobalOrderingSolution< gno_t > > &solution_)
Ordering method.
SparseMatrixAdapter_t::part_t part_t
This class provides geometric coordinates with optional weights to the Zoltan2 algorithm.
Defines the IdentifierModel interface.
A PartitioningSolution is a solution to a partitioning problem.
The StridedData class manages lists of weights or coordinates.
lno_t size() const
Return the length of the strided array.
Algorithm defines the base class for all algorithms.
map_t::local_ordinal_type lno_t
The user parameters, debug, timing and memory profiling output objects, and error checking methods...
#define Z2_THROW_EXPERIMENTAL(mystr)
Throw an error when experimental code is requested but not compiled.
GraphModel defines the interface required for graph models.
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_)
int localOrder(const RCP< LocalOrderingSolution< lno_t > > &solution_)
Ordering method.