3
************************************************************************
5
Isorropia: Partitioning and Load Balancing Package
6
Copyright (2006) Sandia Corporation
8
Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
9
license for use of this work by or on behalf of the U.S. Government.
11
This library is free software; you can redistribute it and/or modify
12
it under the terms of the GNU Lesser General Public License as
13
published by the Free Software Foundation; either version 2.1 of the
14
License, or (at your option) any later version.
16
This library is distributed in the hope that it will be useful, but
17
WITHOUT ANY WARRANTY; without even the implied warranty of
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19
Lesser General Public License for more details.
21
You should have received a copy of the GNU Lesser General Public
22
License along with this library; if not, write to the Free Software
23
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
26
************************************************************************
30
#include <Isorropia_Zoltan_Repartition.hpp>
32
#ifdef HAVE_ISORROPIA_ZOLTAN
35
#error "Isorropia_Zoltan requires MPI."
38
#include <Isorropia_Exception.hpp>
40
#include <Teuchos_RefCountPtr.hpp>
43
#include <Epetra_Map.h>
44
#include <Epetra_RowMatrix.h>
46
#include <Epetra_MpiComm.h>
48
#include <Epetra_CrsGraph.h>
51
#include <QueryObject.hpp>
61
//TODO do we need to add these functions for geometric partitioning?
62
// Are these being used?
65
repartition(Teuchos::RefCountPtr<const Epetra_CrsGraph> input_graph,
66
Teuchos::RefCountPtr<const Isorropia::Epetra::CostDescriber> costs,
67
Teuchos::ParameterList& paramlist,
68
std::vector<int>& myNewElements,
69
std::map<int,int>& exports,
70
std::map<int,int>& imports)
72
int inputType = QueryObject::hgraph_input_;
73
std::string lb_method_str("LB_METHOD");
74
if (paramlist.isParameter(lb_method_str)){
75
std::string lb_meth = paramlist.get(lb_method_str, "HYPERGRAPH");
76
if (lb_meth == "GRAPH"){
77
inputType = QueryObject::graph_input_;
81
Teuchos::RefCountPtr<QueryObject> queryObject =
82
Teuchos::rcp(new QueryObject(input_graph, costs, inputType));
84
const Epetra_Comm &ecomm = input_graph->RowMap().Comm();
86
const Epetra_MpiComm &empicomm = dynamic_cast<const Epetra_MpiComm &>(ecomm);
88
MPI_Comm mpicomm = empicomm.Comm();
90
return( load_balance(mpicomm, paramlist, *queryObject,
91
myNewElements, exports, imports) );
98
repartition(Teuchos::RefCountPtr<const Epetra_RowMatrix> input_matrix,
99
Teuchos::RefCountPtr<const Isorropia::Epetra::CostDescriber> costs,
100
Teuchos::ParameterList& paramlist,
101
std::vector<int>& myNewElements,
102
std::map<int,int>& exports,
103
std::map<int,int>& imports)
105
int inputType = QueryObject::hgraph_input_;
106
std::string lb_method_str("LB_METHOD");
107
if (paramlist.isParameter(lb_method_str)){
108
std::string lb_meth = paramlist.get(lb_method_str, "HYPERGRAPH");
109
if (lb_meth == "GRAPH"){
110
inputType = QueryObject::graph_input_;
114
Teuchos::RefCountPtr<QueryObject> queryObject =
115
Teuchos::rcp(new QueryObject(input_matrix, costs, inputType));
117
const Epetra_Comm &ecomm = input_matrix->RowMatrixRowMap().Comm();
119
const Epetra_MpiComm &empicomm = dynamic_cast<const Epetra_MpiComm &>(ecomm);
121
MPI_Comm mpicomm = empicomm.Comm();
123
return( load_balance(mpicomm, paramlist, *queryObject,
124
myNewElements, exports, imports) );
132
load_balance(MPI_Comm &comm,
133
Teuchos::ParameterList& paramlist,
134
QueryObject& queryObject,
135
std::vector<int>& myNewElements,
136
std::map<int,int>& exports,
137
std::map<int,int>& imports)
143
// create a Zoltan problem
146
Zoltan_Initialize(argcTmp, argvTmp, &version);
148
Zoltan *zz = new Zoltan(comm);
151
throw Isorropia::Exception("Error creating Zoltan object");
155
// set problem parameters
157
std::string dbg_level_str("DEBUG_LEVEL");
158
if (!paramlist.isParameter(dbg_level_str)) {
159
paramlist.set(dbg_level_str, "0");
162
std::string lb_approach_str("LB_APPROACH");
163
if (!paramlist.isParameter(lb_approach_str)) {
164
paramlist.set(lb_approach_str, "PARTITION");
167
std::string lb_method_str("LB_METHOD");
168
std::string lb_meth = paramlist.get(lb_method_str, "HYPERGRAPH");
170
if (!paramlist.isParameter(lb_method_str)) {
171
paramlist.set(lb_method_str, lb_meth); // set to HYPERGRAPH
174
// If no process set vertex weights, let Zoltan default to
175
// unit weights for vertices
177
if (queryObject.haveVertexWeights()) {
178
if (!paramlist.isParameter("OBJ_WEIGHT_DIM")) {
179
paramlist.set("OBJ_WEIGHT_DIM", "1");
183
// If no process set graph or hypergraph edge weights,
184
// let Zoltan default to unit weights for edges
186
if (queryObject.haveGraphEdgeWeights() ||
187
queryObject.haveHypergraphEdgeWeights()) {
188
if (!paramlist.isParameter("EDGE_WEIGHT_DIM")) {
189
paramlist.set("EDGE_WEIGHT_DIM", "1");
193
Teuchos::ParameterList::ConstIterator
194
iter = paramlist.begin(),
195
iter_end = paramlist.end();
197
for(; iter != iter_end; ++iter) {
198
const std::string& name = iter->first;
199
const std::string& value = Teuchos::getValue<std::string>(iter->second);
200
zz->Set_Param(name, value);
203
// Set the query functions
205
zz->Set_Num_Obj_Fn(QueryObject::Number_Objects, (void *)&queryObject);
206
zz->Set_Obj_List_Fn(QueryObject::Object_List, (void *)&queryObject);
208
if (lb_meth == "HYPERGRAPH"){
209
zz->Set_HG_Size_CS_Fn(QueryObject::HG_Size_CS, (void *)&queryObject);
210
zz->Set_HG_CS_Fn(QueryObject::HG_CS, (void *)&queryObject);
211
zz->Set_HG_Size_Edge_Wts_Fn(QueryObject::HG_Size_Edge_Weights ,
212
(void *)&queryObject);
213
zz->Set_HG_Edge_Wts_Fn(QueryObject::HG_Edge_Weights, (void *)&queryObject);
216
zz->Set_Num_Edges_Multi_Fn(QueryObject::Number_Edges_Multi, (void *)&queryObject);
217
zz->Set_Edge_List_Multi_Fn(QueryObject::Edge_List_Multi, (void *)&queryObject);
220
//Generate Load Balance
221
int changes, num_gid_entries, num_lid_entries, num_import, num_export;
222
ZOLTAN_ID_PTR import_global_ids, import_local_ids;
223
ZOLTAN_ID_PTR export_global_ids, export_local_ids;
224
int * import_procs, * export_procs;
225
int *import_to_part, *export_to_part;
227
int err = zz->LB_Partition(changes, num_gid_entries, num_lid_entries,
228
num_import, import_global_ids, import_local_ids, import_procs, import_to_part,
229
num_export, export_global_ids, export_local_ids, export_procs, export_to_part );
231
if (err != ZOLTAN_OK){
232
throw Isorropia::Exception("Error computing partitioning with Zoltan");
236
//Generate New Element List
237
int numMyElements = queryObject.RowMap().NumMyElements();
238
std::vector<int> elementList( numMyElements );
239
queryObject.RowMap().MyGlobalElements( &elementList[0] );
241
int newNumMyElements = numMyElements - num_export + num_import;
242
myNewElements.resize( newNumMyElements );
244
for( int i = 0; i < num_export; ++i ) {
245
exports[export_global_ids[i]] = export_procs[i];
248
for( int i = 0; i < num_import; ++i ) {
249
imports[import_global_ids[i]] = import_procs[i];
252
//Add unmoved indices to new list
254
for( int i = 0; i < numMyElements; ++i ) {
255
if( !exports.count( elementList[i] ) ) {
256
myNewElements[loc++] = elementList[i];
260
//Add imports to end of list
261
for( int i = 0; i < num_import; ++i ) {
262
myNewElements[loc+i] = import_global_ids[i];
266
zz->LB_Free_Part(&import_global_ids, &import_local_ids,
267
&import_procs, &import_to_part);
268
zz->LB_Free_Part(&export_global_ids, &export_local_ids,
269
&export_procs, &export_to_part);
277
}//namespace ZoltanLib
279
}//namespace Isorropia