#include <Isorropia_Exception.hpp>
#include <Isorropia_Epetra.hpp>
#include <Teuchos_ParameterList.hpp>
#ifdef HAVE_MPI
#include <mpi.h>
#endif
#ifdef HAVE_EPETRA
#ifdef HAVE_MPI
#include <Epetra_MpiComm.h>
#else
#include <Epetra_SerialComm.h>
#endif
#include <Epetra_Map.h>
#include <Epetra_CrsMatrix.h>
#endif
#ifdef HAVE_EPETRA
Teuchos::RCP<Epetra_CrsGraph>
create_epetra_graph(int numProcs, int localProc);
Teuchos::RCP<Epetra_CrsMatrix>
create_epetra_matrix(int numProcs, int localProc);
#endif
int main(int argc, char** argv) {
#if defined(HAVE_MPI) && defined(HAVE_EPETRA)
int p, numProcs = 1;
int localProc = 0;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &localProc);
MPI_Comm_size(MPI_COMM_WORLD, &numProcs);
Teuchos::RCP<Epetra_CrsGraph> crsgraph;
try {
crsgraph = create_epetra_graph(numProcs, localProc);
}
catch(std::exception& exc) {
std::cout << "matrix_1 example: create_epetra_graph threw exception '"
<< exc.what() << "' on proc " << localProc << std::endl;
MPI_Finalize();
return(-1);
}
if (localProc == 0) {
std::cout << " calling Isorropia::create_balanced_copy..." << std::endl;
}
Teuchos::ParameterList paramlist;
Teuchos::RCP<Epetra_CrsGraph> balanced_graph;
try {
balanced_graph =
Isorropia::Epetra::create_balanced_copy(*crsgraph, paramlist);
}
catch(std::exception& exc) {
std::cout << "matrix_1 example: Isorropia::create_balanced_copy threw "
<< "exception '" << exc.what() << "' on proc "
<< localProc << std::endl;
MPI_Finalize();
return(-1);
}
int graphrows1 = crsgraph->NumMyRows();
int bal_graph_rows = balanced_graph->NumMyRows();
int graphnnz1 = crsgraph->NumMyNonzeros();
int bal_graph_nnz = balanced_graph->NumMyNonzeros();
for(p=0; p<numProcs; ++p) {
MPI_Barrier(MPI_COMM_WORLD);
if (p != localProc) continue;
std::cout << "proc " << p << ": input graph local rows: " << graphrows1
<< ", local NNZ: " << graphnnz1 << std::endl;
}
for(p=0; p<numProcs; ++p) {
MPI_Barrier(MPI_COMM_WORLD);
if (p != localProc) continue;
std::cout << "proc " << p << ": balanced graph local rows: "
<< bal_graph_rows << ", local NNZ: " << bal_graph_nnz << std::endl;
}
if (localProc == 0) {
std::cout << std::endl;
}
Teuchos::RCP<Epetra_CrsMatrix> crsmatrix;
try {
crsmatrix = create_epetra_matrix(numProcs, localProc);
}
catch(std::exception& exc) {
std::cout << "matrix_1 example: create_epetra_matrix threw exception '"
<< exc.what() << "' on proc " << localProc << std::endl;
MPI_Finalize();
return(-1);
}
#ifdef HAVE_ISORROPIA_ZOLTAN
Teuchos::ParameterList& sublist = paramlist.sublist("Zoltan");
sublist.set("LB_METHOD", "GRAPH");
#else
#endif
if (localProc == 0) {
std::cout << " calling Isorropia::Epetra::create_balanced_copy...\n"
<< "Specifying GRAPH partitioning."
<< std::endl;
}
Teuchos::RCP<Epetra_CrsMatrix> balanced_matrix;
try {
balanced_matrix =
Isorropia::Epetra::create_balanced_copy(*crsmatrix, paramlist);
}
catch(std::exception& exc) {
std::cout << "matrix_1 example: Isorropia::create_balanced_copy(matrix)"
<< " threw exception '" << exc.what() << "' on proc "
<< localProc << std::endl;
MPI_Finalize();
return(-1);
}
int matrows1 = crsmatrix->NumMyRows();
int bal_mat_rows = balanced_matrix->NumMyRows();
int matnnz1 = crsmatrix->NumMyNonzeros();
int bal_mat_nnz = balanced_matrix->NumMyNonzeros();
for(p=0; p<numProcs; ++p) {
MPI_Barrier(MPI_COMM_WORLD);
if (p != localProc) continue;
std::cout << "proc " << p << ": input matrix local rows: " << matrows1
<< ", local NNZ: " << matnnz1 << std::endl;
}
for(p=0; p<numProcs; ++p) {
MPI_Barrier(MPI_COMM_WORLD);
if (p != localProc) continue;
std::cout << "proc " << p << ": balanced matrix local rows: "
<< bal_mat_rows << ", local NNZ: " << bal_mat_nnz << std::endl;
}
MPI_Finalize();
#else
std::cout << "matrix_1: must have both MPI and EPETRA. Make sure Trilinos "
<< "is configured with --enable-mpi and --enable-epetra." << std::endl;
#endif
return(0);
}
#if defined(HAVE_MPI) && defined(HAVE_EPETRA)
Teuchos::RCP<Epetra_CrsMatrix>
create_epetra_matrix(int numProcs, int localProc)
{
if (localProc == 0) {
std::cout << " creating Epetra_CrsMatrix with un-even distribution..."
<< std::endl;
}
Epetra_MpiComm comm(MPI_COMM_WORLD);
int local_num_rows = 200;
int nnz_per_row = local_num_rows/4+1;
int global_num_rows = numProcs*local_num_rows;
int mid_proc = numProcs/2;
bool num_procs_even = numProcs%2==0 ? true : false;
int adjustment = local_num_rows/2;
if (localProc < mid_proc) {
local_num_rows -= adjustment;
}
else {
local_num_rows += adjustment;
}
if (localProc == numProcs-1) {
if (num_procs_even == false) {
local_num_rows -= adjustment;
}
}
Epetra_Map rowmap(global_num_rows, local_num_rows, 0, comm);
Teuchos::RCP<Epetra_CrsMatrix> matrix =
Teuchos::rcp(new Epetra_CrsMatrix(Copy, rowmap, nnz_per_row));
std::vector<int> indices(nnz_per_row);
std::vector<double> coefs(nnz_per_row);
int err = 0;
for(int i=0; i<local_num_rows; ++i) {
int global_row = rowmap.GID(i);
int first_col = global_row - nnz_per_row/2;
if (first_col < 0) {
first_col = 0;
}
else if (first_col > (global_num_rows - nnz_per_row)) {
first_col = global_num_rows - nnz_per_row;
}
for(int j=0; j<nnz_per_row; ++j) {
indices[j] = first_col + j;
coefs[j] = 1.0;
}
int err = matrix->InsertGlobalValues(global_row, nnz_per_row,
&coefs[0], &indices[0]);
if (err < 0) {
err = matrix->ReplaceGlobalValues(global_row, nnz_per_row,
&coefs[0], &indices[0]);
if (err < 0) {
throw Isorropia::Exception("create_epetra_matrix: error inserting matrix values.");
}
}
}
err = matrix->FillComplete();
if (err != 0) {
throw Isorropia::Exception("create_epetra_matrix: error in matrix.FillComplete()");
}
return(matrix);
}
Teuchos::RCP<Epetra_CrsGraph>
create_epetra_graph(int numProcs, int localProc)
{
if (localProc == 0) {
std::cout << " creating Epetra_CrsGraph with un-even distribution..."
<< std::endl;
}
Epetra_MpiComm comm(MPI_COMM_WORLD);
int local_num_rows = 800;
int nnz_per_row = local_num_rows/4+1;
int global_num_rows = numProcs*local_num_rows;
int mid_proc = numProcs/2;
bool num_procs_even = numProcs%2==0 ? true : false;
int adjustment = local_num_rows/2;
if (localProc < mid_proc) {
local_num_rows -= adjustment;
}
else {
local_num_rows += adjustment;
}
if (localProc == numProcs-1) {
if (num_procs_even == false) {
local_num_rows -= adjustment;
}
}
Epetra_Map rowmap(global_num_rows, local_num_rows, 0, comm);
Teuchos::RCP<Epetra_CrsGraph> graph =
Teuchos::rcp(new Epetra_CrsGraph(Copy, rowmap, nnz_per_row));
std::vector<int> indices(nnz_per_row);
std::vector<double> coefs(nnz_per_row);
int err = 0;
for(int i=0; i<local_num_rows; ++i) {
int global_row = rowmap.GID(i);
int first_col = global_row - nnz_per_row/2;
if (first_col < 0) {
first_col = 0;
}
else if (first_col > (global_num_rows - nnz_per_row)) {
first_col = global_num_rows - nnz_per_row;
}
for(int j=0; j<nnz_per_row; ++j) {
indices[j] = first_col + j;
coefs[j] = 1.0;
}
err = graph->InsertGlobalIndices(global_row, nnz_per_row,
&indices[0]);
if (err < 0) {
throw Isorropia::Exception("create_epetra_graph: error inserting indices in graph");
}
}
err = graph->FillComplete();
if (err != 0) {
throw Isorropia::Exception("create_epetra_graph: error in graph.FillComplete()");
}
return(graph);
}
#endif //HAVE_MPI && HAVE_EPETRA