Zoltan is added as thirdParty package

This commit is contained in:
Hamidreza
2025-05-15 21:58:43 +03:30
parent 83a6e4baa1
commit d7479cf1bd
3392 changed files with 318142 additions and 1 deletions

64
thirdParty/Zoltan/src/tpls/README vendored Normal file
View File

@ -0,0 +1,64 @@
# @HEADER
#
########################################################################
#
# Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
# Copyright 2012 Sandia Corporation
#
# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
# the U.S. Government retains certain rights in this software.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the Corporation nor the names of the
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Questions? Contact Karen Devine kddevin@sandia.gov
# Erik Boman egboman@sandia.gov
#
########################################################################
#
# @HEADER
PARMETIS DIRECTORY -- Routines to providing the interface to the
ParMETIS and Jostle libraries.
----------------------------------------------------------------
Files compiled into Zoltan:
parmetis_jostle_const.h -- Prototypes and definitions.
parmetis_jostle.c -- Routines to interpret parameters,
build the necessary data structures,
call the appropriate libraries,
and create the Zoltan return lists.
verify_graph.c -- Routines to verify the correctness of a graph.
scatter_graph.c -- Routines to scatter a ParMetis-style graph to all
processors.
build_graph.c -- Build ParMETIS/Jostle graph data structure.

167
thirdParty/Zoltan/src/tpls/build_graph.c vendored Normal file
View File

@ -0,0 +1,167 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
#include <ctype.h>
#include "zz_const.h"
#include "zz_util_const.h"
#include "all_allo_const.h"
#include "params_const.h"
#include "graph.h"
int Zoltan_Build_Graph(ZZ *zz, int *graph_type, int check_graph,
int num_obj, ZOLTAN_ID_PTR global_ids, ZOLTAN_ID_PTR local_ids,
int obj_wgt_dim, int * edge_wgt_dim,
ZOLTAN_GNO_TYPE **vtxdist, int **xadj, ZOLTAN_GNO_TYPE **adjncy, float **ewgts,
int **adjproc)
{
int ierr = ZOLTAN_OK;
int local;
int my_num_obj;
ZOLTAN_GNO_TYPE glb_obj;
int my_obj_wgt_dim;
ZG graph;
local = IS_LOCAL_GRAPH(*graph_type);
ierr = Zoltan_ZG_Build (zz, &graph, local, 0,0,NULL,NULL); /* Normal graph */
ierr = Zoltan_ZG_Export (zz, &graph,
&glb_obj, &my_num_obj, &my_obj_wgt_dim, edge_wgt_dim,
vtxdist, xadj, adjncy, adjproc,
ewgts, NULL);
graph.mtx.mtx.pinwgt = NULL;
graph.mtx.mtx.ystart = NULL;
graph.mtx.mtx.yend = NULL;
graph.mtx.mtx.pinGNO = NULL;
graph.mtx.dist_y = NULL;
Zoltan_ZG_Free(&graph);
return (ierr);
}
/**************************************************************************/
int Zoltan_Get_Num_Edges_Per_Obj(
ZZ *zz,
int num_obj,
ZOLTAN_ID_PTR global_ids,
ZOLTAN_ID_PTR local_ids,
int **edges_per_obj,
int *max_edges,
int *num_edges
)
{
/* Calls ZOLTAN_NUM_EDGE_FN or ZOLTAN_NUM_EDGE_MULTI_FN to obtain number
* of edges per object.
* Returns number of edges per object in array edges_per_obj.
* Computes max edges per obj and total edges per obj.
*/
static char *yo = "Zoltan_Get_Num_Edges_Per_Obj";
int ierr = ZOLTAN_OK;
int i;
int nedges;
int num_gid_entries = zz->Num_GID;
int num_lid_entries = zz->Num_LID;
ZOLTAN_ID_PTR lid;
*max_edges = *num_edges = 0;
if (num_obj) {
*edges_per_obj = (int *) ZOLTAN_MALLOC(num_obj * sizeof(int));
if (*edges_per_obj == NULL) {
ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Memory error.");
ierr = ZOLTAN_MEMERR;
goto End;
}
if (zz->Get_Num_Edges_Multi) {
zz->Get_Num_Edges_Multi(zz->Get_Num_Edges_Multi_Data,
num_gid_entries, num_lid_entries, num_obj,
global_ids, local_ids, *edges_per_obj, &ierr);
if (ierr) {
ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Error in Get_Num_Edges_Multi.");
goto End;
}
for (i = 0; i < num_obj; i++) {
nedges = (*edges_per_obj)[i];
*num_edges += nedges;
if (nedges > *max_edges) *max_edges = nedges;
}
}
else {
for (i=0; i< num_obj; i++) {
lid = (num_lid_entries ? &(local_ids[i*num_lid_entries]) : NULL);
nedges = zz->Get_Num_Edges(zz->Get_Num_Edges_Data,
num_gid_entries, num_lid_entries,
&(global_ids[i*num_gid_entries]),
lid, &ierr);
if (ierr) {
/* Return error */
ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Error in Get_Num_Edges.");
goto End;
}
*num_edges += nedges;
if (nedges > *max_edges) *max_edges = nedges;
(*edges_per_obj)[i] = nedges;
}
}
}
End:
return ierr;
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

72
thirdParty/Zoltan/src/tpls/graph_util.h vendored Normal file
View File

@ -0,0 +1,72 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifndef __COMMON_H
#define __COMMON_H
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
#include "zoltan_util.h"
#include "third_library_const.h"
extern int Zoltan_Verify_Graph(MPI_Comm, indextype *, indextype *,
indextype *, weighttype *, weighttype *,
int, int, int, int, int);
extern int Zoltan_Scatter_Graph(indextype **, indextype **,
indextype **, weighttype **, indextype **, weighttype **,
realtype **, int, int, ZZ *, ZOLTAN_COMM_OBJ **);
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif
#endif

View File

@ -0,0 +1,901 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
#include <ctype.h>
#include "zz_const.h"
#include "zz_util_const.h"
#include "all_allo_const.h"
#include "params_const.h"
#include "order_const.h"
#include "third_library.h"
#include "parmetis_interface.h"
#include "parmetis_interface_params.h"
/*********** COMPATIBILITY CHECKING AT COMPILE TIME ************/
#ifdef ZOLTAN_PARMETIS
#if (PARMETIS_MAJOR_VERSION < 3)
#error "Specified version of ParMETIS is not compatible with Zoltan; upgrade to ParMETIS v3.1 or later, or build Zoltan without ParMETIS."
#endif
#if (PARMETIS_MAJOR_VERSION == 3) && (PARMETIS_MINOR_VERSION < 1)
#error "Specified version of ParMETIS is not compatible with Zoltan; upgrade to ParMETIS v3.1 or later, or build Zoltan without ParMETIS."
#endif
/********** Workaround for memory bug in ParMETIS 3.1.0 **********/
#ifndef PARMETIS_SUBMINOR_VERSION
#define PARMETIS_SUBMINOR_VERSION 0
#endif
#if (PARMETIS_MAJOR_VERSION == 3) && (PARMETIS_MINOR_VERSION == 1) && (PARMETIS_SUBMINOR_VERSION == 0)
#define PARMETIS31_ALWAYS_FREES_VSIZE
#endif
#endif
static int pmv3method(char *alg);
static int mylog2(int x)
{
int i = 0;
for (i=0 ; (1<<i) <= x ; ++i);
return (i-1);
}
static int Zoltan_Parmetis_Parse(ZZ*, indextype *, char*, realtype*, double *,
ZOLTAN_Output_Order*);
/**********************************************************/
/* Interface routine for ParMetis: Partitioning */
/**********************************************************/
int Zoltan_ParMetis(
ZZ *zz, /* Zoltan structure */
float *part_sizes, /* Input: Array of size zz->Num_Global_Parts
containing the percentage of work to be
assigned to each partition. */
int *num_imp, /* number of objects to be imported */
ZOLTAN_ID_PTR *imp_gids, /* global ids of objects to be imported */
ZOLTAN_ID_PTR *imp_lids, /* local ids of objects to be imported */
int **imp_procs, /* list of processors to import from */
int **imp_to_part, /* list of partitions to which imported objects are
assigned. */
int *num_exp, /* number of objects to be exported */
ZOLTAN_ID_PTR *exp_gids, /* global ids of objects to be exported */
ZOLTAN_ID_PTR *exp_lids, /* local ids of objects to be exported */
int **exp_procs, /* list of processors to export to */
int **exp_to_part /* list of partitions to which exported objects are
assigned. */
)
{
char *yo = "Zoltan_ParMetis";
int ierr;
ZOLTAN_Third_Graph gr;
ZOLTAN_Third_Geom *geo = NULL;
ZOLTAN_Third_Vsize vsp;
ZOLTAN_Third_Part prt;
ZOLTAN_Output_Part part;
ZOLTAN_ID_PTR global_ids = NULL;
ZOLTAN_ID_PTR local_ids = NULL;
int use_timers = 0;
int timer_p = -1;
int get_times = 0;
double times[5];
double pmv3_itr = 0.0;
realtype itr = 0.0;
indextype options[MAX_PARMETIS_OPTIONS];
char alg[MAX_PARAM_STRING_LEN];
#ifdef ZOLTAN_PARMETIS
MPI_Comm comm = zz->Communicator;/* don't risk letting external packages */
/* change our zz struct. */
#endif
indextype i;
realtype *imb_tols;
indextype ncon;
indextype edgecut;
indextype wgtflag;
indextype numflag = 0;
indextype num_part = zz->LB.Num_Global_Parts; /* passed to ParMETIS. */
ZOLTAN_TRACE_ENTER(zz, yo);
Zoltan_Third_Init(&gr, &prt, &vsp, &part,
imp_gids, imp_lids, imp_procs, imp_to_part,
exp_gids, exp_lids, exp_procs, exp_to_part);
if (sizeof(realtype) != sizeof(float)) {
int tmp = zz->LB.Num_Global_Parts * MAX(zz->Obj_Weight_Dim, 1);
prt.input_part_sizes = (realtype *) ZOLTAN_MALLOC(tmp * sizeof(realtype));
for (i = 0; i < tmp; i++)
prt.input_part_sizes[i] = (realtype) part_sizes[i];
/* KDD 2/2014: removed re-scaling part sizes so they sum to one.
* part_sizes are already scaled in Zoltan_LB_Get_Part_Sizes.
* plus, the code here was wrong for multiple object weights.
* similar scaling code did not exist in the Scotch interface.
*/
prt.part_sizes = prt.input_part_sizes;
}
else
prt.input_part_sizes = prt.part_sizes = (realtype *) part_sizes;
ierr = Zoltan_Parmetis_Parse(zz, options, alg, &itr, &pmv3_itr, NULL);
if ((ierr != ZOLTAN_OK) && (ierr != ZOLTAN_WARN)) {
Zoltan_Third_Exit(&gr, geo, &prt, &vsp, &part, NULL);
return (ierr);
}
gr.graph_type = 0;
#ifdef ZOLTAN_PARMETIS
SET_GLOBAL_GRAPH(&gr.graph_type);
/* Select type of graph, negative because we impose them */
/* TODO: add a parameter to select the type, shared with Scotch */
/* if (strcmp (graph_type, "GLOBAL") != 0) { */
/* gr.graph_type = - LOCAL_GRAPH; */
/* if (zz->Num_Proc > 1) { */
/* ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Distributed graph: cannot call METIS, switching to ParMetis"); */
/* gr.graph_type = - GLOBAL_GRAPH; */
/* retval = ZOLTAN_WARN; */
/* } */
/* } */
#else /* graph is local */
SET_LOCAL_GRAPH(&gr.graph_type);
#endif /* ZOLTAN_PARMETIS */
/* Some algorithms use geometry data */
if (strncmp(alg, "PARTGEOM", 8) == 0){ /* PARTGEOM & PARTGEOMKWAY */
geo = (ZOLTAN_Third_Geom*) ZOLTAN_MALLOC(sizeof(ZOLTAN_Third_Geom));
memset (geo, 0, sizeof(ZOLTAN_Third_Geom));
/* ParMETIS will crash if geometric method and some procs have no nodes. */
/* Avoid fatal crash by setting scatter to level 2 or higher. */
gr.scatter_min = 2;
if (geo == NULL) {
ZOLTAN_PRINT_ERROR (zz->Proc, yo, "Out of memory.");
return (ZOLTAN_MEMERR);
}
if (strcmp(alg, "PARTGEOM") == 0) {
gr.get_data = 0;
}
}
timer_p = Zoltan_Preprocess_Timer(zz, &use_timers);
/* Start timer */
get_times = (zz->Debug_Level >= ZOLTAN_DEBUG_ATIME);
if (get_times){
MPI_Barrier(zz->Communicator);
times[0] = Zoltan_Time(zz->Timer);
}
vsp.vsize_malloc = 0;
#ifdef PARMETIS31_ALWAYS_FREES_VSIZE
if (!strcmp(alg, "ADAPTIVEREPART") && (zz->Num_Proc > 1)) {
/* ParMETIS will free this memory; use malloc to allocate so
ZOLTAN_MALLOC counters don't show an error. */
vsp.vsize_malloc = 1 ;
}
#endif /* PARMETIS31_ALWAYS_FREES_VSIZE */
ierr = Zoltan_Preprocess_Graph(zz, &global_ids, &local_ids, &gr,
geo, &prt, &vsp);
if ((ierr != ZOLTAN_OK) && (ierr != ZOLTAN_WARN)) {
Zoltan_Third_Exit(&gr, geo, &prt, &vsp, &part, NULL);
return (ierr);
}
/* Get object sizes if requested */
if (options[PMV3_OPT_USE_OBJ_SIZE] &&
(zz->Get_Obj_Size || zz->Get_Obj_Size_Multi) &&
(!strcmp(alg, "ADAPTIVEREPART") || gr.final_output))
gr.showMoveVol = 1;
/* Get a time here */
if (get_times) times[1] = Zoltan_Time(zz->Timer);
/* Get ready to call ParMETIS */
edgecut = -1;
wgtflag = 2*(gr.obj_wgt_dim>0) + (gr.edge_wgt_dim>0);
numflag = 0;
ncon = (gr.obj_wgt_dim > 0 ? gr.obj_wgt_dim : 1);
if (!prt.part_sizes){
ZOLTAN_THIRD_ERROR(ZOLTAN_FATAL,"Input parameter part_sizes is NULL.");
}
if ((zz->Proc == 0) && (zz->Debug_Level >= ZOLTAN_DEBUG_ALL)) {
for (i=0; i<num_part; i++){
indextype j;
printf("Debug: Size(s) for part " TPL_IDX_SPEC " = ", i);
for (j=0; j<ncon; j++)
printf("%f ", prt.part_sizes[i*ncon+j]);
printf("\n");
}
}
/* if (strcmp(alg, "ADAPTIVEREPART") == 0) */
for (i = 0; i < num_part*ncon; i++)
if (prt.part_sizes[i] == 0)
ZOLTAN_THIRD_ERROR(ZOLTAN_FATAL, "Zero-sized part(s) requested! "
"ParMETIS 3.x will likely fail. Please use a "
"different method, or remove the zero-sized "
"parts from the problem.");
/* Set Imbalance Tolerance for each weight component. */
imb_tols = (realtype *) ZOLTAN_MALLOC(ncon * sizeof(realtype));
if (!imb_tols){
/* Not enough memory */
ZOLTAN_THIRD_ERROR(ZOLTAN_MEMERR, "Out of memory.");
}
for (i=0; i<ncon; i++)
imb_tols[i] = (realtype) (zz->LB.Imbalance_Tol[i]);
/* Now we can call ParMetis */
/* Zoltan_Third_Graph_Print(zz, &gr, "Before calling parmetis"); */
#ifdef ZOLTAN_PARMETIS
if (!IS_LOCAL_GRAPH(gr.graph_type)) { /* May be GLOBAL or NO GRAPH */
/* First check for ParMetis 3 routines */
if (strcmp(alg, "PARTKWAY") == 0){
ZOLTAN_TRACE_DETAIL(zz, yo, "Calling the ParMETIS library "
"ParMETIS_V3_PartKway");
ParMETIS_V3_PartKway(gr.vtxdist, gr.xadj, gr.adjncy, gr.vwgt, gr.ewgts,
&wgtflag, &numflag, &ncon, &num_part, prt.part_sizes,
imb_tols, options, &edgecut, prt.part, &comm);
ZOLTAN_TRACE_DETAIL(zz, yo, "Returned from the ParMETIS library");
}
else if (strcmp(alg, "PARTGEOMKWAY") == 0){
indextype ndims = geo->ndims;
ZOLTAN_TRACE_DETAIL(zz, yo, "Calling the ParMETIS library "
"ParMETIS_V3_PartGeomKway");
ParMETIS_V3_PartGeomKway(gr.vtxdist, gr.xadj, gr.adjncy, gr.vwgt,gr.ewgts,
&wgtflag, &numflag, &ndims, geo->xyz, &ncon,
&num_part, prt.part_sizes,
imb_tols, options, &edgecut, prt.part, &comm);
ZOLTAN_TRACE_DETAIL(zz, yo, "Returned from the ParMETIS library");
}
else if (strcmp(alg, "PARTGEOM") == 0){
indextype ndims = geo->ndims;
ZOLTAN_TRACE_DETAIL(zz, yo, "Calling the ParMETIS library "
"ParMETIS_V3_PartGeom");
ParMETIS_V3_PartGeom(gr.vtxdist, &ndims, geo->xyz, prt.part, &comm);
ZOLTAN_TRACE_DETAIL(zz, yo, "Returned from the ParMETIS library");
}
else if (strcmp(alg, "ADAPTIVEREPART") == 0){
ZOLTAN_TRACE_DETAIL(zz, yo, "Calling the ParMETIS library "
"ParMETIS_V3_AdaptiveRepart");
ParMETIS_V3_AdaptiveRepart(gr.vtxdist, gr.xadj, gr.adjncy, gr.vwgt,
vsp.vsize, gr.ewgts, &wgtflag, &numflag, &ncon,
&num_part, prt.part_sizes, imb_tols,
&itr, options, &edgecut, prt.part, &comm);
ZOLTAN_TRACE_DETAIL(zz, yo, "Returned from the ParMETIS library");
}
else if (strcmp(alg, "REFINEKWAY") == 0){
ZOLTAN_TRACE_DETAIL(zz, yo, "Calling the ParMETIS library "
"ParMETIS_V3_RefineKway");
ParMETIS_V3_RefineKway(gr.vtxdist, gr.xadj, gr.adjncy, gr.vwgt, gr.ewgts,
&wgtflag, &numflag, &ncon, &num_part,
prt.part_sizes, imb_tols,
options, &edgecut, prt.part, &comm);
ZOLTAN_TRACE_DETAIL(zz, yo, "Returned from the ParMETIS library");
}
else {
/* Sanity check: This should never happen! */
char msg[256];
sprintf(msg, "Unknown ParMetis algorithm %s.", alg);
ZOLTAN_THIRD_ERROR(ZOLTAN_FATAL, msg);
}
}
#endif /* ZOLTAN_PARMETIS */
#ifdef ZOLTAN_METIS
/* TODO: I don't know how to set balance ! */
if (IS_LOCAL_GRAPH(gr.graph_type)) {
/* Check for Metis routines */
if (strcmp(alg, "PARTKWAY") == 0){
ZOLTAN_TRACE_DETAIL(zz, yo, "Calling the METIS library ");
/* Use default options for METIS */
#if !defined(METIS_VER_MAJOR) || METIS_VER_MAJOR < 5
options[0] = 0;
METIS_WPartGraphKway (gr.vtxdist+1, gr.xadj, gr.adjncy,
gr.vwgt, gr.ewgts, &wgtflag,
&numflag, &num_part, prt.part_sizes,
options, &edgecut, prt.part);
#else
METIS_SetDefaultOptions(options);
METIS_PartGraphKway (gr.vtxdist+1, &ncon, gr.xadj, gr.adjncy,
gr.vwgt, vsp.vsize, gr.ewgts, &num_part,
prt.part_sizes, imb_tols, options,
&edgecut, prt.part);
#endif
ZOLTAN_TRACE_DETAIL(zz, yo, "Returned from the METIS library");
}
else {
/* Sanity check: This should never happen! */
char msg[256];
sprintf(msg, "Unknown Metis algorithm %s.", alg);
ZOLTAN_THIRD_ERROR(ZOLTAN_FATAL, msg);
}
}
#endif /* ZOLTAN_METIS */
/* Get a time here */
if (get_times) times[2] = Zoltan_Time(zz->Timer);
if (gr.final_output) {
/* Do final output now because after the data will not be coherent:
unscatter only unscatter part data, not graph */
ierr = Zoltan_Postprocess_FinalOutput (zz, &gr, &prt, &vsp, use_timers, itr);
}
/* Ignore the timings of Final Ouput */
if (get_times) times[3] = Zoltan_Time(zz->Timer);
ierr = Zoltan_Postprocess_Graph(zz, global_ids, local_ids, &gr,
geo, &prt, &vsp, NULL, &part);
Zoltan_Third_Export_User(&part,
num_imp, imp_gids, imp_lids, imp_procs, imp_to_part,
num_exp, exp_gids, exp_lids, exp_procs, exp_to_part);
/* Get a time here */
if (get_times) times[4] = Zoltan_Time(zz->Timer);
if (get_times) Zoltan_Third_DisplayTime(zz, times);
if (use_timers && timer_p >= 0)
ZOLTAN_TIMER_STOP(zz->ZTime, timer_p, zz->Communicator);
Zoltan_Third_Exit(&gr, geo, &prt, &vsp, NULL, NULL);
if (imb_tols != NULL) ZOLTAN_FREE(&imb_tols);
if (geo != NULL) ZOLTAN_FREE(&geo);
ZOLTAN_FREE(&global_ids);
ZOLTAN_FREE(&local_ids);
ZOLTAN_TRACE_EXIT(zz, yo);
return (ierr);
}
static int Zoltan_Parmetis_Parse(
ZZ* zz,
indextype *options,
char* alg,
realtype* itr,
double *pmv3_itr,
ZOLTAN_Output_Order *ord
)
{
static char * yo = "Zoltan_Parmetis_Parse";
int i;
int output_level, seed, coarse_alg, fold, use_obj_size;
/* Always use ParMetis option array because Zoltan by default
produces no output (silent mode). ParMetis requires options[0]=1
when options array is to be used. */
options[0] = 1;
for (i = 1; i < MAX_PARMETIS_OPTIONS; i++)
options[i] = 0;
/* Set the default option values. */
output_level = 0;
coarse_alg = 2;
use_obj_size = 1;
fold = 0;
seed = GLOBAL_SEED;
if(ord == NULL) {
/* Map LB_APPROACH to suitable PARMETIS_METHOD */
if (!strcasecmp(zz->LB.Approach, "partition")){
strcpy(alg, "PARTKWAY");
}
else if (!strcasecmp(zz->LB.Approach, "repartition")){
strcpy(alg, "ADAPTIVEREPART");
*pmv3_itr = 100.; /* Ratio of inter-proc comm. time to data redist. time;
100 gives similar partition quality to GDiffusion */
}
else if (!strcasecmp(zz->LB.Approach, "refine")){
strcpy(alg, "REFINEKWAY");
}
else { /* If no LB_APPROACH is set, use repartition */
strcpy(alg, "ADAPTIVEREPART");
*pmv3_itr = 100.; /* Ratio of inter-proc comm. time to data redist. time;
100 gives similar partition quality to GDiffusion */
}
}
else {
strcpy(alg, "NODEND");
}
Zoltan_Bind_Param(Parmetis_params, "PARMETIS_METHOD",
(void *) alg);
Zoltan_Bind_Param(Parmetis_params, "PARMETIS_OUTPUT_LEVEL",
(void *) &output_level);
Zoltan_Bind_Param(Parmetis_params, "PARMETIS_SEED",
(void *) &seed);
Zoltan_Bind_Param(Parmetis_params, "PARMETIS_ITR",
(void *) pmv3_itr);
Zoltan_Bind_Param(Parmetis_params, "PARMETIS_COARSE_ALG",
(void *) &coarse_alg);
Zoltan_Bind_Param(Parmetis_params, "PARMETIS_FOLD",
(void *) &fold);
Zoltan_Assign_Param_Vals(zz->Params, Parmetis_params, zz->Debug_Level,
zz->Proc, zz->Debug_Proc);
/* Copy option values to ParMetis options array */
/* In this version of Zoltan, processors and partitions are coupled. */
/* This will likely change in future releases, and then the options */
/* value should change to DISCOUPLED. */
options[PMV3_OPTION_PSR] = COUPLED;
if (pmv3method(alg)){
/* ParMetis 3.0 options */
options[PMV3_OPTION_DBGLVL] = output_level;
options[PMV3_OPTION_SEED] = seed;
options[PMV3_OPT_USE_OBJ_SIZE] = use_obj_size;
if (ord == NULL)
*itr = (realtype)*pmv3_itr;
}
/* If ordering, use ordering method instead of load-balancing method */
if (ord && ord->order_opt){
strcpy(alg, ord->order_opt->method);
}
if ((zz->Num_Proc == 1) &&
(!strcmp(alg, "ADAPTIVEREPART") ||
!strcmp(alg, "REPARTLDIFFUSION") ||
!strcmp(alg, "REPARTGDIFFUSION") ||
!strcmp(alg, "REPARTREMAP") ||
!strcmp(alg, "REPARTMLREMAP"))) {
/* These ParMETIS methods fail on one processor; an MPI command assumes
at least two processors. */
char str[256];
sprintf(str, "ParMETIS method %s fails on one processor due to a bug"
" in ParMETIS v3.x; resetting method to PartKway.", alg);
ZOLTAN_PRINT_WARN(zz->Proc, yo, str);
strcpy(alg, "PARTKWAY");
return (ZOLTAN_WARN);
}
return(ZOLTAN_OK);
}
/***************************************************************************/
static int pmv3method( char *alg)
{
/* Check if alg is a supported ParMetis 3.0 method */
return ((!strcmp(alg, "PARTKWAY"))
|| (!strcmp(alg, "PARTGEOMKWAY"))
|| (!strcmp(alg, "ADAPTIVEREPART"))
|| (!strcmp(alg, "REFINEKWAY"))
|| (!strcmp(alg, "NODEND"))
);
}
/***************************************************************************
* The ParMetis ordering routine piggy-backs on the ParMetis
* partitioning routines.
**************************************************************************/
int Zoltan_ParMetis_Order(
ZZ *zz, /* Zoltan structure */
int num_obj, /* Number of (local) objects to order. */
ZOLTAN_ID_PTR gids, /* List of global ids (local to this proc) */
/* The application must allocate enough space */
ZOLTAN_ID_PTR lids, /* List of local ids (local to this proc) */
/* The application must allocate enough space */
ZOLTAN_ID_PTR rank, /* rank[i] is the rank of gids[i] */
int *iperm,
ZOOS *order_opt /* Ordering options, parsed by Zoltan_Order */
)
{
static char *yo = "Zoltan_ParMetis_Order";
int i, n, ierr;
ZOLTAN_Output_Order ord;
ZOLTAN_Third_Graph gr;
#ifdef ZOLTAN_PARMETIS
MPI_Comm comm = zz->Communicator;/* don't want to risk letting external
packages changing our communicator */
#endif
indextype numflag = 0;
int timer_p = 0;
int get_times = 0;
int use_timers = 0;
double times[5];
ZOLTAN_ID_PTR l_gids = NULL;
ZOLTAN_ID_PTR l_lids = NULL;
indextype options[MAX_PARMETIS_OPTIONS];
char alg[MAX_PARAM_STRING_LEN];
ZOLTAN_TRACE_ENTER(zz, yo);
#ifdef ZOLTAN_PARMETIS
#if TPL_USE_DATATYPE != TPL_METIS_DATATYPES
#ifdef TPL_FLOAT_WEIGHT
i = 1;
#else
i = 0;
#endif
if ((sizeof(indextype) != sizeof(idxtype)) ||
(sizeof(weighttype) != sizeof(idxtype)) || i){
ZOLTAN_THIRD_ERROR(ZOLTAN_FATAL,
"Not supported: Multiple 3rd party libraries with incompatible "
"data types.");
return ZOLTAN_FATAL;
}
#endif
#endif
memset(&gr, 0, sizeof(ZOLTAN_Third_Graph));
memset(&ord, 0, sizeof(ZOLTAN_Output_Order));
memset(times, 0, sizeof(times));
ord.order_opt = order_opt;
if (!order_opt){
/* If for some reason order_opt is NULL, allocate a new ZOOS here. */
/* This should really never happen. */
order_opt = (ZOOS *) ZOLTAN_MALLOC(sizeof(ZOOS));
strcpy(order_opt->method,"PARMETIS");
}
ierr = Zoltan_Parmetis_Parse(zz, options, alg, NULL, NULL, &ord);
/* ParMetis only computes the rank vector */
order_opt->return_args = RETURN_RANK;
/* Check that num_obj equals the number of objects on this proc. */
/* This constraint may be removed in the future. */
n = zz->Get_Num_Obj(zz->Get_Num_Obj_Data, &ierr);
if ((ierr!= ZOLTAN_OK) && (ierr!= ZOLTAN_WARN)){
/* Return error code */
ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Get_Num_Obj returned error.");
return(ZOLTAN_FATAL);
}
if (n != num_obj){
/* Currently this is a fatal error. */
ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Input num_obj does not equal the "
"number of objects.");
return(ZOLTAN_FATAL);
}
/* Do not use weights for ordering */
gr.obj_wgt_dim = -1;
gr.edge_wgt_dim = -1;
gr.num_obj = num_obj;
/* Check what ordering type is requested */
if (order_opt){
SET_GLOBAL_GRAPH(&gr.graph_type); /* GLOBAL by default */
#ifdef ZOLTAN_PARMETIS
if ((strcmp(order_opt->method, "METIS") == 0))
#endif /* ZOLTAN_PARMETIS */
SET_LOCAL_GRAPH(&gr.graph_type);
}
gr.get_data = 1;
if (IS_LOCAL_GRAPH(gr.graph_type) && zz->Num_Proc > 1) {
ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Serial ordering on more than 1 process: "
"set ParMetis instead.");
return(ZOLTAN_FATAL);
}
timer_p = Zoltan_Preprocess_Timer(zz, &use_timers);
/* Start timer */
get_times = (zz->Debug_Level >= ZOLTAN_DEBUG_ATIME);
if (get_times){
MPI_Barrier(zz->Communicator);
times[0] = Zoltan_Time(zz->Timer);
}
ierr = Zoltan_Preprocess_Graph(zz, &l_gids, &l_lids, &gr, NULL, NULL, NULL);
if ((ierr != ZOLTAN_OK) && (ierr != ZOLTAN_WARN)) {
Zoltan_Third_Exit(&gr, NULL, NULL, NULL, NULL, NULL);
return (ierr);
}
/* Allocate space for separator sizes */
if (IS_GLOBAL_GRAPH(gr.graph_type)) {
if (Zoltan_TPL_Order_Init_Tree(&zz->TPL_Order, 2*zz->Num_Proc, zz->Num_Proc) != ZOLTAN_OK) {
/* Not enough memory */
Zoltan_Third_Exit(&gr, NULL, NULL, NULL, NULL, &ord);
ZOLTAN_THIRD_ERROR(ZOLTAN_MEMERR, "Out of memory.");
}
ord.sep_sizes = (indextype*)ZOLTAN_MALLOC((2*zz->Num_Proc+1)*sizeof(indextype));
if (ord.sep_sizes == NULL) {
Zoltan_Third_Exit(&gr, NULL, NULL, NULL, NULL, &ord);
ZOLTAN_THIRD_ERROR(ZOLTAN_MEMERR, "Out of memory.");
}
memset(ord.sep_sizes, 0, (2*zz->Num_Proc+1)*sizeof(int)); /* It seems parmetis don't initialize correctly */
}
/* Allocate space for direct perm */
ord.rank = (indextype *) ZOLTAN_MALLOC(gr.num_obj*sizeof(indextype));
if (!ord.rank){
/* Not enough memory */
Zoltan_Third_Exit(&gr, NULL, NULL, NULL, NULL, &ord);
ZOLTAN_THIRD_ERROR(ZOLTAN_MEMERR, "Out of memory.");
}
if (IS_LOCAL_GRAPH(gr.graph_type)){
/* Allocate space for inverse perm */
ord.iperm = (indextype *) ZOLTAN_MALLOC(gr.num_obj*sizeof(indextype));
if (!ord.iperm){
/* Not enough memory */
Zoltan_Third_Exit(&gr, NULL, NULL, NULL, NULL, &ord);
ZOLTAN_THIRD_ERROR(ZOLTAN_MEMERR, "Out of memory.");
}
}
else
ord.iperm = NULL;
/* Get a time here */
if (get_times) times[1] = Zoltan_Time(zz->Timer);
#ifdef ZOLTAN_PARMETIS
if (IS_GLOBAL_GRAPH(gr.graph_type)){
ZOLTAN_TRACE_DETAIL(zz, yo, "Calling the ParMETIS library");
ParMETIS_V3_NodeND (gr.vtxdist, gr.xadj, gr.adjncy,
&numflag, options, ord.rank, ord.sep_sizes, &comm);
ZOLTAN_TRACE_DETAIL(zz, yo, "Returned from the ParMETIS library");
}
else
#endif /* ZOLTAN_PARMETIS */
#if defined(ZOLTAN_METIS) || defined(ZOLTAN_PARMETIS)
if (IS_LOCAL_GRAPH(gr.graph_type)) { /* Be careful : permutation parameters are in the opposite order */
indextype numobj = gr.num_obj;
ZOLTAN_TRACE_DETAIL(zz, yo, "Calling the METIS library");
order_opt->return_args = RETURN_RANK|RETURN_IPERM; /* We provide directly all the permutations */
#if !defined(METIS_VER_MAJOR) || METIS_VER_MAJOR < 5
options[0] = 0; /* Use default options for METIS. */
METIS_NodeND(&numobj, gr.xadj, gr.adjncy, &numflag, options,
ord.iperm, ord.rank);
#else
METIS_SetDefaultOptions(options);
METIS_NodeND(&numobj, gr.xadj, gr.adjncy, NULL, options,
ord.iperm, ord.rank); /* NULL is vwgt -- new interface in v4 */
#endif
ZOLTAN_TRACE_DETAIL(zz, yo, "Returned from the METIS library");
}
#endif /* ZOLTAN_METIS */
/* Get a time here */
if (get_times) times[2] = Zoltan_Time(zz->Timer);
if (IS_GLOBAL_GRAPH(gr.graph_type)){ /* Update Elimination tree */
int numbloc;
int start;
int leaf;
int *converttab;
int levelmax;
levelmax = mylog2(zz->Num_Proc) + 1;
converttab = (int*)ZOLTAN_MALLOC(zz->Num_Proc*2*sizeof(int));
memset(converttab, 0, zz->Num_Proc*2*sizeof(int));
/* Determine the first node in each separator, store it in zz->TPL_Order.start */
for (numbloc = 0, start=0, leaf=0; numbloc < zz->Num_Proc /2; numbloc++) {
int father;
father = zz->Num_Proc + numbloc;
converttab[start] = 2*numbloc;
zz->TPL_Order.leaves[leaf++]=start;
zz->TPL_Order.ancestor[start] = start + 2;
converttab[start+1] = 2*numbloc+1;
zz->TPL_Order.leaves[leaf++]=start+1;
zz->TPL_Order.ancestor[start+1] = start + 2;
start+=2;
do {
converttab[start] = father;
if (father %2 == 0) {
int nextoffset;
int level;
level = mylog2(2*zz->Num_Proc - 1 - father);
nextoffset = (1<<(levelmax-level));
zz->TPL_Order.ancestor[start] = start+nextoffset;
start++;
break;
}
else {
zz->TPL_Order.ancestor[start] = start+1;
start++;
father = zz->Num_Proc + father/2;
}
} while (father < 2*zz->Num_Proc - 1);
}
zz->TPL_Order.start[0] = 0;
zz->TPL_Order.ancestor [2*zz->Num_Proc - 2] = -1;
for (numbloc = 1 ; numbloc < 2*zz->Num_Proc ; numbloc++) {
int oldblock=converttab[numbloc-1];
zz->TPL_Order.start[numbloc] = zz->TPL_Order.start[numbloc-1] + ord.sep_sizes[oldblock];
}
ZOLTAN_FREE(&converttab);
ZOLTAN_FREE(&ord.sep_sizes);
zz->TPL_Order.leaves[zz->Num_Proc] = -1;
zz->TPL_Order.nbr_leaves = zz->Num_Proc;
zz->TPL_Order.nbr_blocks = 2*zz->Num_Proc-1;
}
else { /* No tree */
zz->TPL_Order.nbr_blocks = 0;
zz->TPL_Order.start = NULL;
zz->TPL_Order.ancestor = NULL;
zz->TPL_Order.leaves = NULL;
}
/* Correct because no redistribution */
memcpy(gids, l_gids, n*zz->Num_GID*sizeof(ZOLTAN_ID_TYPE));
memcpy(lids, l_lids, n*zz->Num_LID*sizeof(ZOLTAN_ID_TYPE));
ierr = Zoltan_Postprocess_Graph (zz, l_gids, l_lids, &gr, NULL, NULL, NULL, &ord, NULL);
ZOLTAN_FREE(&l_gids);
ZOLTAN_FREE(&l_lids);
/* Get a time here */
if (get_times) times[3] = Zoltan_Time(zz->Timer);
if (get_times) Zoltan_Third_DisplayTime(zz, times);
if (use_timers)
ZOLTAN_TIMER_STOP(zz->ZTime, timer_p, zz->Communicator);
if (sizeof(indextype) == sizeof(ZOLTAN_ID_TYPE)){
memcpy(rank, ord.rank, gr.num_obj*sizeof(indextype));
}
else{
for (i=0; i < gr.num_obj; i++){
rank[i] = (ZOLTAN_ID_TYPE)ord.rank[i];
}
}
if ((ord.iperm != NULL) && (iperm != NULL)){
if (sizeof(indextype) == sizeof(int)){
memcpy(iperm, ord.iperm, gr.num_obj*sizeof(indextype));
}
else{
for (i=0; i < gr.num_obj; i++){
iperm[i] = (int)ord.iperm[i];
}
}
}
if (ord.iperm != NULL) ZOLTAN_FREE(&ord.iperm);
ZOLTAN_FREE(&ord.rank);
/* Free all other "graph" stuff */
Zoltan_Third_Exit(&gr, NULL, NULL, NULL, NULL, NULL);
ZOLTAN_TRACE_EXIT(zz, yo);
return (ZOLTAN_OK);
}
/*********************************************************************/
/* ParMetis parameter routine */
/*********************************************************************/
int Zoltan_ParMetis_Set_Param(
char *name, /* name of variable */
char *val) /* value of variable */
{
int status, i;
PARAM_UTYPE result; /* value returned from Check_Param */
int index; /* index returned from Check_Param */
char *valid_methods[] = {
"PARTKWAY", "PARTGEOMKWAY", "PARTGEOM",
"REPARTLDIFFUSION", "REPARTGDIFFUSION",
"REPARTREMAP", "REPARTMLREMAP",
"REFINEKWAY", "ADAPTIVEREPART",
"NODEND", /* for nested dissection ordering */
NULL };
status = Zoltan_Check_Param(name, val, Parmetis_params, &result, &index);
if (status == 0){
/* OK so far, do sanity check of parameter values */
if (strcmp(name, "PARMETIS_METHOD") == 0){
status = 2;
for (i=0; valid_methods[i] != NULL; i++){
if (strcmp(val, valid_methods[i]) == 0){
status = 0;
break;
}
}
}
}
return(status);
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,98 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifndef __PARMETIS_INTERFACE_H
#define __PARMETIS_INTERFACE_H
#include <limits.h>
#include "zoltan_comm.h"
#include "third_library_const.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
/* Guess the version number of ParMetis if not defined */
/* PARMETIS_MAJOR_VERSION is only defined in version 3.0 and higher */
#if (!defined(PARMETIS_MAJOR_VERSION))
#define PARMETIS_MAJOR_VERSION 0
#define PARMETIS_MINOR_VERSION 0
#endif
/* ParMetis option defs. These must be identical to the defs
* in defs.h in the version of ParMetis you are using!
* Both ParMetis 2.0 and 3.0 defs are included below.
*/
#define PMV3_OPTION_DBGLVL 1
#define PMV3_OPTION_SEED 2
#define PMV3_OPTION_IPART 3
#define PMV3_OPTION_PSR 3
#define PMV3_OPT_USE_OBJ_SIZE 9 /* Added by EB, not in ParMetis */
#if (PARMETIS_MAJOR_VERSION < 4)
#define MAX_PARMETIS_OPTIONS 40 /* Max number of options +1 */
#else
#define MAX_PARMETIS_OPTIONS METIS_NOPTIONS
#endif
/* Other ParMetis constants we may need */
#define GLOBAL_DBGLVL 0 /* Default debug level */
#define GLOBAL_SEED 15 /* Default random seed */
#define COUPLED 1 /* Processors coupled to partitions? */
#define DISCOUPLED 2 /* Processors coupled to partitions? */
int Zoltan_ParMetis(
ZZ *, float *, int *, ZOLTAN_ID_PTR *, ZOLTAN_ID_PTR *,
int **, int **, int *, ZOLTAN_ID_PTR *, ZOLTAN_ID_PTR *,
int **, int **);
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif
#endif

View File

@ -0,0 +1,74 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifndef __PARMETIS_INTERFACE_PARAMS_H
#define __PARMETIS_INTERFACE_PARAMS_H
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
#include "zz_const.h"
#include "zz_util_const.h"
#include "params_const.h"
/********** parameters structure for parmetis methods **********/
static PARAM_VARS Parmetis_params[] = {
{ "PARMETIS_METHOD", NULL, "STRING", 0 },
{ "PARMETIS_OUTPUT_LEVEL", NULL, "INT", 0 },
{ "PARMETIS_SEED", NULL, "INT", 0 },
{ "PARMETIS_ITR", NULL, "DOUBLE", 0 },
{ "PARMETIS_COARSE_ALG", NULL, "INT", 0 },
{ "PARMETIS_FOLD", NULL, "INT", 0 },
{ NULL, NULL, NULL, 0 } };
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,774 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#include <ctype.h>
#include "zz_const.h"
#include "zz_util_const.h"
#include "all_allo_const.h"
#include "params_const.h"
#include "order_const.h"
#include "third_library.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
/* Auxiliary function prototypes. */
static int
Zoltan_Postprocess_UnScatter_Graph (ZZ *zz,
ZOLTAN_Third_Graph *gr,
ZOLTAN_Third_Part *prt,
indextype **rank);
static int
Zoltan_Postprocess_Order (ZZ *zz,
ZOLTAN_Third_Graph *gr,
ZOLTAN_Output_Order *ord);
static int
Zoltan_Postprocess_Partition (ZZ *zz,
ZOLTAN_Third_Graph *gr,
ZOLTAN_Third_Part *prt,
ZOLTAN_Output_Part *part,
ZOLTAN_ID_PTR global_ids,
ZOLTAN_ID_PTR local_ids);
static int Compute_Bal(ZZ *, int, weighttype *, int, indextype *, double *);
static int Compute_EdgeCut(ZZ *, int, indextype *, float *, indextype *, int *, double *);
static float Compute_NetCut(ZZ *, int, indextype *, float *, indextype *, int *);
static float Compute_ConCut(ZZ *, int, indextype *, float *, indextype *, int *);
static int Compute_Adjpart(ZZ *, int, indextype *, indextype *, indextype *, int *, indextype *, int *);
int Zoltan_Postprocess_Graph(
ZZ *zz, /* Zoltan structure */
ZOLTAN_ID_PTR global_ids,
ZOLTAN_ID_PTR local_ids,
ZOLTAN_Third_Graph *gr, /* Graph for third part libs */
ZOLTAN_Third_Geom *geo,
ZOLTAN_Third_Part *prt,
ZOLTAN_Third_Vsize *vsp,
ZOLTAN_Output_Order *ord,
ZOLTAN_Output_Part *part)
{
int ierr = ZOLTAN_OK;
static char * yo = "Zoltan_Postprocess_Graph";
if (gr->scatter > 0) { /* Graph has been scattered */
indextype *rank = NULL;
if (ord) rank = ord->rank;
else rank = NULL;
ierr = Zoltan_Postprocess_UnScatter_Graph (zz, gr, prt, &rank);
if (ierr) {
ZOLTAN_THIRD_ERROR(ZOLTAN_FATAL,
"Error returned from Zoltan_Postprocess_UnScatter_Graph");
}
if (ord) ord->rank = rank;
}
if (ord) { /* We have done ordering */
ierr = Zoltan_Postprocess_Order (zz, gr, ord);
if (ierr == ZOLTAN_FATAL) {
ZOLTAN_THIRD_ERROR(ZOLTAN_FATAL,
"Error returned from Zoltan_Postprocess_Order");
}
}
if (part) { /* We have done partitioning */
ierr = Zoltan_Postprocess_Partition (zz, gr, prt, part, global_ids, local_ids);
if (ierr == ZOLTAN_FATAL) {
ZOLTAN_THIRD_ERROR(ZOLTAN_FATAL,
"Error returned from Zoltan_Postprocess_Partition");
}
}
return (ierr);
}
static int
Zoltan_Postprocess_UnScatter_Graph (ZZ *zz,
ZOLTAN_Third_Graph *gr,
ZOLTAN_Third_Part *prt,
indextype **rank)
{
static char * yo = "Zoltan_Postprocess_UnScatter_Graph";
int ierr = ZOLTAN_FATAL;
indextype *src;
indextype *dst;
if (gr->scatter >0){
gr->num_obj = gr->num_obj_orig;
if (*rank) { /* We have to project back rank */
dst = (indextype*) ZOLTAN_MALLOC(gr->num_obj*sizeof(indextype));
src = *rank;
}
else {
dst = prt->part_orig;
src = prt->part;
}
ierr = Zoltan_Comm_Do_Reverse(gr->comm_plan, TAG2, (char *) src,
sizeof(indextype), NULL, (char *) dst);
if ((ierr == ZOLTAN_FATAL) || (ierr == ZOLTAN_MEMERR)){
ZOLTAN_THIRD_ERROR(ierr, "Zoltan_Comm_Do_Reverse returned error.");
}
Zoltan_Comm_Destroy(&gr->comm_plan); /* Destroy the comm. plan */
/* We don't need the partition array with the scattered distribution
* any more */
ZOLTAN_FREE(&src);
if (prt) {
/* part is now the new partition array under the original distribution */
prt->part = prt->part_orig;
prt->part_orig = NULL;
}
else {
*rank = dst;
}
}
return (ierr);
}
static int
Zoltan_Postprocess_Order (ZZ *zz,
ZOLTAN_Third_Graph *gr,
ZOLTAN_Output_Order *ord)
{
int ierr = ZOLTAN_OK;
int i;
const char *yo = "Zoltan_Postprocess_Order";
/* Ordering */
/* ParMetis produces the rank vector in Zoltan lingo */
if (ord->rank != NULL) {
/* Check if start_index != 0 */
if (ord->order_opt && ord->order_opt->start_index) {
int start_index;
start_index = ord->order_opt->start_index;
for (i=0; i<gr->num_obj; i++){
ord->rank[i] += start_index;
}
}
}
else {
ZOLTAN_PRINT_WARN(zz->Proc, yo, "rank is NULL, no data returned");
ierr = ZOLTAN_WARN;
}
/* If we did local ordering via METIS, then we also have the inv. perm. */
if ((gr->graph_type == LOCAL_GRAPH) && (ord->iperm != NULL)){
int start_index;
start_index = ord->order_opt->start_index;
for (i=0; i<gr->num_obj; i++){
ord->iperm[i] += start_index;
}
/* EBEB: Return parameter that says we have computed both return args? */
}
/* Fill in the Zoltan Order Struct */
/* EBEB: For now, discard separator info */
if (0){ /* DEBUG: Print separator sizes to file */
FILE *fp;
fp = fopen("separators.txt", "w");
fprintf(fp, "%i\n", ord->num_part);
for (i=0; i<ord->num_part; ++i){
fprintf(fp, TPL_IDX_SPEC " ", ord->sep_sizes[i]);
}
fprintf(fp, "\n");
for (i=ord->num_part; i<2*ord->num_part-1; ++i){
fprintf(fp, TPL_IDX_SPEC " ", ord->sep_sizes[i]);
}
fprintf(fp, "\n");
fclose(fp);
}
return (ierr);
}
static int
Zoltan_Postprocess_Partition (ZZ *zz,
ZOLTAN_Third_Graph *gr,
ZOLTAN_Third_Part *prt,
ZOLTAN_Output_Part *part,
ZOLTAN_ID_PTR global_ids,
ZOLTAN_ID_PTR local_ids)
{
static char * yo = "Zoltan_Postprocess_Partition";
int ierr = ZOLTAN_OK;
int i, j, nsend;
int *newproc, *tmp_part, *tmp_input_part;
int num_gid_entries = zz->Num_GID;
int num_lid_entries = zz->Num_LID;
/* Partitioning */
/* Determine new processor and number of objects to export */
newproc = (int *) ZOLTAN_MALLOC(gr->num_obj * sizeof(int));
if (gr->num_obj && !newproc){
/* Not enough memory */
ZOLTAN_THIRD_ERROR(ZOLTAN_MEMERR, "Out of memory. ");
}
for (i=0; i<gr->num_obj; i++){
newproc[i] = Zoltan_LB_Part_To_Proc(zz, (int)prt->part[i],
&(global_ids[i*num_gid_entries]));
if (newproc[i]<0){
ZOLTAN_FREE(&newproc);
ZOLTAN_THIRD_ERROR(ZOLTAN_FATAL,
"Zoltan_LB_Part_To_Proc returned invalid processor number.");
}
}
if (zz->LB.Remap_Flag) {
int new_map;
if (sizeof(indextype) == sizeof(int)){
ierr = Zoltan_LB_Remap(zz, &new_map, gr->num_obj, newproc, (int *)prt->input_part,
(int *)prt->part, 1);
}
else{
tmp_part = (int *)ZOLTAN_MALLOC(sizeof(int) * gr->num_obj);
tmp_input_part = (int *)ZOLTAN_MALLOC(sizeof(int) * gr->num_obj);
if (gr->num_obj && (!tmp_part || !tmp_input_part)){
ZOLTAN_THIRD_ERROR(ZOLTAN_MEMERR, "Not enough memory.");
}
for (i=0; i < gr->num_obj; i++){
tmp_part[i] = (int)prt->part[i];
tmp_input_part[i] = (int)prt->input_part[i];
}
ierr = Zoltan_LB_Remap(zz, &new_map, gr->num_obj, newproc, tmp_input_part, tmp_part, 1);
for (i=0; i < gr->num_obj; i++){
prt->part[i] = (indextype)tmp_part[i];
prt->input_part[i] = (indextype)tmp_input_part[i];
}
ZOLTAN_FREE(&tmp_part);
ZOLTAN_FREE(&tmp_input_part);
}
if (ierr < 0) {
ZOLTAN_FREE(&newproc);
ZOLTAN_THIRD_ERROR(ZOLTAN_FATAL,
"Error returned from Zoltan_LB_Remap");
}
}
nsend = 0;
for (i=0; i<gr->num_obj; i++){
if ((prt->part[i] != prt->input_part[i]) || ((!part->compute_only_part_changes) &&
(newproc[i] != zz->Proc)))
nsend++;
if (zz->Debug_Level >= ZOLTAN_DEBUG_ALL)
printf("[%1d] DEBUG: local object %1d: old part = " TPL_IDX_SPEC ", new part = " TPL_IDX_SPEC "\n",
zz->Proc, i, prt->input_part[i], prt->part[i]);
}
/* Create export lists */
if (zz->LB.Return_Lists){
if (zz->LB.Return_Lists == ZOLTAN_LB_CANDIDATE_LISTS) {
ZOLTAN_THIRD_ERROR(ZOLTAN_FATAL, "Candidate Lists not supported in GRAPH;"
"change RETURN_LISTS parameter.");
}
part->num_exp = nsend;
if (nsend > 0) {
if (!Zoltan_Special_Malloc(zz,(void **)part->exp_gids,nsend,ZOLTAN_SPECIAL_MALLOC_GID)) {
ZOLTAN_FREE(&newproc);
ZOLTAN_THIRD_ERROR(ZOLTAN_MEMERR, "Not enough memory.");
}
if (!Zoltan_Special_Malloc(zz,(void **)part->exp_lids,nsend,ZOLTAN_SPECIAL_MALLOC_LID)) {
Zoltan_Special_Free(zz,(void **)part->exp_gids,ZOLTAN_SPECIAL_MALLOC_GID);
ZOLTAN_FREE(&newproc);
ZOLTAN_THIRD_ERROR(ZOLTAN_MEMERR, "Not enough memory.");
}
if (!Zoltan_Special_Malloc(zz,(void **)part->exp_procs,nsend,ZOLTAN_SPECIAL_MALLOC_INT)) {
Zoltan_Special_Free(zz,(void **)part->exp_lids,ZOLTAN_SPECIAL_MALLOC_LID);
Zoltan_Special_Free(zz,(void **)part->exp_gids,ZOLTAN_SPECIAL_MALLOC_GID);
ZOLTAN_FREE(&newproc);
ZOLTAN_THIRD_ERROR(ZOLTAN_MEMERR, "Not enough memory.");
}
if (!Zoltan_Special_Malloc(zz,(void **)part->exp_part,nsend,ZOLTAN_SPECIAL_MALLOC_INT)) {
Zoltan_Special_Free(zz,(void **)part->exp_lids,ZOLTAN_SPECIAL_MALLOC_LID);
Zoltan_Special_Free(zz,(void **)part->exp_gids,ZOLTAN_SPECIAL_MALLOC_GID);
Zoltan_Special_Free(zz,(void **)part->exp_procs,ZOLTAN_SPECIAL_MALLOC_INT);
ZOLTAN_FREE(&newproc);
ZOLTAN_THIRD_ERROR(ZOLTAN_MEMERR, "Not enough memory.");
}
j = 0;
for (i=0; i<gr->num_obj; i++){
if ((prt->part[i] != prt->input_part[i]) || ((!part->compute_only_part_changes)
&& (newproc[i] != zz->Proc))){
/* Object should move to new partition or processor */
ZOLTAN_SET_GID(zz, &((*(part->exp_gids))[j*num_gid_entries]),
&(global_ids[i*num_gid_entries]));
if (num_lid_entries)
ZOLTAN_SET_LID(zz, &((*(part->exp_lids))[j*num_lid_entries]),
&(local_ids[i*num_lid_entries]));
(*(part->exp_part))[j] = (int)prt->part[i];
(*(part->exp_procs))[j] = newproc[i];
/* printf("[%1d] Debug: Move object %1d to part %1d, proc %1d\n", */
/* zz->Proc, i, prt->part[i], newproc[i]); */
j++;
}
}
}
}
ZOLTAN_FREE(&newproc);
return (ZOLTAN_OK);
}
int
Zoltan_Postprocess_FinalOutput (ZZ* zz, ZOLTAN_Third_Graph *gr,
ZOLTAN_Third_Part *prt, ZOLTAN_Third_Vsize *vsp,
int use_timers, realtype itr)
{
#define FOMAXDIM 10
static char * yo = "Zoltan_Postprocess_FinalOutput";
static int nRuns=0;
static double balsum[FOMAXDIM], cutesum[FOMAXDIM];
static double balmax[FOMAXDIM], cutemax[FOMAXDIM];
static double balmin[FOMAXDIM], cutemin[FOMAXDIM];
/* following variables are defined double to avoid overflow */
static double cutlsum = 0.0, cutnsum = 0.0, movesum = 0.0, repartsum = 0.0;
static float cutlmax = 0, cutnmax = 0;
static double movemax = 0, repartmax = 0;
static float cutlmin = (float)INT_MAX, cutnmin = (float)INT_MAX;
static double movemin = 1e100, repartmin = 1e100;
static int timer_final_output = -1;
double bal[FOMAXDIM]; /* Balance: max / avg */
double cute[FOMAXDIM]; /* Traditional weighted graph edge cuts */
float cutl; /* Connnectivity cuts: sum_over_edges((npart-1)) */
float cutn; /* Net cuts: sum_over_edges((nparts>1)) */
double move = 0.0, gmove =0.0; /* migration cost */
double repart; /* total repartitioning cost; cutl x multiplier + move */
int *adjpart = NULL;
int vdim;
int edim;
indextype *vsizeBACKUP = NULL;
indextype *input_part;
int i,rc;
/* #define UVC_DORUK_COMP_OBJSIZE */
#ifdef UVC_DORUK_COMP_OBJSIZE
double minD, maxD, gminD, gmaxD;
#endif
if (use_timers) {
if (timer_final_output < 0)
timer_final_output = Zoltan_Timer_Init(zz->ZTime, 1, "Final_Output");
ZOLTAN_TIMER_START(zz->ZTime, timer_final_output, zz->Communicator);
}
if (nRuns == 0) {
for (i = 0; i < FOMAXDIM; i++) {
/* Initialize first time */
balsum[i] = cutesum[i] = 0.0;
balmax[i] = cutemax[i] = 0.0;
balmin[i] = cutemin[i] = 1e100;
}
}
if (vsp && vsp->vsizeBACKUP)
vsizeBACKUP = vsp->vsizeBACKUP;
vdim = MAX(gr->obj_wgt_dim,1);
edim = MAX(zz->Edge_Weight_Dim,1);
if (gr->obj_wgt_dim < FOMAXDIM && zz->Edge_Weight_Dim < FOMAXDIM) {
if (gr->xadj[gr->num_obj]){
adjpart = (int *) ZOLTAN_MALLOC(gr->xadj[gr->num_obj] * sizeof(int));
if (!adjpart){
ZOLTAN_THIRD_ERROR(ZOLTAN_MEMERR,
"Error 1 returned from Zoltan_Postprocess_FinalOutput");
}
}
Compute_Bal(zz, gr->num_obj, gr->vwgt, gr->obj_wgt_dim, prt->part, bal);
rc = Compute_Adjpart(zz, gr->num_obj, gr->vtxdist, gr->xadj, gr->adjncy,
gr->adjproc, prt->part, adjpart);
if (rc != ZOLTAN_OK){
ZOLTAN_THIRD_ERROR(ZOLTAN_MEMERR,
"Error 2 returned from Zoltan_Postprocess_FinalOutput");
}
Compute_EdgeCut(zz, gr->num_obj, gr->xadj, gr->float_ewgts,
prt->part, adjpart, cute);
cutl = Compute_ConCut(zz, gr->num_obj, gr->xadj, gr->float_ewgts,
prt->part, adjpart);
cutn = Compute_NetCut(zz, gr->num_obj, gr->xadj, gr->float_ewgts,
prt->part, adjpart);
#ifdef UVC_DORUK_COMP_OBJSIZE
if (vsizeBACKUP) {
minD = vsizeBACKUP[0];
maxD = vsizeBACKUP[0];
}
#endif
if (gr->scatter != 0) { /* Project input part in the scatter graph */
input_part = (indextype*) ZOLTAN_MALLOC(gr->num_obj * sizeof(int));
Zoltan_Comm_Do(gr->comm_plan, TAG1, (char *) prt->input_part, sizeof(indextype),
(char *) input_part);
}
else
input_part = prt->input_part;
for (i=0; i<gr->num_obj; i++) {
/*printf("obj[%d] = %d\n", i, vsize[i]);*/
if (prt->part[i] != input_part[i]) {
move += (double) ((vsizeBACKUP) ? vsizeBACKUP[i] : 1.0);
}
#ifdef UVC_DORUK_COMP_OBJSIZE
if (vsizeBACKUP) {
minD = minD < vsizeBACKUP[i] ? minD : vsizeBACKUP[i];
maxD = maxD > vsizeBACKUP[i] ? maxD : vsizeBACKUP[i];
}
#endif
}
if (gr->scatter != 0)
ZOLTAN_FREE(&input_part);
#ifdef UVC_DORUK_COMP_OBJSIZE
if (gr->showMoveVol) {
MPI_Allreduce(&minD, &gminD, 1, MPI_DOUBLE, MPI_MIN, zz->Communicator);
MPI_Allreduce(&maxD, &gmaxD, 1, MPI_DOUBLE, MPI_MAX, zz->Communicator);
if (zz->Proc == 0)
printf("minD: %f, maxD: %f, gminD: %f, gmaxD: %f\n", minD, maxD, gminD, gmaxD);
}
#endif
MPI_Allreduce(&move, &gmove, 1, MPI_DOUBLE, MPI_SUM, zz->Communicator);
repart = (itr) * (double) cutl + gmove;
repartsum += repart;
if (repart > repartmax) repartmax = repart;
if (repart < repartmin) repartmin = repart;
movesum += gmove;
if (gmove > movemax) movemax = gmove;
if (gmove < movemin) movemin = gmove;
cutlsum += cutl;
if (cutl > cutlmax) cutlmax = cutl;
if (cutl < cutlmin) cutlmin = cutl;
cutnsum += cutn;
if (cutn > cutnmax) cutnmax = cutn;
if (cutn < cutnmin) cutnmin = cutn;
for (i = 0; i < vdim; i++) {
balsum[i] += bal[i];
if (bal[i] > balmax[i]) balmax[i] = bal[i];
if (bal[i] < balmin[i]) balmin[i] = bal[i];
}
for (i = 0; i < edim; i++) {
cutesum[i] += cute[i];
if (cute[i] > cutemax[i]) cutemax[i] = cute[i];
if (cute[i] < cutemin[i]) cutemin[i] = cute[i];
}
nRuns++;
if (zz->Proc == 0) {
for (i = 0; i < vdim; i++)
printf("STATS Runs %d bal[%d] CURRENT %f MAX %f MIN %f AVG %f\n",
nRuns, i, bal[i], balmax[i], balmin[i], balsum[i]/nRuns);
printf("STATS Runs %d cutl CURRENT %f MAX %f MIN %f AVG %f\n",
nRuns, cutl, cutlmax, cutlmin, cutlsum/nRuns);
printf("STATS Runs %d cutn CURRENT %f MAX %f MIN %f AVG %f\n",
nRuns, cutn, cutnmax, cutnmin, cutnsum/nRuns);
for (i = 0; i < edim; i++)
printf("STATS Runs %d cute[%d] CURRENT %f MAX %f MIN %f AVG %f\n",
nRuns, i, cute[i], cutemax[i], cutemin[i], cutesum[i]/nRuns);
printf("STATS Runs %d %s CURRENT %f MAX %f MIN %f AVG %f\n",
nRuns, gr->showMoveVol ? "moveVol" : "moveCnt", gmove,
movemax, movemin, movesum/nRuns);
if (gr->showMoveVol)
printf("STATS Runs %d repart CURRENT %f MAX %f MIN %f AVG %f\n",
nRuns, repart, repartmax, repartmin, repartsum/nRuns);
}
ZOLTAN_FREE(&adjpart);
}
#undef FOMAXDIM
if (use_timers)
ZOLTAN_TIMER_STOP(zz->ZTime, timer_final_output, zz->Communicator);
return (ZOLTAN_OK);
}
/****************************************************************************/
static int Compute_Bal(
ZZ *zz,
int nvtx,
weighttype *vwgts,
int obj_wgt_dim,
indextype *parts,
double *bal
)
{
/*
* Compute the load balance of the computed partition.
*/
int i, j;
int dim = MAX(obj_wgt_dim, 1);
int size;
float *sum = NULL, *gsum = NULL;
float *tot = NULL, *max = NULL;
size = zz->LB.Num_Global_Parts * dim;
sum = (float *) ZOLTAN_CALLOC(2 * size, sizeof(float));
gsum = sum + size;
tot = (float *) ZOLTAN_CALLOC(2 * dim, sizeof(float));
max = tot + dim;
for (i = 0; i < nvtx; i++)
for (j = 0; j < dim; j++)
sum[parts[i]*dim + j] += (vwgts ? vwgts[i*dim + j] : 1.);
MPI_Allreduce(sum, gsum, size, MPI_FLOAT, MPI_SUM, zz->Communicator);
for (i = 0; i < zz->LB.Num_Global_Parts; i++)
for (j = 0; j < dim; j++) {
tot[j] += gsum[i*dim+j];
if (gsum[i*dim+j] > max[j]) max[j] = gsum[i*dim+j];
}
for (j = 0; j < dim; j++)
if (tot[j] > 0.)
bal[j] = zz->LB.Num_Global_Parts * max[j] / tot[j];
ZOLTAN_FREE(&sum);
ZOLTAN_FREE(&tot);
return ZOLTAN_OK;
}
/****************************************************************************/
static int Compute_EdgeCut(
ZZ *zz,
int nvtx,
indextype *xadj,
float *ewgts,
indextype *parts,
int *nborparts,
double *cute
)
{
/*
* Compute total weight of cut graph edges w.r.t. partitions.
*/
indextype i, j, k;
int dim = MAX(zz->Edge_Weight_Dim, 1);
double *cut = NULL;
cut = (double *) ZOLTAN_CALLOC(dim, sizeof(double));
for (i = 0; i < nvtx; i++)
for (j = xadj[i]; j < xadj[i+1]; j++)
if (parts[i] != nborparts[j])
for (k = 0; k < dim; k++)
cut[k] += (ewgts ? ewgts[j*dim+k] : 1.);
MPI_Allreduce(cut, cute, dim, MPI_DOUBLE, MPI_SUM, zz->Communicator);
ZOLTAN_FREE(&cut);
return ZOLTAN_OK;
}
/****************************************************************************/
static float Compute_NetCut(
ZZ *zz,
int nvtx,
indextype *xadj,
float *ewgts,
indextype *parts,
int *nborparts
)
{
/*
* Compute weight of hyperedges cut w.r.t. partitions.
* Assume one hyperedge per vertex.
* Equivalent to number of boundary vertices weighted by edge weights.
*/
indextype i, j;
float cutn = 0., gcutn = 0.;
int dim = zz->Edge_Weight_Dim;
for (i = 0; i < nvtx; i++) {
/* Compute the maximum graph edge weight of all edges incident to vertex */
/* For now, use only first weight per edge. */
float maxewgt = 0.;
if (ewgts)
for (j = xadj[i]; j < xadj[i+1]; j++)
if (ewgts[j*dim] > maxewgt) maxewgt = ewgts[j*dim];
for (j = xadj[i]; j < xadj[i+1]; j++)
if (parts[i] != nborparts[j]) {
cutn += (ewgts ? maxewgt : 1.);
break;
}
}
MPI_Allreduce(&cutn, &gcutn, 1, MPI_FLOAT, MPI_SUM, zz->Communicator);
return gcutn;
}
/****************************************************************************/
static float Compute_ConCut(
ZZ *zz,
int nvtx,
indextype *xadj,
float *ewgts,
indextype *parts,
int *nborparts
)
{
/*
* Compute SUM over hyperedges( (#parts/hyperedge - 1)*ewgt);
* Assume one hyperedge per vertex.
*/
indextype i, j;
float cutl = 0., gcutl = 0.;
indextype *used = NULL;
int dim = zz->Edge_Weight_Dim;
used = (indextype *) ZOLTAN_MALLOC(zz->LB.Num_Global_Parts * sizeof(indextype));
for (i = 0; i < zz->LB.Num_Global_Parts; i++) used[i] = -1;
for (i = 0; i < nvtx; i++) {
/* Compute the maximum graph edge weight of all edges incident to vertex */
/* For now, use only first weight per edge. */
float maxewgt = 0.;
if (ewgts)
for (j = xadj[i]; j < xadj[i+1]; j++)
if (ewgts[j*dim] > maxewgt) maxewgt = ewgts[j*dim];
used[parts[i]] = i;
for (j = xadj[i]; j < xadj[i+1]; j++)
if (used[nborparts[j]] < i) {
used[nborparts[j]] = i;
cutl += (ewgts ? maxewgt : 1.);
}
}
ZOLTAN_FREE(&used);
MPI_Allreduce(&cutl, &gcutl, 1, MPI_FLOAT, MPI_SUM, zz->Communicator);
return gcutl;
}
/****************************************************************************/
static int Compute_Adjpart(
ZZ *zz,
int nvtx, /* Input: # vtxs in this processor */
indextype *vtxdist, /* Input: Distribution of vertices across processors */
indextype *xadj, /* Input: Index of adjncy: adjncy[xadj[i]] to
adjncy[xadj[i]+1] are all edge nbors of vtx i. */
indextype *adjncy, /* Input: Array of nbor vertices. */
int *adjproc, /* Input: adjproc[j] == processor owning adjncy[j]. */
indextype *part, /* Input: Partition assignments of vtxs. */
int *adjpart /* Output: adjpart[j] == partition owning adjncy[j] */
)
{
/* Given an adjacency list adjncy, find the partition number of each
* vertex in adjncy. Return it in adjpart.
*/
ZOLTAN_COMM_OBJ *plan;
int i;
indextype start = vtxdist[zz->Proc]; /* First vertex on this processor */
indextype *recv_gno= NULL;
int *send_int=NULL;
int nrecv;
int tag = 24542;
Zoltan_Comm_Create(&plan, (int)xadj[nvtx], adjproc, zz->Communicator, tag++, &nrecv);
if (nrecv){
recv_gno = (indextype *) ZOLTAN_MALLOC(nrecv * sizeof(indextype));
send_int = (int *) ZOLTAN_MALLOC(nrecv * sizeof(int));
if (!recv_gno || !send_int) {
Zoltan_Comm_Destroy(&plan);
ZOLTAN_FREE(&recv_gno);
ZOLTAN_FREE(&send_int);
return ZOLTAN_MEMERR;
}
}
Zoltan_Comm_Do(plan, tag++, (char *) adjncy, sizeof(indextype), (char *) recv_gno);
for (i = 0; i < nrecv; i++){
send_int[i] = part[recv_gno[i] - start];
}
ZOLTAN_FREE(&recv_gno);
Zoltan_Comm_Do_Reverse(plan, tag, (char *)send_int, sizeof(int), NULL, (char *) adjpart);
ZOLTAN_FREE(&send_int);
Zoltan_Comm_Destroy(&plan);
return ZOLTAN_OK;
}
#ifdef __cplusplus
}
#endif

1158
thirdParty/Zoltan/src/tpls/preprocessing.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,305 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
#include "zz_const.h"
#include "third_library_const.h"
#include "third_library_tools.h"
#include "graph_util.h"
/*
* Scatter a ParMetis-style graph to all processors such that each proc
* gets an even chunk of vertices and corresponding edges.
* The entire graph structure is shuffled around; no attempt is made
* to keep data local. Processor i receives nodes i*n/p through (i+1)*n/p.
* This routine is only useful if the distribution is highly imbalanced!
*
* The input graph structure is lost and fresh memory is allocated
* for the new distributed graph.
*
* This routine can also handle geometry data. The graph data may be NULL.
*
* The vertex communication plan is returned so it may be used to compute
* the export lists after partitioning.
*
* Currently the number of weights are inferred from zz->Obj_Weight_Dim
* and zz->Edge_Weight_Dim. Perhaps these values should be input parameters.
*/
int Zoltan_Scatter_Graph(
indextype **vtxdist,
indextype **xadj,
indextype **adjncy,
weighttype **vwgt,
indextype **vsize,
weighttype **adjwgt,
realtype **xyz,
int ndims, /* # dimensions of xyz geometry data */
int vwgt_dim,
ZZ *zz,
ZOLTAN_COMM_OBJ **plan
)
{
static char *yo = "Zoltan_Scatter_Graph";
char msg[256];
indextype *old_vtxdist, *old_adjncy;
indextype *old_xadj;
indextype *old_vsize;
weighttype *old_vwgt, *old_adjwgt;
realtype *old_xyz;
int *ptr, *proclist = NULL, *proclist2 = NULL;
int i, j, num_obj, old_num_obj, num_edges, nrecv;
int use_graph; /* do we use graph data, or only the geometry? */
int use_vsize; /* do we use the vsize array? */
int ewgt_dim= zz->Edge_Weight_Dim;
ZOLTAN_COMM_OBJ *plan2;
ZOLTAN_TRACE_ENTER(zz, yo);
/* Save pointers to "old" data distribution */
old_adjncy = NULL;
old_xadj = NULL;
old_vwgt = old_adjwgt = NULL;
old_vsize = NULL;
old_xyz = NULL;
old_vtxdist = *vtxdist;
if (xadj)
old_xadj = *xadj;
if (adjncy)
old_adjncy = *adjncy;
if (vwgt)
old_vwgt = *vwgt;
if (vsize)
old_vsize = *vsize;
if (adjwgt)
old_adjwgt = *adjwgt;
if (xyz)
old_xyz = *xyz;
old_num_obj = (int)(old_vtxdist[zz->Proc+1] - old_vtxdist[zz->Proc]);
if (zz->Debug_Level >= ZOLTAN_DEBUG_ALL)
printf("[%1d] Debug: Old number of objects = %d\n", zz->Proc, old_num_obj);
/* Compute new distribution, *vtxdist */
(*vtxdist) = (indextype *)ZOLTAN_MALLOC((zz->Num_Proc+1)* sizeof(indextype));
for (i=0; i<=zz->Num_Proc; i++){
(*vtxdist)[i] = (i*old_vtxdist[zz->Num_Proc])/zz->Num_Proc;
}
/* Check if any proc has graph data */
i = (old_xadj != NULL);
MPI_Allreduce(&i, &use_graph, 1, MPI_INT, MPI_LOR, zz->Communicator);
j = (old_vsize != NULL);
MPI_Allreduce(&j, &use_vsize, 1, MPI_INT, MPI_LOR, zz->Communicator);
if (zz->Debug_Level >= ZOLTAN_DEBUG_ALL)
printf("[%1d] Debug: use_graph = %1d, use_vsize = %1d\n", zz->Proc,
use_graph, use_vsize);
/* Reset all data pointers to NULL for now */
*xadj = NULL;
*adjncy = NULL;
*vwgt = *adjwgt = NULL;
*xyz = NULL;
if (use_vsize) *vsize = NULL;
/* Convert the xdj array so that it contains the degree of each vertex */
if (use_graph){
for (i=0; i<old_num_obj; i++){
old_xadj[i] = old_xadj[i+1] - old_xadj[i];
}
}
/* Allocate new space for vertex data */
num_obj = (int)((*vtxdist)[zz->Proc+1] - (*vtxdist)[zz->Proc]);
if (zz->Debug_Level >= ZOLTAN_DEBUG_ALL)
printf("[%1d] Debug: New number of objects = %d\n", zz->Proc, num_obj);
if (use_graph)
*xadj = (indextype *) ZOLTAN_MALLOC((num_obj+1)*sizeof(indextype));
if (vwgt_dim)
*vwgt = (weighttype *) ZOLTAN_MALLOC(vwgt_dim*num_obj*sizeof(weighttype));
if (use_vsize)
*vsize = (indextype *) ZOLTAN_MALLOC(num_obj*sizeof(indextype));
if (ndims)
*xyz = (realtype *) ZOLTAN_MALLOC(ndims*num_obj*sizeof(realtype));
if (old_num_obj > 0) {
/* Set up the communication plan for the vertex data */
proclist = (int *) ZOLTAN_MALLOC(old_num_obj * sizeof(int));
/* Let j be the new owner of vertex old_vtxdist[zz->Proc]+i */
j = 0;
while (old_vtxdist[zz->Proc] >= (*vtxdist)[j+1]) j++;
for (i=0; i<old_num_obj; i++){
if (old_vtxdist[zz->Proc]+i >= (*vtxdist)[j+1]) j++;
proclist[i] = j;
}
}
Zoltan_Comm_Create(plan, old_num_obj, proclist, zz->Communicator, TAG1, &nrecv);
if (nrecv != num_obj){
sprintf(msg,"Proc %d received %d object but expected %d.",
zz->Proc, nrecv, num_obj);
ZOLTAN_PRINT_ERROR(zz->Proc, yo, msg);
/* Free data */
ZOLTAN_FREE(&proclist);
ZOLTAN_TRACE_EXIT(zz, yo);
return ZOLTAN_FATAL;
}
/* Do the communication. To save memory, we do not pack all the data into
* a buffer, but send directly from the old arrays to the new arrays.
* We use the vertex communication plan for all the vertex-based arrays
* and the edge communication plan for all the edge-based arrays.
*/
if (zz->Debug_Level >= ZOLTAN_DEBUG_ALL)
printf("[%1d] Debug: Starting vertex-based communication.\n", zz->Proc);
if (use_graph){
Zoltan_Comm_Do( *plan, TAG2, (char *) old_xadj, sizeof(indextype), (char *) *xadj);
}
if (vwgt_dim){
Zoltan_Comm_Do( *plan, TAG3, (char *) old_vwgt, vwgt_dim*sizeof(weighttype), (char *) *vwgt);
}
if (use_vsize){
Zoltan_Comm_Do( *plan, TAG4, (char *) old_vsize, sizeof(indextype), (char *) *vsize);
}
if (ndims){
Zoltan_Comm_Do( *plan, TAG5, (char *) old_xyz, ndims*sizeof(realtype), (char *) *xyz);
}
if (zz->Debug_Level >= ZOLTAN_DEBUG_ALL)
printf("[%1d] Debug: Finished vertex-based communication.\n", zz->Proc);
if (use_graph){
/* Rebuild xadj from degrees */
for (i=1; i<num_obj; i++)
(*xadj)[i] += (*xadj)[i-1];
for (i=num_obj; i>0; i--)
(*xadj)[i] = (*xadj)[i-1];
(*xadj)[0] = 0;
/* Allocate space for new edge data structures */
num_edges = (*xadj)[num_obj];
*adjncy = (indextype *) ZOLTAN_MALLOC(num_edges*sizeof(indextype));
if (ewgt_dim)
*adjwgt = (weighttype *) ZOLTAN_MALLOC(ewgt_dim*num_edges*sizeof(weighttype));
/* Set up the communication plan for the edge data. */
ptr = proclist2 = (int *) ZOLTAN_MALLOC(old_xadj[old_num_obj] * sizeof(int));
for (i=0; i<old_num_obj; i++)
for (j=0; j<old_xadj[i]; j++)
*ptr++ = proclist[i];
if (zz->Debug_Level >= ZOLTAN_DEBUG_ALL) {
printf("[%1d] Debug: Allocated proclist of length " TPL_IDX_SPEC " for edges.\n",
zz->Proc, old_xadj[old_num_obj]);
}
Zoltan_Comm_Create(&plan2, (int)old_xadj[old_num_obj], proclist2, zz->Communicator,
TAG1, &nrecv);
if (nrecv != num_edges){
sprintf(msg,"Proc %d received %d edges but expected %d.",
zz->Proc, nrecv, num_edges);
ZOLTAN_PRINT_ERROR(zz->Proc, yo, msg);
/* Free data */
ZOLTAN_FREE(&proclist);
ZOLTAN_FREE(&proclist2);
ZOLTAN_FREE(&old_vtxdist);
ZOLTAN_FREE(&old_xadj);
ZOLTAN_FREE(&old_adjncy);
ZOLTAN_FREE(&old_vwgt);
ZOLTAN_FREE(&old_vsize);
ZOLTAN_FREE(&old_adjwgt);
ZOLTAN_FREE(&old_xyz);
ZOLTAN_TRACE_EXIT(zz, yo);
return ZOLTAN_FATAL;
}
if (zz->Debug_Level >= ZOLTAN_DEBUG_ALL)
printf("[%1d] Debug: Starting edge-based communication.\n", zz->Proc);
/* Do the communication. */
Zoltan_Comm_Do( plan2, TAG2, (char *) old_adjncy, sizeof(indextype), (char *) *adjncy);
if (ewgt_dim){
Zoltan_Comm_Do( plan2, TAG3, (char *) old_adjwgt, ewgt_dim*sizeof(weighttype), (char *) *adjwgt);
}
if (zz->Debug_Level >= ZOLTAN_DEBUG_ALL)
printf("[%1d] Debug: Finished edge-based communication.\n", zz->Proc);
/* Free the comm. plan for edge data */
Zoltan_Comm_Destroy(&plan2);
} /* end of use_graph */
/* Free data structures */
ZOLTAN_FREE(&proclist);
ZOLTAN_FREE(&proclist2);
ZOLTAN_FREE(&old_vtxdist);
ZOLTAN_FREE(&old_xadj);
ZOLTAN_FREE(&old_adjncy);
ZOLTAN_FREE(&old_vwgt);
ZOLTAN_FREE(&old_vsize);
ZOLTAN_FREE(&old_adjwgt);
ZOLTAN_FREE(&old_xyz);
ZOLTAN_TRACE_EXIT(zz, yo);
return ZOLTAN_OK;
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,69 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifndef __SCOTCH_INTERFACE_H
#define __SCOTCH_INTERFACE_H
#include <limits.h>
#include "zoltan_comm.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
int Zoltan_Scotch(
ZZ *, float *, int *, ZOLTAN_ID_PTR *, ZOLTAN_ID_PTR *,
int **, int **, int *, ZOLTAN_ID_PTR *, ZOLTAN_ID_PTR *,
int **, int **);
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif
#endif

View File

@ -0,0 +1,67 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifndef __SCOTCH_INTERFACE_PARAMS_H
#define __SCOTCH_INTERFACE_PARAMS_H
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
/********** parameters structure for Scotch methods **********/
static PARAM_VARS Scotch_params[] = {
{ "SCOTCH_METHOD", NULL, "STRING", 0 },
{ "SCOTCH_TYPE", NULL, "STRING", 0 },
{ "SCOTCH_STRAT", NULL, "STRING", 0 },
{ "SCOTCH_STRAT_FILE", NULL, "STRING", 0 },
{ NULL, NULL, NULL, 0 } };
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,465 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
#include <ctype.h>
#include "zz_const.h"
#include "zz_util_const.h"
#include "all_allo_const.h"
#include "params_const.h"
#include "order_const.h"
#include "third_library.h"
#include "third_library_params.h"
/**********************************************************/
/* Interface routine for Graph methods. */
/**********************************************************/
int Zoltan_Graph(
ZZ *zz, /* Zoltan structure */
float *part_sizes, /* Input: Array of size zz->Num_Global_Parts
containing the percentage of work to be
assigned to each part. */
int *num_imp, /* number of objects to be imported */
ZOLTAN_ID_PTR *imp_gids, /* global ids of objects to be imported */
ZOLTAN_ID_PTR *imp_lids, /* local ids of objects to be imported */
int **imp_procs, /* list of processors to import from */
int **imp_to_part, /* list of partitions to which imported objects are
assigned. */
int *num_exp, /* number of objects to be exported */
ZOLTAN_ID_PTR *exp_gids, /* global ids of objects to be exported */
ZOLTAN_ID_PTR *exp_lids, /* local ids of objects to be exported */
int **exp_procs, /* list of processors to export to */
int **exp_to_part /* list of partitions to which exported objects are
assigned. */
)
{
static char* yo = "Zoltan_Graph";
char *defaultMethod= "PHG";
char package[MAX_PARAM_STRING_LEN];
int rc;
strcpy(package, defaultMethod);
Zoltan_Bind_Param(Graph_Package_params, "GRAPH_PACKAGE", package);
Zoltan_Assign_Param_Vals(zz->Params, Graph_Package_params, zz->Debug_Level,
zz->Proc, zz->Debug_Proc);
if (!strcasecmp(package, "PARMETIS")){
#ifdef ZOLTAN_PARMETIS
rc = Zoltan_ParMetis(zz, part_sizes, num_imp, imp_gids, imp_lids,
imp_procs, imp_to_part,
num_exp, exp_gids, exp_lids, exp_procs, exp_to_part);
#else
ZOLTAN_PRINT_ERROR(zz->Proc, yo,
"ParMETIS partitioning was requested but "
"Zoltan was compiled without ParMETIS.\n");
rc = ZOLTAN_FATAL;
#endif /* ZOLTAN_PARMETIS */
}
else if (!strcasecmp(package, "METIS")){
#ifdef ZOLTAN_METIS
rc = Zoltan_ParMetis(zz, part_sizes, num_imp, imp_gids, imp_lids,
imp_procs, imp_to_part,
num_exp, exp_gids, exp_lids, exp_procs, exp_to_part);
#else
ZOLTAN_PRINT_ERROR(zz->Proc, yo,
"METIS partitioning was requested but "
"Zoltan was compiled without METIS.\n");
rc = ZOLTAN_FATAL;
#endif /* ZOLTAN_METIS */
}
else if (!strcasecmp(package, "SCOTCH")){
#ifdef ZOLTAN_SCOTCH
rc = Zoltan_Scotch(zz, part_sizes, num_imp, imp_gids, imp_lids,
imp_procs, imp_to_part,
num_exp, exp_gids, exp_lids, exp_procs, exp_to_part);
#else
ZOLTAN_PRINT_ERROR(zz->Proc, yo,
"Scotch partitioning was requested but "
"Zoltan was compiled without Scotch.\n");
rc = ZOLTAN_FATAL;
#endif /* ZOLTAN_SCOTCH */
}
else if (!strcasecmp(package, "ZOLTAN") ||
!strcasecmp(package, "PHG")) {
rc = Zoltan_PHG(zz, part_sizes, num_imp, imp_gids, imp_lids,
imp_procs, imp_to_part,
num_exp, exp_gids, exp_lids, exp_procs, exp_to_part);
}
else{
ZOLTAN_PRINT_ERROR(zz->Proc, yo,
"Invalid value for GRAPH_PACKAGE parameter\n");
rc = ZOLTAN_FATAL;
}
return rc;
}
/*********************************************************************/
/* Graph_Package parameter routine */
/*********************************************************************/
int Zoltan_Graph_Package_Set_Param(
char *name, /* name of variable */
char *val) /* value of variable */
{
int status, i;
PARAM_UTYPE result; /* value returned from Check_Param */
int index; /* index returned from Check_Param */
char *valid_methods[] = {
"PARMETIS", "PHG", "ZOLTAN", "SCOTCH", "METIS",
NULL };
status = Zoltan_Check_Param(name, val, Graph_Package_params,
&result, &index);
if (status == 0){
/* OK so far, do sanity check of parameter values */
if (strcmp(name, "GRAPH_PACKAGE") == 0){
status = 2;
for (i=0; valid_methods[i] != NULL; i++){
if (strcmp(val, valid_methods[i]) == 0){
status = 0;
break;
}
}
}
}
return(status);
}
#define MEMFREE(ptr) do { if (ptr) ZOLTAN_FREE(&(ptr)); } while (0);
void Zoltan_Third_Exit(ZOLTAN_Third_Graph *gr, ZOLTAN_Third_Geom *geo,
ZOLTAN_Third_Part *prt, ZOLTAN_Third_Vsize *vsp,
ZOLTAN_Output_Part *part, ZOLTAN_Output_Order *ord)
{
if (gr) {
Zoltan_Matrix2d_Free(&gr->graph.mtx);
MEMFREE(gr->vwgt);
MEMFREE(gr->vtxdist);
MEMFREE(gr->xadj);
MEMFREE(gr->adjncy);
MEMFREE(gr->ewgts);
MEMFREE(gr->float_ewgts);
MEMFREE(gr->adjproc);
Zoltan_ZG_Free(&gr->graph);
}
if (geo) {
MEMFREE(geo->xyz);
}
if (prt) {
MEMFREE(prt->part);
MEMFREE(prt->input_part);
MEMFREE(prt->part_orig);
if (prt->part_sizes != prt->input_part_sizes)
MEMFREE(prt->part_sizes);
if (sizeof(realtype) != sizeof(float))
MEMFREE(prt->input_part_sizes);
}
if (vsp) {
if (!vsp->vsize_malloc) {
MEMFREE(vsp->vsize);
}
MEMFREE(vsp->vsizeBACKUP);
}
if (ord) {
MEMFREE(ord->sep_sizes);
MEMFREE(ord->rank);
MEMFREE(ord->iperm);
}
}
int Zoltan_Third_Init(ZOLTAN_Third_Graph *gr, ZOLTAN_Third_Part *prt, ZOLTAN_Third_Vsize *vsp, ZOLTAN_Output_Part *part,
ZOLTAN_ID_PTR *imp_gids, ZOLTAN_ID_PTR *imp_lids, int **imp_procs, int **imp_to_part,
ZOLTAN_ID_PTR *exp_gids, ZOLTAN_ID_PTR *exp_lids, int **exp_procs, int **exp_to_part)
{
memset (gr, 0, sizeof(ZOLTAN_Third_Graph));
memset (prt, 0, sizeof(ZOLTAN_Third_Part));
memset (vsp, 0, sizeof(ZOLTAN_Third_Vsize));
memset (part, 0, sizeof(ZOLTAN_Output_Part));
/* Initialize return-argument arrays to return arguments so that F90 works. */
part->imp_gids = imp_gids;
part->imp_lids = imp_lids;
part->imp_procs = imp_procs;
part->imp_part = imp_to_part;
part->exp_gids = exp_gids;
part->exp_lids = exp_lids;
part->exp_procs = exp_procs;
part->exp_part = exp_to_part;
part->num_imp = part->num_exp = -1;
/* Most ParMetis methods use only graph data */
gr->get_data = 1;
return (ZOLTAN_OK);
}
/* export to user variables */
int Zoltan_Third_Export_User(ZOLTAN_Output_Part *part,
int *num_imp, ZOLTAN_ID_PTR *imp_gids, ZOLTAN_ID_PTR *imp_lids, int **imp_procs, int **imp_to_part,
int *num_exp, ZOLTAN_ID_PTR *exp_gids, ZOLTAN_ID_PTR *exp_lids, int **exp_procs, int **exp_to_part)
{
/* Write results in user variables */
*num_imp = part->num_imp;
*imp_gids = *(part->imp_gids);
*imp_lids = *(part->imp_lids);
*imp_procs = *(part->imp_procs);
*imp_to_part = *(part->imp_part);
*num_exp = part->num_exp;
*exp_gids = *(part->exp_gids);
*exp_lids = *(part->exp_lids);
*exp_procs = *(part->exp_procs);
*exp_to_part = *(part->exp_part);
return (ZOLTAN_OK);
}
int Zoltan_matrix_Print(Zoltan_matrix *m, char *s)
{
int i, j, k;
float *wgts;
if (s) fprintf(stderr,"Zoltan_matrix, %s\n",s);
fprintf(stderr,"\nOptions: enforceSquare %d, pinwgtop %s, randomize %d, pinwgt %d\n",
m->opts.enforceSquare,
((m->opts.pinwgtop == 0) ? "add weight" : ((m->opts.pinwgtop == 1) ? "max weight" : "cmp weight")),
m->opts.randomize, m->opts.pinwgt);
fprintf(stderr,"Options: local %d, final_output %d, symmetrize %d keep_distribution %d speed %s\n",
m->opts.local, m->opts.final_output, m->opts.symmetrize, m->opts.keep_distribution,
((m->opts.speed == 0) ? "full dd" : ((m->opts.speed == 1) ? "fast" : "no redist")));
fprintf(stderr,"redist %d, completed %d, bipartite %d\n", m->redist, m->completed, m->bipartite);
fprintf(stderr,"globalX " ZOLTAN_GNO_SPEC ", globalY " ZOLTAN_GNO_SPEC ", nY %d, nY_ori %d, ywgtdim %d, nPins %d\n",
m->globalX, m->globalY, m->nY, m->nY_ori, m->ywgtdim, m->nPins);
fprintf(stderr,"Edges and non-zeroes:\n");
wgts = m->pinwgt;
if (m->yGNO && m->pinGNO){
for (i=0; i < m->nY; i++){
fprintf(stderr, ZOLTAN_GNO_SPEC ": ",m->yGNO[i]);
for (j=m->ystart[i]; j < m->ystart[i+1]; j++){
fprintf(stderr, ZOLTAN_GNO_SPEC " ", m->pinGNO[j]);
if (wgts && (m->pinwgtdim > 0)){
fprintf(stderr,"(");
for (k=0; k < m->pinwgtdim; k++){
fprintf(stderr,"%f ",*wgts++);
}
fprintf(stderr,") ");
}
}
fprintf(stderr,"\n");
}
}
else{
fprintf(stderr,"not set");
}
fprintf(stderr,"\n");
fflush(stderr);
return ZOLTAN_OK;
}
int Zoltan_ZG_Print(ZZ *zz, ZG *gr, char *s)
{
int i, me, proc;
Zoltan_matrix_2d *m2d = &gr->mtx;
Zoltan_matrix *m = &m2d->mtx;
int nproc_x = m2d->comm->nProc_x;
int nproc_y = m2d->comm->nProc_y;
me = zz->Proc;
for (proc=0; proc < zz->Num_Proc; proc++){
if (proc == me){
if (proc == 0) fprintf(stderr,"\n%s\n",s);
fprintf(stderr,"Process: %d) flags: bipartite %d fixObj %d, fixed vertices buffer %p:\n",
zz->Proc, gr->bipartite, gr->fixObj, (void *)gr->fixed_vertices);
fprintf(stderr,"GNO distribution in x direction: ");
if (m2d->dist_x){
for (i=0; i <= nproc_x; i++){
fprintf(stderr, ZOLTAN_GNO_SPEC " ",m2d->dist_x[i]);
}
}
else{
fprintf(stderr,"not set");
}
fprintf(stderr,"\nGNO distribution in y direction: ");
if (m2d->dist_y){
for (i=0; i <= nproc_y; i++){
fprintf(stderr, ZOLTAN_GNO_SPEC " ",m2d->dist_y[i]);
}
}
else{
fprintf(stderr,"not set");
}
Zoltan_matrix_Print(m, NULL);
fflush(stderr);
}
MPI_Barrier(MPI_COMM_WORLD);
MPI_Barrier(MPI_COMM_WORLD);
}
MPI_Barrier(MPI_COMM_WORLD);
MPI_Barrier(MPI_COMM_WORLD);
return ZOLTAN_OK;
}
int Zoltan_Third_Graph_Print(ZZ *zz, ZOLTAN_Third_Graph *gr, char *s)
{
int i, me, proc;
indextype numvtx, offset, j;
me = zz->Proc;
for (proc=0; proc < zz->Num_Proc; proc++){
if (proc == me){
if (proc == 0) fprintf(stderr,"\n%s\n",s);
fprintf(stderr,"Process: %d) graph type %d, check graph %d, final output %d, showMoveVol %d, scatter %d\n",
me, gr->graph_type, gr->check_graph, gr->final_output, gr->showMoveVol, gr->scatter);
fprintf(stderr,"scatter min %d, get data %d, obj wgt dim %d, edge wgt dim %d\n",
gr->scatter_min, gr->get_data, gr->obj_wgt_dim, gr->edge_wgt_dim);
fprintf(stderr,"num obj %d, num obj orig %d, num edges %d\n",
gr->num_obj, gr->num_obj_orig, gr->num_edges);
if (gr->vtxdist){
numvtx = gr->vtxdist[proc+1] - gr->vtxdist[proc];
offset = gr->vtxdist[proc];
fprintf(stderr,"Num vertices: " TPL_IDX_SPEC "\n",numvtx);
if (gr->xadj){
fprintf(stderr,"Num edges: " TPL_IDX_SPEC "\n",gr->xadj[numvtx]);
}
for (i=0; i < numvtx; i++){
fprintf(stderr,TPL_IDX_SPEC ": ",i+offset);
if (gr->xadj){
for (j=gr->xadj[i];j < gr->xadj[i+1]; j++){
if (gr->adjncy){
fprintf(stderr,"gid " TPL_IDX_SPEC,gr->adjncy[j]);
}
if (gr->adjproc){
fprintf(stderr," proc %d ",gr->adjproc[j]);
}
}
}
else{
fprintf(stderr,"adjacency info is null");
}
fprintf(stderr,"\n");
}
}
fflush(stderr);
}
MPI_Barrier(MPI_COMM_WORLD);
MPI_Barrier(MPI_COMM_WORLD);
}
MPI_Barrier(MPI_COMM_WORLD);
MPI_Barrier(MPI_COMM_WORLD);
return ZOLTAN_OK;
}
/*
** Copy of Zoltan_Order_Init_Tree in order_tools.c which uses TPL data types
*/
#define CHECK_ZOLTAN_FREE(ptr) do { if ((ptr) != NULL) ZOLTAN_FREE(&(ptr)); } while (0)
int Zoltan_TPL_Order_Init_Tree (struct Zoltan_TPL_Order_Struct *order, indextype blocknbr, indextype leavesnbr)
{
Zoltan_TPL_Order_Free_Struct(order);
order->ancestor = (indextype *) ZOLTAN_MALLOC(blocknbr*sizeof(indextype));
order->start = (indextype *) ZOLTAN_MALLOC((blocknbr+1)*sizeof(indextype));
order->leaves = (indextype *) ZOLTAN_MALLOC((leavesnbr+1)*sizeof(indextype));
order->needfree = 1;
if ((order->ancestor == NULL) || (order->start == NULL) || (order->leaves == NULL)) {
Zoltan_TPL_Order_Free_Struct(order);
return (ZOLTAN_MEMERR);
}
return (ZOLTAN_OK);
}
void Zoltan_TPL_Order_Free_Struct(struct Zoltan_TPL_Order_Struct *order)
{
if (order->needfree == 0)
return;
CHECK_ZOLTAN_FREE(order->start);
CHECK_ZOLTAN_FREE(order->ancestor);
CHECK_ZOLTAN_FREE(order->leaves);
order->needfree = 0;
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,214 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifndef __THIRD_LIBRARY_H
#define __THIRD_LIBRARY_H
#include <limits.h>
#include "zoltan_comm.h"
#include "third_library_const.h"
#include "graph.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
#define INT_EPSILON (1e-5) /* How close we need to be to say it's an integer */
/* Macro for error handling */
#define ZOLTAN_PARMETIS_ERROR(error,str) {ierr = error ; \
ZOLTAN_PRINT_ERROR(zz->Proc, yo, str) ; goto End ;}
#define ZOLTAN_THIRD_ERROR(error,str) { \
ZOLTAN_PRINT_ERROR(zz->Proc, yo , str) ; return(error) ;}
/* Structure that defines a graph for third party libraries like ParMetis. */
typedef struct ZOLTAN_Third_Graph_ {
int graph_type; /* Type of the graph */
int check_graph; /* We have to check graph consistency */
int final_output; /* Do some output computations */
int showMoveVol; /* How works the final output */
int scatter; /* Graph has been scattered */
int scatter_min; /* Minimum level of scatter */
int get_data; /* Construct edge datas */
int obj_wgt_dim; /* Number of weights by vertex */
int edge_wgt_dim; /* Number of weights by edge */
int num_obj; /* Local number of vertices */
int num_obj_orig; /* Local number of vertices in original graph */
int num_edges; /* Local number of edges */
indextype *vtxdist; /* How vertices are distributed */
indextype * xadj; /* Indexes on adjency array */
indextype *adjncy; /* adjency array (CSR) */
weighttype * vwgt; /* Array of vertex weights */
weighttype * ewgts; /* Array of edge weights */
float * float_ewgts;
int * adjproc; /* Array of procs ? */
ZOLTAN_COMM_OBJ *comm_plan; /* Communication plan used by scattering process */
ZG graph;
} ZOLTAN_Third_Graph;
/* Structure that defines a geometry for third party libraries like ParMetis. */
typedef struct ZOLTAN_Third_Geom_ {
int ndims; /* Number of dimensions */
realtype *xyz; /* Coordinates */
} ZOLTAN_Third_Geom;
/* Structure that defines a partition for third party libraries like ParMetis. */
typedef struct ZOLTAN_Third_Part_ {
indextype *part; /* Current partition */
indextype *input_part;
indextype *part_orig;
realtype *part_sizes;
realtype *input_part_sizes;
} ZOLTAN_Third_Part;
typedef struct ZOLTAN_Third_Vsize_ {
int vsize_malloc;
indextype *vsize;
indextype *vsizeBACKUP;
} ZOLTAN_Third_Vsize;
/* Structure that defines an ordering output for third party libraries like ParMetis. */
typedef struct ZOLTAN_Output_Order_ {
int num_part;
indextype start_index;
indextype *rank; /* rank[i] is the rank of gids[i] */
indextype *iperm; /* inverse permutation of rank */
ZOOS *order_opt; /* ordering options */
ZTPL_OS *order_info; /* ordering info */
indextype *sep_sizes;
} ZOLTAN_Output_Order;
/* Structure that describes a partitioning output in Zoltan lingo
for third party libraries like ParMetis. */
typedef struct ZOLTAN_Output_Part_ {
int compute_only_part_changes;
int num_imp;
ZOLTAN_ID_PTR* imp_gids;
ZOLTAN_ID_PTR* imp_lids;
int **imp_procs;
int **imp_part;
int num_exp;
ZOLTAN_ID_PTR *exp_gids;
ZOLTAN_ID_PTR *exp_lids;
int **exp_procs;
int **exp_part;
} ZOLTAN_Output_Part;
/*****************************
* Functions which can be used to interface with third party libraries
****************************************************************************/
/* Construct graph and associated datas in order to call third library */
int Zoltan_Preprocess_Graph(
ZZ *zz, /* Zoltan structure */
ZOLTAN_ID_PTR *global_ids,
ZOLTAN_ID_PTR *local_ids,
ZOLTAN_Third_Graph *gr, /* Graph for third part libs */
ZOLTAN_Third_Geom *geo,
ZOLTAN_Third_Part *prt,
ZOLTAN_Third_Vsize *vsp
);
/* Activate timers if requested */
int Zoltan_Preprocess_Timer(ZZ *zz, int *use_timer);
/* Display timing informations */
void Zoltan_Third_DisplayTime(ZZ* zz, double* times);
/* Initialize Zoltan internal structures */
int Zoltan_Third_Init(ZOLTAN_Third_Graph *gr, ZOLTAN_Third_Part *prt, ZOLTAN_Third_Vsize *vsp, ZOLTAN_Output_Part *part,
ZOLTAN_ID_PTR *imp_gids, ZOLTAN_ID_PTR *imp_lids, int **imp_procs, int **imp_to_part,
ZOLTAN_ID_PTR *exp_gids, ZOLTAN_ID_PTR *exp_lids, int **exp_procs, int **exp_to_part);
/* export to user variables */
int Zoltan_Third_Export_User(ZOLTAN_Output_Part *part,
int *num_imp, ZOLTAN_ID_PTR *imp_gids, ZOLTAN_ID_PTR *imp_lids, int **imp_procs, int **imp_to_part,
int *num_exp, ZOLTAN_ID_PTR *exp_gids, ZOLTAN_ID_PTR *exp_lids, int **exp_procs, int **exp_to_part);
/* Free temporary datas */
void Zoltan_Third_Exit(ZOLTAN_Third_Graph *gr, ZOLTAN_Third_Geom *geo,
ZOLTAN_Third_Part *prt, ZOLTAN_Third_Vsize *vsp,
ZOLTAN_Output_Part *part, ZOLTAN_Output_Order *ord);
/* Do some postprocesing in order to exploit third party results in Zoltan */
int Zoltan_Postprocess_Graph(
ZZ *zz, /* Zoltan structure */
ZOLTAN_ID_PTR global_ids,
ZOLTAN_ID_PTR local_ids,
ZOLTAN_Third_Graph *gr, /* Graph for third part libs */
ZOLTAN_Third_Geom *geo,
ZOLTAN_Third_Part *prt,
ZOLTAN_Third_Vsize *vsp,
ZOLTAN_Output_Order *ord,
ZOLTAN_Output_Part *part);
int
Zoltan_Postprocess_FinalOutput (ZZ* zz, ZOLTAN_Third_Graph *gr,
ZOLTAN_Third_Part *prt, ZOLTAN_Third_Vsize *vsp,
int use_timers, realtype itr);
int Zoltan_matrix_Print(Zoltan_matrix *m, char *s);
int Zoltan_Third_Graph_Print(ZZ *zz, ZOLTAN_Third_Graph *gr, char *s);
int Zoltan_ZG_Print(ZZ *zz, ZG *gr, char *s);
int Zoltan_Check_TPL_Data_Sizes(ZZ *, int);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,279 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifndef __THIRD_LIBRARY_CONST_H
#define __THIRD_LIBRARY_CONST_H
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
#include <stdint.h>
#include <sys/types.h>
#include <float.h>
#include "zoltan_util.h"
/*****************************************************************************/
/* Include appropriate files for TPLs */
#ifdef ZOLTAN_METIS
#include "metis.h"
#define __metis__ 1
#else
#define __metis__ 0
#endif
#ifdef ZOLTAN_PARMETIS
#include "parmetis.h"
#define __parmetis__ 1
#else
#define __parmetis__ 0
#endif
#ifdef ZOLTAN_PTSCOTCH
#include "ptscotch.h"
#define __ptscotch__ 1
#else
#define __ptscotch__ 0
#endif
#ifdef ZOLTAN_SCOTCH
#ifndef ZOLTAN_PTSCOTCH
#include "scotch.h"
#endif
#define __scotch__ 1
#else
#define __scotch__ 0
#endif
/****************************************************************************/
/* TPL-Specific settings for data types */
/*
* "indextype" is the type used for global numbers and indices in the graph
* data structure.
* "weighttype" is the type used for weights.
*
* If there are no third party graph/ordering libraries, let indextype be
* ZOLTAN_GNO_TYPE and let "weighttype" be float.
*
* If there is only one third party library used for graph algorithms,
* define indextype and weighttype to match the types used by that library.
*
* If more than one library is linked in, arbitrarily choose one.
* Check for compatibility between the libraries here; all should use the same
* size integer for indices.
*
* At runtime, if
* either the indextype or weighttype is not compatible with the graph library
* API, return an error.
*/
#define TPL_SCOTCH_DATATYPES 1
#define TPL_METIS_DATATYPES 2
#define TPL_ZOLTAN_DATATYPES 3
#undef TPL_USE_DATATYPE
#undef indextype
#undef weighttype
/* Select the data types to use */
#if __parmetis__ + __metis__ + __ptscotch__ + __scotch__ == 0
/* No graph TPLs used; use Zoltan values */
#define TPL_USE_DATATYPE TPL_ZOLTAN_DATATYPES
#define indextype ZOLTAN_GNO_TYPE
#define weighttype float
#define realtype float
#define TPL_FLOAT_WEIGHT
#define MAX_WGT_SUM (FLT_MAX/8)
#define TPL_IDX_SPEC ZOLTAN_GNO_SPEC
#define TPL_WGT_SPEC "%f"
#elif (__ptscotch__ + __scotch__ > 0) && (__parmetis__ + __metis__ == 0)
/* Using only Scotch/PTScotch */
#define TPL_USE_DATATYPE TPL_SCOTCH_DATATYPES
#elif (__parmetis__ + __metis__ > 0) && (__ptscotch__ + __scotch__ == 0)
/* Using only METIS/ParMETIS */
#define TPL_USE_DATATYPE TPL_METIS_DATATYPES
#else
/* Using both METIS/ParMETIS and Scotch/PTScotch; let METIS datatypes rule */
#define TPL_USE_DATATYPE TPL_METIS_DATATYPES
#endif
#if TPL_USE_DATATYPE == TPL_METIS_DATATYPES
#if (PARMETIS_MAJOR_VERSION == 4 || METIS_VER_MAJOR == 5)
#define indextype idx_t
#define weighttype idx_t
#define realtype real_t
#define TPL_INTEGRAL_WEIGHT
#define MAX_WGT_SUM (IDX_MAX/8)
#define TPL_IDX_SPEC "%"PRIDX
#define TPL_WGT_SPEC "%"PRIDX
#else
/* Assume IDXTYPE_INT in ParMETIS v3.x */
#ifndef IDXTYPE_INT
/* typedef short idxtype; IDXTYPE_INT is not defined in parmetis.h */
#error "ParMETIS short idxtype is not supported in Zoltan; define IDXTYPE_INT in parmetis.h."
#endif
#define indextype idxtype
#define weighttype idxtype
#define realtype float
#define TPL_INTEGRAL_WEIGHT
#define MAX_WGT_SUM (INT_MAX/8)
#define TPL_IDX_SPEC "%d"
#define TPL_WGT_SPEC "%d"
#define IDXTYPEWIDTH 32
#endif
#elif TPL_USE_DATATYPE == TPL_SCOTCH_DATATYPES
#define indextype SCOTCH_Num
#define weighttype SCOTCH_Num
#define realtype float
#define MAX_WGT_SUM (SCOTCH_NUMMAX/8)
#ifdef SCOTCH_NUMSTRING /* SCOTCH_NUMSTRING is only in later Scotch versions */
#define TPL_IDX_SPEC SCOTCH_NUMSTRING
#define TPL_WGT_SPEC SCOTCH_NUMSTRING
#else
#define TPL_IDX_SPEC "%d"
#define TPL_WGT_SPEC "%d"
#endif
#define TPL_INTEGRAL_WEIGHT
#endif
/**************************************************************************/
/* Graph types, used as mask to set bit in graph_type */
#define NO_GRAPH 0
#define LOCAL_GRAPH 1
#define TRY_FAST 2
#define FORCE_FAST 3
#define UNSYMMETRIC 4
/* At this time, means A+At */
#define SYMMETRIZE 5
#define SET_NO_GRAPH(gtype) do { (*(gtype)) &= ~(1<<NO_GRAPH); (*(gtype)) &= ~(1<<LOCAL_GRAPH); } while (0)
#define SET_GLOBAL_GRAPH(gtype) do { (*(gtype)) &= ~(1<<LOCAL_GRAPH); (*(gtype)) &= ~(1<<NO_GRAPH); } while (0)
#define SET_LOCAL_GRAPH(gtype) do { (*(gtype)) |= (1<<LOCAL_GRAPH); (*(gtype)) &= ~(1<<NO_GRAPH); } while (0)
#define IS_NO_GRAPH(gtype) ((!((gtype)&(1<<LOCAL_GRAPH))) && (((gtype)&(1<<NO_GRAPH))))
#define IS_GLOBAL_GRAPH(gtype) ((!((gtype)&(1<<NO_GRAPH))) && (!((gtype)&(1<<LOCAL_GRAPH))))
#define IS_LOCAL_GRAPH(gtype) ((!((gtype)&(1<<NO_GRAPH))) && (((gtype)&(1<<LOCAL_GRAPH))))
/* Misc. defs to be used with MPI */
#define TAG1 32001
#define TAG2 32002
#define TAG3 32003
#define TAG4 32004
#define TAG5 32005
#define TAG6 32006
#define TAG7 32007
/* Zoltan function prototypes */
extern int Zoltan_Graph_Package_Set_Param(char *, char *);
#ifdef ZOLTAN_PARMETIS
extern int Zoltan_ParMetis_Set_Param(char *, char *);
#endif /* ZOLTAN_PARMETIS */
#ifdef ZOLTAN_SCOTCH
extern int Zoltan_Scotch_Set_Param(char *, char *);
#endif /* ZOLTAN_SCOTCH */
extern int Zoltan_Third_Set_Param(char *, char *);
extern int Zoltan_Build_Graph(struct Zoltan_Struct *zz, int *graph_type, int check_graph,
int num_obj, ZOLTAN_ID_PTR global_ids, ZOLTAN_ID_PTR local_ids,
int obj_wgt_dim, int * edge_wgt_dim,
ZOLTAN_GNO_TYPE **vtxdist, int **xadj, ZOLTAN_GNO_TYPE **adjncy, float **ewgts,
int **adjproc);
extern int Zoltan_Get_Num_Edges_Per_Obj(struct Zoltan_Struct *, int, ZOLTAN_ID_PTR,
ZOLTAN_ID_PTR, int **, int *, int *);
/*==========================================================================
* The ZOS structure copied from order/order_const.h, but using TPL datatypes.
*/
struct Zoltan_TPL_Order_Struct {
indextype needfree;
indextype nbr_objects; /* # of objects (local) */
ZOLTAN_ID_PTR gids; /* ptr to list of global ids */
ZOLTAN_ID_PTR lids; /* ptr to list of local ids */
indextype *rank; /* rank[i] is the rank of gids[i] */
ZOLTAN_ID_PTR gidrank;
indextype *iperm;
indextype start_index;
char method[MAX_PARAM_STRING_LEN]; /* Ordering method used */
char order_type[MAX_PARAM_STRING_LEN]; /* Ordering method used */
/* Elimination Tree */
indextype nbr_blocks; /* Out: number of ordering blocks */
indextype *start; /* Out: start[i] is the first vertex of block i */
indextype *ancestor; /* Out: father of block i */
indextype *leaves; /* Out: list of all leaves */
indextype nbr_leaves; /* Number of leaves */
indextype *vtxdist; /* How vertices are distributed accross processors */
/* Deprecated */
indextype num_separators; /* Optional: # of separators. */
indextype *sep_sizes; /* Optional: Separator sizes. */
};
typedef struct Zoltan_TPL_Order_Struct ZTPL_OS;
int Zoltan_TPL_Order_Init_Tree (struct Zoltan_TPL_Order_Struct *order, indextype blocknbr, indextype leavesnbr);
void Zoltan_TPL_Order_Free_Struct(struct Zoltan_TPL_Order_Struct *order);
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif
#endif

View File

@ -0,0 +1,71 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifndef __THIRD_LIBRARY_PARAMS_H
#define __THIRD_LIBRARY_PARAMS_H
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
#include "zz_const.h"
#include "zz_util_const.h"
#include "params_const.h"
/********** parameters structure used by PHG, ParMetis and Jostle **********/
static PARAM_VARS Graph_Package_params[] = {
{ "GRAPH_PACKAGE", NULL, "STRING", 0 },
{ "ORDER_TYPE", NULL, "STRING", 0 },
{ NULL, NULL, NULL, 0 } };
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,89 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifndef __THIRD_LIBRARY_TOOLS_H
#define __THIRD_LIBRARY_TOOLS_H
#include <limits.h>
#include "zoltan_comm.h"
#include "third_library_const.h"
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
/* Misc. local constants */
#define CHUNKSIZE 20 /* Number of nodes to allocate in initial chunk. */
#define REALLOC_FACTOR 1.5 /* Increase size by this factor if too small. */
/* Data structures used in ParMetis interface routines */
/* An array of this data structure works with a parallel array of
* ZOLTAN_ID_PTR called proc_list_nbor containing the global IDs of the
* neighboring object.
* This separate array is needed to prevent individual mallocs of
* neighboring global IDs.
*/
struct Edge_Info {
ZOLTAN_ID_PTR my_gid; /* Pointer to the Global id of local vtx */
int my_gno; /* Global number of local vtx */
int nbor_proc; /* Proc id for the neighboring proc */
int *adj; /* Pointer to adjcny array */
};
struct Hash_Node {
ZOLTAN_ID_PTR gid; /* Pointer to a Global id */
int gno; /* Global number */
struct Hash_Node * next;
};
#ifdef __cplusplus
}
#endif
#endif /* __THIRD_LIBRARY_TOOLS_H */

View File

@ -0,0 +1,574 @@
/*
* @HEADER
*
* ***********************************************************************
*
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
* Copyright 2012 Sandia Corporation
*
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
* the U.S. Government retains certain rights in this software.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Corporation nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Questions? Contact Karen Devine kddevin@sandia.gov
* Erik Boman egboman@sandia.gov
*
* ***********************************************************************
*
* @HEADER
*/
#ifdef __cplusplus
/* if C++, define the rest of this header file as extern C */
extern "C" {
#endif
#include "zz_util_const.h"
#include "third_library_const.h"
#include "third_library_tools.h"
#include "graph_util.h"
/* comparison routine for bsearch */
static int Zoltan_Compare_Indextypes(const void *key, const void *arg);
#include "zz_sort.h"
/*********************************************************************/
/* Verify ParMetis graph structure. */
/* */
/* Input parameter graph_type specifies the type of graph: */
/* LOCAL_GRAPH - each proc owns a local METIS style graph */
/* GLOBAL_GRAPH - the procs share a global ParMETIS graph */
/* */
/* Input parameter check_graph specifies the level of verification: */
/* 0 - perform no checks at all */
/* 1 - verify on-processor part of graph */
/* 2 - verify complete graph (requires communication) */
/* */
/* Input parameter output_level specifies the level of verbosity: */
/* 0 - suppress warnings */
/* 1 - print summary of warnings */
/* 2 - detailed output for each warning */
/* */
/* Output: an error code (the same on all procs) */
/* */
/* Fatal error : */
/* - non-symmetric graph */
/* - incorrect vertex number */
/* - negative vertex or edge weight */
/* */
/* Warning : */
/* - no vertices or no edges in graph */
/* - zero sum of vertex or edge weights */
/* - self-edge */
/* - multiple edges between a pair of vertices */
/* - singletons (vertices with no edges) */
/* - non-symmetric edge weights */
/* */
/*********************************************************************/
int Zoltan_Verify_Graph(MPI_Comm comm, indextype *vtxdist, indextype *xadj,
indextype *adjncy, weighttype *vwgt, weighttype *adjwgt,
int vwgt_dim, int ewgt_dim,
int graph_type, int check_graph, int output_level)
{
int flag, cross_edges = 0, mesg_size, sum;
int ierr; /* Error in the graph; always return the worst ierr found */
int runerr;/* Error running this routine */
int nprocs, proc, *proclist, errors, global_errors;
int *perm=NULL;
int free_adjncy_sort=0;
ZOLTAN_COMM_OBJ *comm_plan;
static char *yo = "Zoltan_Verify_Graph";
char msg[256];
ZOLTAN_GNO_TYPE num_obj;
int nrecv;
indextype *ptr, *ptr1, *ptr2;
indextype global_i, global_j;
indextype *sendgno=NULL, *recvgno=NULL, *adjncy_sort=NULL;
weighttype *sendwgt, *recvwgt;
ZOLTAN_GNO_TYPE num_duplicates, num_singletons;
ZOLTAN_GNO_TYPE num_selfs, nedges, global_sum, num_zeros;
ZOLTAN_GNO_TYPE i, j, ii, k;
MPI_Datatype zoltan_gno_mpi_type;
ierr = ZOLTAN_OK;
runerr = ZOLTAN_OK;
zoltan_gno_mpi_type = Zoltan_mpi_gno_type();
/* Make sure all procs have same value of check_graph. */
MPI_Allreduce(&check_graph, &i, 1, MPI_INT, MPI_MAX, comm);
check_graph = i;
if (check_graph == 0) /* perform no error checking at all */
return ierr;
/* Get number of procs and my rank */
MPI_Comm_size(comm, &nprocs);
MPI_Comm_rank(comm, &proc);
/* Check number of vertices (objects) */
num_obj = (ZOLTAN_GNO_TYPE)(vtxdist[proc+1] - vtxdist[proc]);
MPI_Reduce(&num_obj, &global_sum, 1, zoltan_gno_mpi_type, MPI_SUM, 0, comm);
if ((proc==0) && (global_sum==0)){
if (ierr == ZOLTAN_OK) ierr = ZOLTAN_WARN;
if (output_level>0)
ZOLTAN_PRINT_WARN(proc, yo, "No vertices in graph.");
}
/* Verify that vertex weights are non-negative */
num_zeros = 0;
if (vwgt_dim){
for (i=0; i<num_obj; i++){
sum = 0;
for (k=0; k<vwgt_dim; k++){
if (vwgt[i*vwgt_dim+k] < 0) {
sprintf(msg, "Negative object weight of " TPL_WGT_SPEC " for object " ZOLTAN_GNO_SPEC ".",
vwgt[i*vwgt_dim+k], i);
ZOLTAN_PRINT_ERROR(proc, yo, msg);
ierr = ZOLTAN_FATAL;
}
sum += vwgt[i*vwgt_dim+k];
}
if (sum == 0){
num_zeros++;
if (output_level>1) {
sprintf(msg, "Zero vertex (object) weights for object " ZOLTAN_GNO_SPEC ".", i);
ZOLTAN_PRINT_WARN(proc, yo, msg);
}
if (ierr == ZOLTAN_OK) ierr = ZOLTAN_WARN;
}
}
MPI_Reduce(&num_zeros, &global_sum, 1, zoltan_gno_mpi_type, MPI_SUM, 0, comm);
if ((proc==0) && (global_sum>0)){
if (ierr == ZOLTAN_OK) ierr = ZOLTAN_WARN;
if (output_level>0){
sprintf(msg, ZOLTAN_GNO_SPEC " objects have zero weights.", global_sum);
ZOLTAN_PRINT_WARN(proc, yo, msg);
}
}
}
/* Check number of edges */
nedges = (ZOLTAN_GNO_TYPE)xadj[num_obj];
MPI_Reduce(&nedges, &global_sum, 1, zoltan_gno_mpi_type, MPI_SUM, 0, comm);
if ((proc==0) && (global_sum==0)){
if (ierr == ZOLTAN_OK) ierr = ZOLTAN_WARN;
if (output_level>0)
ZOLTAN_PRINT_WARN(proc, yo, "No edges in graph.");
}
/* Verify that edge weights are non-negative */
num_zeros = 0;
if (ewgt_dim){
for (j=0; j<nedges; j++){
sum = 0;
for (k=0; k<ewgt_dim; k++){
if (adjwgt[j*ewgt_dim+k] < 0) {
sprintf(msg, "Negative edge weight of " TPL_WGT_SPEC " in edge " ZOLTAN_GNO_SPEC ".",
adjwgt[j*ewgt_dim+k], j);
ZOLTAN_PRINT_ERROR(proc, yo, msg);
ierr = ZOLTAN_FATAL;
}
sum += adjwgt[j*ewgt_dim+k];
}
if (sum == 0){
num_zeros++;
if (output_level>1) {
sprintf(msg, "Zero edge (communication) weights for edge " ZOLTAN_GNO_SPEC ".", j);
ZOLTAN_PRINT_WARN(proc, yo, msg);
}
if (ierr == ZOLTAN_OK) ierr = ZOLTAN_WARN;
}
}
MPI_Reduce(&num_zeros, &global_sum, 1, zoltan_gno_mpi_type, MPI_SUM, 0, comm);
if ((proc==0) && (global_sum>0)){
if (ierr == ZOLTAN_OK) ierr = ZOLTAN_WARN;
if (output_level>0){
sprintf(msg, ZOLTAN_GNO_SPEC " edges have zero weights.", global_sum);
ZOLTAN_PRINT_WARN(proc, yo, msg);
}
}
}
/* Verify that the graph is symmetric (edge weights, too) */
/* Also check for self-edges and multi-edges */
/* Pre-processing: Check if edge lists are sorted. If not, */
/* make a copy and sort so we can save time in the lookups. */
flag = 0; /* Assume sorted. */
for (i=0; (i<num_obj) && (flag==0); i++){
for (ii=xadj[i]; ii<xadj[i+1]-1; ii++){
if (adjncy[ii] > adjncy[ii+1]){
flag = 1; /* Not sorted. */
break;
}
}
}
if (flag){ /* Need to sort. */
adjncy_sort = (indextype *) ZOLTAN_MALLOC(nedges*sizeof(indextype));
perm = (int *) ZOLTAN_MALLOC(nedges*sizeof(int));
free_adjncy_sort = 1;
if (nedges && (!adjncy_sort || !perm)){
/* Out of memory. */
ZOLTAN_PRINT_ERROR(proc, yo, "Out of memory.");
runerr = ZOLTAN_MEMERR;
}
else {
for (k=0; k<nedges; k++){
adjncy_sort[k] = adjncy[k];
perm[k] = k;
}
if (sizeof(indextype) == sizeof(short)){
for (i=0; i<num_obj; i++)
Zoltan_quicksort_list_inc_short((short *)adjncy_sort, perm,
(int)xadj[i], (int)xadj[i+1]-1);
}
else if (sizeof(indextype) == sizeof(int)){
for (i=0; i<num_obj; i++)
Zoltan_quicksort_list_inc_int((int *)adjncy_sort, perm,
(int)xadj[i], (int)xadj[i+1]-1);
}
else if (sizeof(indextype) == sizeof(long)){
for (i=0; i<num_obj; i++)
Zoltan_quicksort_list_inc_long((long *)adjncy_sort, perm,
(int)xadj[i], (int)xadj[i+1]-1);
}
else if (sizeof(indextype) == sizeof(int64_t)){
for (i=0; i<num_obj; i++)
Zoltan_quicksort_list_inc_long_long((int64_t*)adjncy_sort, perm,
(int)xadj[i], (int)xadj[i+1]-1);
}
else{
ZOLTAN_PRINT_ERROR(proc, yo,
"Error in third party library data type support.");
ierr = ZOLTAN_FATAL;
}
}
}
else { /* Already sorted. */
adjncy_sort = adjncy;
}
/* First pass: Check on-processor edges and count # off-proc edges */
cross_edges = 0;
num_selfs = 0;
num_duplicates = 0;
num_singletons = 0;
for (i=0; i<num_obj; i++){
if (IS_GLOBAL_GRAPH(graph_type)){
global_i = vtxdist[proc]+i;
}
else{ /* graph_type == LOCAL_GRAPH */
global_i = i; /* A bit confusingly, global_i = i for local graphs */
}
/* Singleton? */
if (xadj[i] == xadj[i+1]){
num_singletons++;
if (output_level>1){
sprintf(msg, "Vertex " TPL_IDX_SPEC " has no edges.", global_i);
ZOLTAN_PRINT_WARN(proc, yo, msg);
}
}
for (ii=xadj[i]; ii<xadj[i+1]; ii++){
global_j = adjncy_sort[ii];
/* Valid vertex number? */
if ((IS_GLOBAL_GRAPH(graph_type) &&
((global_j < vtxdist[0]) || (global_j >= vtxdist[nprocs])))
|| (IS_LOCAL_GRAPH(graph_type) &&
((global_j < 0) || (global_j >= num_obj)))){
sprintf(msg, "Edge to invalid vertex " TPL_IDX_SPEC " detected.", global_j);
ZOLTAN_PRINT_ERROR(proc, yo, msg);
ierr = ZOLTAN_FATAL;
}
/* Self edge? */
if (global_j == global_i){
num_selfs++;
if (output_level>1){
sprintf(msg, "Self edge for vertex " TPL_IDX_SPEC " detected.", global_i);
ZOLTAN_PRINT_WARN(proc, yo, msg);
}
}
/* Duplicate edge? */
if ((ii+1<xadj[i+1]) && (adjncy_sort[ii]==adjncy_sort[ii+1])){
num_duplicates++;
if (output_level>1){
sprintf(msg, "Duplicate edge (" TPL_IDX_SPEC "," TPL_IDX_SPEC ") detected.", global_i, global_j);
ZOLTAN_PRINT_WARN(proc, yo, msg);
}
}
/* Is global_j a local vertex? */
if (IS_LOCAL_GRAPH(graph_type) || (IS_GLOBAL_GRAPH(graph_type) &&
(global_j >= vtxdist[proc]) && (global_j < vtxdist[proc+1]))){
/* Check if (global_j, global_i) is an edge */
if (IS_GLOBAL_GRAPH(graph_type))
j = global_j - vtxdist[proc];
else /* graph_type == LOCAL_GRAPH */
j = global_j;
/* Binary search for edge (global_j, global_i) */
ptr = (indextype *)bsearch(&global_i, &adjncy_sort[xadj[j]], (int)(xadj[j+1]-xadj[j]),
sizeof(indextype), Zoltan_Compare_Indextypes);
if (ptr){
/* OK, found edge (global_j, global_i) */
if ((adjncy_sort==adjncy) && ewgt_dim){
/* Compare weights */
/* EBEB For now, don't compare weights if we sorted edge lists. */
flag = 0;
for (k=0; k<ewgt_dim; k++){
if (adjwgt[(ptr-adjncy_sort)*ewgt_dim+k] !=
adjwgt[ii*ewgt_dim+k]){
/* Numerically nonsymmetric */
flag = -1;
if (ierr == ZOLTAN_OK) ierr = ZOLTAN_WARN;
}
}
if (flag<0 && output_level>0){
sprintf(msg, "Graph is numerically nonsymmetric "
"in edge (" TPL_IDX_SPEC "," TPL_IDX_SPEC ")", global_i, global_j);
ZOLTAN_PRINT_WARN(proc, yo, msg);
}
}
}
else { /* bsearch failed */
sprintf(msg, "Graph is not symmetric. "
"Edge (" TPL_IDX_SPEC "," TPL_IDX_SPEC ") exists, but no edge (" TPL_IDX_SPEC "," TPL_IDX_SPEC ").",
global_i, global_j, global_j, global_i);
ZOLTAN_PRINT_ERROR(proc, yo, msg);
ierr = ZOLTAN_FATAL;
}
}
else {
cross_edges++;
}
}
}
/* Sum up warnings so far. */
MPI_Reduce(&num_selfs, &global_sum, 1, zoltan_gno_mpi_type, MPI_SUM, 0, comm);
if ((proc==0) && (global_sum>0)){
if (ierr == ZOLTAN_OK) ierr = ZOLTAN_WARN;
if (output_level>0){
sprintf(msg, ZOLTAN_GNO_SPEC " self-edges in graph.", global_sum);
ZOLTAN_PRINT_WARN(proc, yo, msg);
}
}
MPI_Reduce(&num_duplicates, &global_sum, 1, zoltan_gno_mpi_type, MPI_SUM, 0, comm);
if ((proc==0) && (global_sum>0)){
if (ierr == ZOLTAN_OK) ierr = ZOLTAN_WARN;
if (output_level>0){
sprintf(msg, ZOLTAN_GNO_SPEC " duplicate edges in graph.", global_sum);
ZOLTAN_PRINT_WARN(proc, yo, msg);
}
}
MPI_Reduce(&num_singletons, &global_sum, 1, zoltan_gno_mpi_type, MPI_SUM, 0, comm);
if ((proc==0) && (global_sum>0)){
if (ierr == ZOLTAN_OK) ierr = ZOLTAN_WARN;
if (output_level>0){
sprintf(msg, ZOLTAN_GNO_SPEC " vertices in the graph are singletons (have no edges).", global_sum);
ZOLTAN_PRINT_WARN(proc, yo, msg);
}
}
/* Check if any processor has encountered an error so far */
errors = 0;
if (ierr == ZOLTAN_WARN)
errors |= 1;
if (ierr == ZOLTAN_MEMERR)
errors |= 2;
if (ierr == ZOLTAN_FATAL)
errors |= 4;
MPI_Allreduce(&errors, &global_errors, 1, MPI_INT, MPI_BOR, comm);
if (global_errors & 4){
/* Fatal error: return now */
if (free_adjncy_sort) ZOLTAN_FREE(&adjncy_sort);
if (free_adjncy_sort) ZOLTAN_FREE(&perm);
return ZOLTAN_FATAL;
}
if ((IS_GLOBAL_GRAPH(graph_type)) && (check_graph >= 2)) {
/* Test for consistency across processors. */
/* Allocate space for off-proc data */
mesg_size = (2*sizeof(indextype)) + (ewgt_dim * sizeof(weighttype));
sendgno = (indextype *) ZOLTAN_MALLOC(cross_edges*mesg_size);
recvgno = (indextype *) ZOLTAN_MALLOC(cross_edges*mesg_size);
proclist = (int *) ZOLTAN_MALLOC(cross_edges*sizeof(int));
if (cross_edges && !(sendgno && recvgno && proclist)){
ZOLTAN_PRINT_ERROR(proc, yo, "Out of memory.");
runerr = ZOLTAN_MEMERR;
}
else {
/* Second pass: Copy data to send buffer */
nedges = 0;
ptr1 = (indextype *) sendgno;
for (i=0; i<num_obj; i++){
global_i = vtxdist[proc]+i;
for (ii=xadj[i]; ii<xadj[i+1]; ii++){
global_j = adjncy[ii];
/* Is global_j off-proc? */
if ((global_j < vtxdist[proc]) || (global_j >= vtxdist[proc+1])){
/* Add to list */
k=0;
while (global_j >= vtxdist[k+1]) k++;
proclist[nedges++] = k;
/* Copy (global_i,global_j) and corresponding weights to sendgno */
*ptr1++ = global_i;
*ptr1++ = global_j;
for (k=0; k<ewgt_dim; k++){
*ptr1++ = adjwgt[ii*ewgt_dim+k];
}
}
}
}
/* Do the irregular communication */
runerr = Zoltan_Comm_Create(&comm_plan, cross_edges, proclist, comm,
TAG1, &nrecv);
if (runerr != ZOLTAN_OK && runerr != ZOLTAN_WARN) {
sprintf(msg, "Error %s returned from Zoltan_Comm_Create.",
(runerr == ZOLTAN_MEMERR ? "ZOLTAN_MEMERR" : "ZOLTAN_FATAL"));
Zoltan_Comm_Destroy(&comm_plan);
ZOLTAN_PRINT_ERROR(proc, yo, msg);
}
else {
if (nrecv != cross_edges){
sprintf(msg, "Incorrect number of edges to/from proc %d.", proc);
ZOLTAN_PRINT_ERROR(proc, yo, msg);
ierr = ZOLTAN_FATAL;
}
runerr = Zoltan_Comm_Do(comm_plan, TAG2, (char *)sendgno, mesg_size,
(char *)recvgno);
Zoltan_Comm_Destroy(&comm_plan);
if (runerr != ZOLTAN_OK && runerr != ZOLTAN_WARN) {
sprintf(msg, "Error %s returned from Zoltan_Comm_Do.",
(runerr == ZOLTAN_MEMERR ? "ZOLTAN_MEMERR" : "ZOLTAN_FATAL"));
ZOLTAN_PRINT_ERROR(proc, yo, msg);
}
else {
/* Third pass: Compare on-proc data to off-proc data we received */
/* sendgno and recvgno should contain the same data except (i,j) is */
/* (j,i) */
for (i=0, ptr1=sendgno; i<cross_edges; i++){
flag = 0;
sendwgt = (weighttype *)(ptr1 + 2);
for (j=0, ptr2=recvgno; j<cross_edges; j++){
recvwgt = (weighttype *)(ptr2 + 2);
if ((ptr2[0] == ptr1[1]) && (ptr2[1] == ptr1[0])){
/* Found matching edge */
flag = 1;
/* Check weights */
for (k=0; k<ewgt_dim; k++){
if (sendwgt[k] != recvwgt[k]){
flag = -1;
if (ierr == ZOLTAN_OK) ierr = ZOLTAN_WARN;
}
}
if (flag<0 && output_level>0){
sprintf(msg, "Edge weight (" TPL_IDX_SPEC "," TPL_IDX_SPEC ") is not symmetric",
ptr1[0], ptr1[1]);
ZOLTAN_PRINT_WARN(proc, yo, msg);
}
}
ptr2 = (indextype *)(recvwgt + ewgt_dim);
}
if (!flag){
sprintf(msg, "Graph is not symmetric. "
"Edge (" TPL_IDX_SPEC "," TPL_IDX_SPEC ") exists, but not (" TPL_IDX_SPEC "," TPL_IDX_SPEC ").",
ptr1[0], ptr1[1], ptr1[1], ptr1[0]);
ZOLTAN_PRINT_ERROR(proc, yo, msg);
ierr = ZOLTAN_FATAL;
}
ptr1 = (indextype *)(sendwgt + ewgt_dim);
}
}
}
}
/* Free memory */
ZOLTAN_FREE(&sendgno);
ZOLTAN_FREE(&recvgno);
ZOLTAN_FREE(&proclist);
}
if (free_adjncy_sort) ZOLTAN_FREE(&adjncy_sort);
if (free_adjncy_sort) ZOLTAN_FREE(&perm);
/* Compute global error code */
errors = 0;
if (ierr == ZOLTAN_WARN)
errors |= 1;
if (ierr == ZOLTAN_MEMERR)
errors |= 2;
if (ierr == ZOLTAN_FATAL)
errors |= 4;
MPI_Allreduce(&errors, &global_errors, 1, MPI_INT, MPI_BOR, comm);
if (global_errors & 4){
return ZOLTAN_FATAL;
}
else if (global_errors & 2){
return ZOLTAN_MEMERR;
}
else if (global_errors & 1){
return ZOLTAN_WARN;
}
else {
if (proc==0 && output_level>0){
printf("ZOLTAN %s: The graph is valid with check_graph = %1d\n",
yo, check_graph);
}
return ZOLTAN_OK;
}
}
/* comparison routine for bsearch */
static int Zoltan_Compare_Indextypes(const void *key, const void *arg)
{
if ( *(indextype*) key > (*(indextype*) arg)) return 1;
if ( *(indextype*) key < (*(indextype*) arg)) return -1;
return 0; /* equal */
}
#ifdef __cplusplus
} /* closing bracket for extern "C" */
#endif