An example of the use of the RCB algorithm to partition coordinate data.
#include <Tpetra_Map.hpp>
#include <vector>
#include <cstdlib>
int main(
int argc,
char *argv[])
{
Tpetra::ScopeGuard tscope(&argc, &argv);
Teuchos::RCP<const Teuchos::Comm<int> > comm = Tpetra::getDefaultComm();
int rank = comm->getRank();
int nprocs = comm->getSize();
typedef Tpetra::Map<> Map_t;
typedef Map_t::local_ordinal_type localId_t;
typedef Map_t::global_ordinal_type globalId_t;
typedef Tpetra::Details::DefaultTypes::scalar_type scalar_t;
typedef inputAdapter_t::part_t
part_t;
size_t localCount = 40;
int dim = 3;
scalar_t *coords = new scalar_t [dim * localCount];
scalar_t *x = coords;
scalar_t *y = x + localCount;
scalar_t *z = y + localCount;
srand(rank);
scalar_t scalingFactor = 10.0 / RAND_MAX;
for (size_t i=0; i < localCount*dim; i++){
coords[i] = scalar_t(rand()) * scalingFactor;
}
globalId_t *globalIds = new globalId_t [localCount];
globalId_t offset = rank * localCount;
for (size_t i=0; i < localCount; i++)
globalIds[i] = offset++;
double tolerance = 1.1;
if (rank == 0)
std::cout << "Imbalance tolerance is " << tolerance << std::endl;
Teuchos::ParameterList params("test params");
params.set("debug_level", "basic_status");
params.set("debug_procs", "0");
params.set("error_check_level", "debug_mode_assertions");
params.set("algorithm", "rcb");
params.set("imbalance_tolerance", tolerance );
params.set("num_global_parts", nprocs);
inputAdapter_t *ia1 = new inputAdapter_t(localCount,globalIds,x,y,z,1,1,1);
if (rank == 0) {
}
if (rank == 0){
if (imb <= tolerance)
std::cout << "pass: " << imb << std::endl;
else
std::cout << "fail: " << imb << std::endl;
std::cout << std::endl;
}
delete metricObject1;
scalar_t *
weights =
new scalar_t [localCount];
for (size_t i=0; i < localCount; i++){
weights[i] = 1.0 + scalar_t(rank) / scalar_t(nprocs);
}
std::vector<const scalar_t *>coordVec(2);
std::vector<int> coordStrides(2);
coordVec[0] = x; coordStrides[0] = 1;
coordVec[1] = y; coordStrides[1] = 1;
std::vector<const scalar_t *>weightVec(1);
std::vector<int> weightStrides(1);
weightVec[0] =
weights; weightStrides[0] = 1;
inputAdapter_t *ia2=new inputAdapter_t(localCount, globalIds, coordVec,
coordStrides,weightVec,weightStrides);
#ifdef HAVE_ZOLTAN2_MPI
MPI_COMM_WORLD,
#else
#endif
if (rank == 0) {
}
if (rank == 0){
if (imb <= tolerance)
std::cout << "pass: " << imb << std::endl;
else
std::cout << "fail: " << imb << std::endl;
std::cout << std::endl;
}
delete metricObject2;
if (localCount > 0){
}
params.set("partitioning_objective", "multicriteria_minimize_total_weight");
weights =
new scalar_t [localCount*3];
srand(rank);
for (size_t i=0; i < localCount*3; i+=3){
weights[i+1] = rank<nprocs/2 ? 1 : 2;
weights[i+2] = rand()/RAND_MAX +.5;
}
weightVec.resize(3);
weightStrides.resize(3);
weightVec[0] =
weights; weightStrides[0] = 3;
weightVec[1] =
weights+1; weightStrides[1] = 3;
weightVec[2] =
weights+2; weightStrides[2] = 3;
inputAdapter_t *ia3=new inputAdapter_t(localCount, globalIds, coordVec,
coordStrides,weightVec,weightStrides);
if (rank == 0) {
}
if (rank == 0){
if (imb <= tolerance)
std::cout << "pass: " << imb << std::endl;
else
std::cout << "fail: " << imb << std::endl;
std::cout << std::endl;
}
delete metricObject3;
bool dataHasChanged = false;
params.set("partitioning_objective", "multicriteria_minimize_maximum_weight");
problem3->
solve(dataHasChanged);
if (rank == 0){
if (imb <= tolerance)
std::cout << "pass: " << imb << std::endl;
else
std::cout << "fail: " << imb << std::endl;
std::cout << std::endl;
}
delete metricObject3;
params.set("partitioning_objective", "multicriteria_balance_total_maximum");
problem3->
solve(dataHasChanged);
if (rank == 0){
if (imb <= tolerance)
std::cout << "pass: " << imb << std::endl;
else
std::cout << "fail: " << imb << std::endl;
std::cout << std::endl;
}
delete metricObject3;
if (localCount > 0){
}
params.set("num_global_parts", nprocs*2);
scalar_t partSizes[2];
partIds[0] = rank*2; partSizes[0] = 0;
partIds[1] = rank*2+1; partSizes[1] = 1;
dataHasChanged = false;
problem1->
solve(dataHasChanged);
int numInEmptyParts = 0;
for (size_t i=0; i < localCount; i++){
if (partAssignments[i] % 2 == 0)
numInEmptyParts++;
}
if (rank == 0)
std::cout << "Request that " << nprocs << " parts be empty." <<std::endl;
if (rank == 0) {
}
if (rank == 0){
if (imb <= tolerance)
std::cout << "pass: " << imb << std::endl;
else
std::cout << "fail: " << imb << std::endl;
std::cout << std::endl;
}
delete metricObject1;
if (coords)
delete [] coords;
if (globalIds)
delete [] globalIds;
delete problem1;
delete ia1;
delete problem2;
delete ia2;
delete problem3;
delete ia3;
if (rank == 0)
std::cout << "PASS" << std::endl;
}
Defines the BasicVectorAdapter class.
Defines the PartitioningProblem class.
Defines the PartitioningSolution class.
A simple class that can be the User template argument for an InputAdapter.
BasicVectorAdapter represents a vector (plus optional weights) supplied by the user as pointers to st...
A class that computes and returns quality metrics.
void printMetrics(std::ostream &os) const
Print all metrics.
scalar_t getWeightImbalance(int weightIndex) const
Return the imbalance for the requested weight.
scalar_t getObjectCountImbalance() const
Return the object count imbalance.
PartitioningProblem sets up partitioning problems for the user.
const PartitioningSolution< Adapter > & getSolution()
Get the solution to the problem.
void solve(bool updateInputData=true)
Direct the problem to create a solution.
void setPartSizes(int len, part_t *partIds, scalar_t *partSizes, bool makeCopy=true)
Set or reset relative sizes for the parts that Zoltan2 will create.
A PartitioningSolution is a solution to a partitioning problem.
const part_t * getPartListView() const
Returns the part list corresponding to the global ID list.
RCP< const Comm< int > > getComm()
Return the communicator used by the problem.
void resetParameters(ParameterList *params)
Reset the list of parameters.
SparseMatrixAdapter_t::part_t part_t
Zoltan2::EvaluatePartition< matrixAdapter_t > quality_t