* bin/rmdepall: Correction to the removing of scanned files.

This commit is contained in:
henry
2008-06-03 21:19:13 +01:00
parent ee6a2ced47
commit bcd1f1cf91
102 changed files with 1 additions and 44596 deletions

View File

@ -4,7 +4,7 @@ if [ $# -eq 0 ]; then
find . \( -name '*.dep' \) -print | xargs -t rm
elif [ $# -eq 1 ]; then
echo "Removing all dep files containing $1..."
find . -name '*.dep' -exec grep "$1" '{}' \; | sed -e 's/:.*//' | xargs -t rm
find . -name '*.dep' -exec grep "$1" '{}' \; -exec rm '{}' \;
else
echo "Usage: `basename $0` to remove all .dep files"
echo " `basename $0` <file> to remove all .dep files referring to <file>"

View File

@ -1,39 +0,0 @@
The distribution of PARMGRIDGEN consists of a number of files arranged in four
directories. The files contained in each directory are as follows:
Doc/ Contains PARMGRIDGEN's user manual
Graphs/ Contains some small sample meshes that can be used with
the stand-alone programs of MGRIDGEN and PARMGRIDGEN
MGridGen/ Contains the serial library
ParMGridGen/ Contains the parallel library
mgridgen Stand-alone serial program
parmgridgen Stand-alone parallel program
The distribution of MGRIDGEN consists of a number of files arranged in three
directories. The files contained in each directory are as follows:
IMlib/ Contains some auxiliary routines
Lib/ Contains the code for MGRIDGEN's library
Programs/ Contains a comprehensive tester for MGRIDGEN's routines
The distribution of PARMGRIDGEN consists of a number of files arranged in three
directories. The files contained in each directory are as follows:
IMParMetis-2.0/ Contains some auxiliary routins from ParMetis-2.0, modified
so as to fit our data types.
ParLib/ Contains the code for MGRIDGEN's library
Programs/ Contains a comprehensive tester for PARMGRIDGEN's routines

View File

@ -1,121 +0,0 @@
This file contains one test problem
M6.metis
This is a small 3D mesh corresponding to a M6 wing.
You can use it to test various coarsening techniques.
===========================================================================
To run the serial code, for example, try something like
../mgridgen1.0 M6.metis 3 4 6 1 4 128
Here is how the correct output should look like.
prompt%: ../mgridgen1.0 M6.metis 3 4 6 1 4 128
Parameters: M6.metis, Dim=3 [ 1 4] CType=4 RType=6 Nvtxs=24893 Nedges=351504
Npoints: 7161, Coarsening Factor: 3.476190
Aspect Ratios: Min : 1.211900e+01, Max : 1.784692e+01
Aspect Ratios: Sum : 1.145611e+05, Wsum: 3.997483e+05
Aspect Ratios: Surf: 1.473822e+06, Avg : 1.599792e+01
Graph lmincut : 1.436660e+05
Cell size: min=1, max=4
CellSizeDist: [ 1 24] [ 2 819] [ 3 2041] [ 4 4277]
Total Time: 6.700000
===========================================================================
To run the parallel code try something like
mpirun -np 4 ../parmgridgen1.0 M6.metis 3 4 6 1 4 128
An output file, named OUTPUT4.[0-3], will be generated for every processor.
prompt% more OUTPUT4.0
Nvtxs: 24893, Nedges: 351504
------------------------ PARAMETERS --------------------------------------
M6.metis, Dim=3 [ 1 4] CType=4 RType=6 Nvtxs=6223 Nedges=87156
-------------------------- LOCAL --------------------------
Npoints: 1883, Coarsening Factor: 3.459373
Aspect Ratios: Min : 1.250444e+01, Max : 1.762476e+01
Aspect Ratios: Sum : 3.005424e+04, Wsum: 1.044060e+05
Aspect Ratios: Surf: 7.849518e+05, Avg : 1.596083e+01
Graph lmincut : 3.818850e+04
Cell size: min=1, max=4
CellSizeDist: [ 1 9] [ 2 253] [ 3 485] [ 4 1136]
-------------------------- GLOBAL --------------------------
Npoints: 7269, Coarsening Factor: 3.424543
Aspect Ratios: Min : 1.198039e+01, Max : 1.800314e+01
Aspect Ratios: Sum : 1.158327e+05, Wsum: 3.984295e+05
Aspect Ratios: Surf: 1.475658e+06, Avg : 1.593517e+01
Graph mincut : 1.440100e+05
------------------------------ END ------------------------------
Total Time = 8.627177
prompt% more OUTPUT4.1
M6.metis, Dim=3 [ 1 4] CType=4 RType=6 Nvtxs=6223 Nedges=89366
-------------------------- LOCAL --------------------------
Npoints: 1891, Coarsening Factor: 3.401904
Aspect Ratios: Min : 1.277087e+01, Max : 1.800314e+01
Aspect Ratios: Sum : 3.009639e+04, Wsum: 1.028172e+05
Aspect Ratios: Surf: 6.049566e+05, Avg : 1.591559e+01
Graph lmincut : 3.751350e+04
Cell size: min=1, max=4
CellSizeDist: [ 1 7] [ 2 265] [ 3 580] [ 4 1039]
-------------------------- GLOBAL --------------------------
Npoints: 7269, Coarsening Factor: 3.424543
Aspect Ratios: Min : 1.198039e+01, Max : 1.800314e+01
Aspect Ratios: Sum : 1.158327e+05, Wsum: 3.984295e+05
Aspect Ratios: Surf: 1.475658e+06, Avg : 1.593517e+01
Graph mincut : 1.440100e+05
------------------------------ END ------------------------------
Total Time = 8.627194
prompt% more OUTPUT4.2
M6.metis, Dim=3 [ 1 4] CType=4 RType=6 Nvtxs=6223 Nedges=88490
-------------------------- LOCAL --------------------------
Npoints: 1735, Coarsening Factor: 3.393660
Aspect Ratios: Min : 1.198039e+01, Max : 1.748248e+01
Aspect Ratios: Sum : 2.759339e+04, Wsum: 9.412172e+04
Aspect Ratios: Surf: 9.847982e+03, Avg : 1.590397e+01
Graph lmincut : 3.376950e+04
Cell size: min=1, max=4
CellSizeDist: [ 1 8] [ 2 249] [ 3 530] [ 4 948]
-------------------------- GLOBAL --------------------------
Npoints: 7269, Coarsening Factor: 3.424543
Aspect Ratios: Min : 1.198039e+01, Max : 1.800314e+01
Aspect Ratios: Sum : 1.158327e+05, Wsum: 3.984295e+05
Aspect Ratios: Surf: 1.475658e+06, Avg : 1.593517e+01
Graph mincut : 1.440100e+05
------------------------------ END ------------------------------
Total Time = 8.627183
prompt% more OUTPUT4.3
M6.metis, Dim=3 [ 1 4] CType=4 RType=6 Nvtxs=6224 Nedges=86492
-------------------------- LOCAL --------------------------
Npoints: 1760, Coarsening Factor: 3.442045
Aspect Ratios: Min : 1.252911e+01, Max : 1.763729e+01
Aspect Ratios: Sum : 2.808869e+04, Wsum: 9.708463e+04
Aspect Ratios: Surf: 7.590192e+04, Avg : 1.595948e+01
Graph lmincut : 3.453850e+04
Cell size: min=1, max=4
CellSizeDist: [ 1 6] [ 2 225] [ 3 514] [ 4 1015]
-------------------------- GLOBAL --------------------------
Npoints: 7269, Coarsening Factor: 3.424543
Aspect Ratios: Min : 1.198039e+01, Max : 1.800314e+01
Aspect Ratios: Sum : 1.158327e+05, Wsum: 3.984295e+05
Aspect Ratios: Surf: 1.475658e+06, Avg : 1.593517e+01
Graph mincut : 1.440100e+05
------------------------------ END ------------------------------
Total Time = 8.627202

View File

@ -1,153 +0,0 @@
Copyright 2001, Regents of the University of Minnesota.
PARMGRIDGEN-1.0 was written by George Karypis (karypis@cs.umn.edu)
and Irene Moulitsas (moulitsa@cs.umn.edu).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
THE SERIAL LIBRARY MGRIDGEN
---------------------------
INTRODUCTION
------------
MGRIDGEN is a software package for generating coarse grids.
The documentation of MGRIDGEN can be found in the Doc/manual-parmgridgen.ps file.
MGRIDGEN is written in ANSI C and should compile on Unix systems that have
a ANSI C compiler. It has been extensively tested on the following
architectures:
AIX
SunOS
Solaris
IRIX
Unicos
Linux
FreeBSD
INSTALLATION INSTRUCTIONS
-------------------------
In order to build MGRIDGEN you need
(a) a C compiler that is ANSI compatible
(b) make
Edit the file Makefile.in that resides in the same directory as this file
according to the requirements of your system. In particular you may need
to modify the following:
1. The executable for GNU make (gmake)
2. The CC and LD variables, to be the name of the ANSI C compiler
in your system. The GNU C compiler (gcc) will do.
3. The settings for the AR and RANLIB variables that are suitable for
you system. Note that some systems do not have 'ranlib' but they use
'ar -ts' instead, or it is not needed all together.
4. You can use COPTIONS and LDOPTIONS to provide additional command line
options that are required by your compiler and linker.
After saving the modified Makefile.in, type 'make' at the prompt. This will
build MGRIDGEN's library, and a program that tests the algorithm.
Upon successful completion, make creates the following files:
MGridGen/IMlib/libIMlib.a
libmgrid.a
mgridgen
Please read the instructions in the file Graphs/README on how to go and
test the various programs.
The header file mgridgen.h can be used to provide the prototype for the
main routine in MGRIDGEN.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
THE PARALLEL LIBRARY PARMGRIDGEN
--------------------------------
INTRODUCTION
------------
PARMGRIDGEN is a parallel software package for generating coarse grids.
The documentation of PARMGRIDGEN can be found in the Doc/manual-parmgridgen.ps
file.
PARMGRIDGEN is written in ANSI C, using Message Passing Interface (MPI)
for communication between the processors, and should compile on Unix systems
that have a ANSI C compiler and an installation of MPI. It has been extensively
tested on the following architectures:
AIX
IRIX
Unicos
Linux
INSTALLATION INSTRUCTIONS
-------------------------
In order to build PARMGRIDGEN you need
(a) an MPI C compiler
(b) make
Edit the file Makefile.in that resides in the same directory as this file
according to the requirements of your system. In particular you may need
to modify the following:
1. The executable for GNU make (gmake)
2. The CC and LD variables, to be the name of the ANSI C compiler
in your system. The GNU C compiler (gcc) will do.
3. The PARCC and PARLD variables, to be the name of the compiler in
your system. The default is to use mpicc from MPICH.
4. The settings for the AR and RANLIB variables that are suitable for
you system. Note that some systems do not have 'ranlib' but they use
'ar -ts' instead, or it is not needed all together.
5. You can use COPTIONS and LDOPTIONS to provide additional command line
options that are required by your compiler and linker.
After saving the modified Makefile.in, type 'make parallel' at the prompt. This
will build PARMGRIDGEN's library, and a program that tests the algorithm.
Upon successful completion, make creates the following files:
ParMGridGen/IMParMetis-2.0/libIMparmetis.a
libparmgrid.a
parmgridgen
Please read the instructions in the file Graphs/README on how to go and
test the various programs.
The header file parmgridgen.h can be used to provide the prototype for the
main routine in PARMGRIDGEN.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
NOTE-1: The results on your machine will most likely look different
because of differences in the random number generators.
Look if the test programs reports any 'incorrect' results.
If the test goes through correctly, then you have compiled
PARMGRIDGEN successfully!
NOTE-2: FYI, the header files mgridgen.h and parmgridgen.h contain
definitions for the datatypes to be used for integer and real
arithmetic. If you wish to switch to short (for integer) or
float (for real) you need to edit the files
o MGridGen/IMlib/IMlib.h
o ParMGridGen/IMParMetis-2.0/ParMETISLib/struct.h
and comment the defintion accordigly.
CONTACT INFORMATION
-------------------
If you have any comments, suggestions, or bug reports, please send them
to moulitsa@cs.umn.edu.
Any bug fixes and upgrades of the MGRIDGEN/PARMGRIDGEN package is available
on WWW at URL: http://www.cs.umn.edu/~moulitsa/software.html
Irene Moulitsas
moulitsa@cs.umn.edu
Tue Dec 4 18:24:47 CST 2001

View File

@ -1,284 +0,0 @@
/*
* IMlib.h
*
* Irene's library of most frequently used routines
*
*/
#ifndef _IMLIB_H_
#define _IMLIB_H_
/* Undefine the following #define in order to use short int as the idxtype */
#define IDXTYPE_INT
/* Undefine the following #define in order to use float as the realtype */
/*#define TYPE_REAL*/
/* Indexes are as long as integers for now */
#ifdef IDXTYPE_INT
typedef int idxtype;
#else
typedef short idxtype;
#endif
/* floats for now */
#ifdef TYPE_REAL
typedef float realtype;
#else
typedef double realtype;
#endif
/*************************************************************************
* Header file inclusion section
**************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdarg.h>
#include <time.h>
#ifdef DMALLOC
#include <dmalloc.h>
#else
#include <malloc.h>
#endif
/*************************************************************************
* Data structure definition section
**************************************************************************/
/*-------------------------------------------------------------
* The following data structure stores int key-value pairs
*-------------------------------------------------------------*/
struct IKeyValueType {
int key;
int val;
};
typedef struct IKeyValueType IKeyValueType;
/*-------------------------------------------------------------
* The following data structure stores int key-value pairs
*-------------------------------------------------------------*/
struct idxKeyValueType {
idxtype key;
idxtype val;
};
typedef struct idxKeyValueType idxKeyValueType;
/*-------------------------------------------------------------
* The following data structure stores int-key - double-value pairs
*-------------------------------------------------------------*/
struct FKeyValueType {
double key;
int val, val1, val2;
};
typedef struct FKeyValueType FKeyValueType;
/*-------------------------------------------------------------
* The following data structure stores int-key - double-value pairs
*-------------------------------------------------------------*/
struct realKeyValueType {
realtype key;
int val, val1, val2;
};
typedef struct realKeyValueType realKeyValueType;
/*************************************************************************
* Definition Section
**************************************************************************/
#define LTERM (void **) 0 /* List terminator for IMfree() */
/*************************************************************************
* Macros Section
**************************************************************************/
/*-------------------------------------------------------------
* Usefull commands
*-------------------------------------------------------------*/
#define sign(a, b) ((b) >= 0 ? ((a) >= 0.0 ? a : -a) : ((a) >= 0.0 ? -a : a))
#define amax(a, b) ((a) >= (b) ? (a) : (b))
#define amin(a, b) ((a) >= (b) ? (b) : (a))
#define RandomInRange(u) ((int)(drand48()*((double)(u))))
#define RandomInRangeFast(u) ((rand()>>3)%(u))
#define SWAP(a, b, tmp) do {(tmp) = (a); (a) = (b); (b) = (tmp);} while(0)
#define INC_DEC(a, b, val) do {(a) += (val); (b) -= (val);} while(0)
#define icopy(n, a, b) (int *)memcpy((void *)(b), (void *)(a), sizeof(int)*(n))
#define idxcopy(n, a, b) (idxtype *)memcpy((void *)(b), (void *)(a), sizeof(idxtype)*(n))
#define scopy(n, a, b) (double *)memcpy((void *)(b), (void *)(a), sizeof(double)*(n))
#define fcopy(n, a, b) (double *)memcpy((void *)(b), (void *)(a), sizeof(double)*(n))
#define realcopy(n, a, b) (realtype *)memcpy((void *)(b), (void *)(a), sizeof(realtype)*(n))
/*-------------------------------------------------------------
* Timing macros
*-------------------------------------------------------------*/
#define cleartimer(tmr) (tmr = 0.0)
#define starttimer(tmr) (tmr -= seconds())
#define stoptimer(tmr) (tmr += seconds())
#define gettimer(tmr) (tmr)
/*-------------------------------------------------------------
* Debuging memory leaks
*-------------------------------------------------------------*/
#ifdef DMALLOC
#define imalloc(n, msg) (malloc(sizeof(int)*(n)))
#define fmalloc(n, msg) (malloc(sizeof(double)*(n)))
#define idxmalloc(n, msg) ((idxtype *)malloc(sizeof(idxtype)*(n)))
#define realmalloc(n, msg) ((realtype *)malloc(sizeof(realtype)*(n)))
#define ismalloc(n, val, msg) (iset((n), (val), malloc(sizeof(int)*(n))))
#define idxsmalloc(n, val, msg) (idxset((n), (val), (idxtype *)malloc(sizeof(idxtype)*(n))))
#define fsmalloc(n, val, msg) (fset((n), (val), malloc(sizeof(double)*(n))))
#define realsmalloc(n, val, msg) (realset((n), (val), (realtype *)malloc(sizeof(realtype)*(n))))
#define IMmalloc(a, b) (malloc((a)))
#endif
#ifdef DMALLOC
# define MALLOC_CHECK(ptr) \
if (malloc_verify((ptr)) == DMALLOC_VERIFY_ERROR) { \
printf("***MALLOC_CHECK failed on line %d of file %s: " #ptr "\n", \
__LINE__, __FILE__); \
abort(); \
}
#else
# define MALLOC_CHECK(ptr) ;
#endif
/*-------------------------------------------------------------
* CSR conversion macros
*-------------------------------------------------------------*/
#define MAKECSR(i, n, a) \
do { \
for (i=1; i<n; i++) a[i] += a[i-1]; \
for (i=n; i>0; i--) a[i] = a[i-1]; \
a[0] = 0; \
} while(0)
/*-------------------------------------------------------------
* Program Assertions
*-------------------------------------------------------------*/
#ifdef DEBUG
# define ASSERT(expr) \
if (!(expr)) { \
printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \
__LINE__, __FILE__); \
abort(); \
}
#else
# define ASSERT(expr) ;
#endif
#ifdef DEBUG
# define ASSERTP(expr,msg) \
if (!(expr)) { \
printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \
__LINE__, __FILE__); \
printf msg ; \
printf("\n"); \
abort(); \
}
#else
# define ASSERTP(expr,msg) ;
#endif
/*************************************************************************
* Function prototypes
**************************************************************************/
/*-------------------------------------------------------------
* blas.c
*-------------------------------------------------------------*/
int *iset(int, int, int *);
idxtype *idxset(int, idxtype, idxtype *);
double *fset(int, double, double *);
realtype *realset(int, realtype, realtype *);
int iamax(int, int *);
int idxamax(int, idxtype *);
int famax(int, double *);
int iamin(int, int *);
int idxamin(int, idxtype *);
int famin(int, double *);
int charsum(int, char *);
int isum(int, int *);
int idxsum(int, idxtype *);
double ssum(int, double *);
double ssum_strd(int, double *, int);
void sscale(int, double, double *);
double snorm2(int, double *);
double sdot(int, double *, double *);
void saxpy(int, double, double *, int, double *, int);
/*-------------------------------------------------------------
* file.c
*-------------------------------------------------------------*/
FILE *IMfopen(char *, char *, char *);
void IMfclose(FILE *);
/*-------------------------------------------------------------
* memory.c
*-------------------------------------------------------------*/
#ifndef DMALLOC
int *imalloc(int, char *);
idxtype *idxmalloc(int, char *);
double *fmalloc(int, char *);
realtype *realmalloc(int, char *);
int *ismalloc(int, int, char *);
idxtype *idxsmalloc(int, idxtype, char *);
double *fsmalloc(int, double, char *);
realtype *realsmalloc(int, realtype, char *);
void *IMmalloc(int, char *);
#endif
/* void IMfree(void **, ...); */
/*-------------------------------------------------------------
* util.c
*-------------------------------------------------------------*/
void *errexit(char *,...);
int IMlog2(int);
double flog2(double);
int ispow2(int);
double seconds(void);
/*-------------------------------------------------------------
* Sorting routines
*-------------------------------------------------------------*/
void dfkeysort(int, FKeyValueType *);
void dkeysort(int, IKeyValueType *);
void ifkeysort(int, FKeyValueType *);
void ifkeysort2(int, FKeyValueType *);
void ifloatsort(int, double *);
void iintsort(int, int *);
void ikeysort(int, IKeyValueType *);
void idxkeysort(int, idxKeyValueType *);
void ikeysort2(int, IKeyValueType *);
void idxkeysort2(int, idxKeyValueType *);
/*-------------------------------------------------------------
* sort.c
*-------------------------------------------------------------*/
void ikeyvalsort_org(int, IKeyValueType *);
int IncKeyValueCmp(const void *, const void *);
void dkeyvalsort(int, IKeyValueType *);
void BucketSortKeysInc(int, idxtype, idxtype *, int *, int *);
int DecKeyValueCmp(const void *, const void *);
int BSearch(int, idxtype *, int);
void RandomPermute(int, idxtype *, int);
void RandomPermuteFine(int, int *, int);
void FastRandomPermute(int, idxtype *, int);
#endif

View File

@ -1,12 +0,0 @@
blas.c
dfkeysort.c
file.c
ifkeysort.c
ifloatsort.c
iintsort.c
ikeysort.c
memory.c
sort.c
util.c
LIB = $(FOAM_LIBBIN)/libIMlib

View File

@ -1,6 +0,0 @@
TYPE_REAL=
#if defined(SP)
TYPE_REAL=-DTYPE_REAL
#endif
EXE_INC = $(TYPE_REAL)

View File

@ -1,44 +0,0 @@
include ../../Makefile.in
#--------------------------------------------------------------------------
DMALLOCINC =
DMALLOCFLAGS =
DEBUGFLAGS =
ifeq ($(ddmalloc),yes)
DMALLOCINC = -I$(DMALLOCDIR)/include
DMALLOCFLAGS = -DDMALLOC
DEBUGFLAGS = -DDEBUG
OPTFLAGS = -g
endif
ifeq ($(dmalloc),yes)
DMALLOCINC = -I$(DMALLOCDIR)/include
DMALLOCFLAGS = -DDMALLOC
OPTFLAGS = -g
endif
ifeq ($(debug),yes)
DEBUGFLAGS = -DDEBUG
OPTFLAGS = -g
endif
INCLUDES = -I./ $(INCDIR) $(DMALLOCINC)
CFLAGS = $(COPTIONS) $(OPTFLAGS) $(DMALLOCFLAGS) $(DEBUGFLAGS) $(INCLUDES)
#--------------------------------------------------------------------------
OBJS = blas.o dfkeysort.o dkeysort.o file.o ifkeysort.o ifloatsort.o \
iintsort.o ikeysort.o memory.o sort.o util.o
.c.o:
$(CC) $(CFLAGS) -c $*.c
./libIMlib.a: $(OBJS)
$(AR) $@ $(OBJS)
$(RANLIB) $@
clean:
rm -f *.o
realclean:
rm -f *.o ; rm -f ./libIMlib.a

View File

@ -1,277 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* blas.c
*
* This function contains various utility routines
*
* George Irene
*/
#include "IMlib.h"
/*************************************************************************
* These functions set the values of a vector
**************************************************************************/
int *iset(int n, int val, int *x)
{
int i;
for (i=0; i<n; i++)
x[i] = val;
return x;
}
/*************************************************************************
* These functions set the values of a vector
**************************************************************************/
idxtype *idxset(int n, idxtype val, idxtype *x)
{
int i;
for (i=0; i<n; i++)
x[i] = val;
return x;
}
/*************************************************************************
* These functions set the values of a vector
**************************************************************************/
double *fset(int n, double val, double *x)
{
int i;
for (i=0; i<n; i++)
x[i] = val;
return x;
}
/*************************************************************************
* These functions set the values of a vector
**************************************************************************/
realtype *realset(int n, realtype val, realtype *x)
{
int i;
for (i=0; i<n; i++)
x[i] = val;
return x;
}
/*************************************************************************
* These functions return the index of the maximum element in a vector
**************************************************************************/
int iamax(int n, int *x)
{
int i, max=0;
for (i=1; i<n; i++)
max = (x[i] > x[max] ? i : max);
return max;
}
/*************************************************************************
* These functions return the index of the maximum element in a vector
**************************************************************************/
int idxamax(int n, idxtype *x)
{
int i, max=0;
for (i=1; i<n; i++)
max = (x[i] > x[max] ? i : max);
return max;
}
/*************************************************************************
* These functions return the index of the maximum element in a vector
**************************************************************************/
int famax(int n, double *x)
{
int i, max=0;
for (i=1; i<n; i++)
max = (x[i] > x[max] ? i : max);
return max;
}
/*************************************************************************
* These functions return the index of the minimum element in a vector
**************************************************************************/
int iamin(int n, int *x)
{
int i, min=0;
for (i=1; i<n; i++)
min = (x[i] < x[min] ? i : min);
return min;
}
/*************************************************************************
* These functions return the index of the minimum element in a vector
**************************************************************************/
int idxamin(int n, idxtype *x)
{
int i, min=0;
for (i=1; i<n; i++)
min = (x[i] < x[min] ? i : min);
return min;
}
/*************************************************************************
* These functions return the index of the minimum element in a vector
**************************************************************************/
int famin(int n, double *x)
{
int i, min=0;
for (i=1; i<n; i++)
min = (x[i] < x[min] ? i : min);
return min;
}
/*************************************************************************
* This function sums the entries in an array
**************************************************************************/
int charsum(int n, char *x)
{
int i, sum = 0;
for (i=0; i<n; i++)
sum += x[i];
return sum;
}
/*************************************************************************
* This function sums the entries in an array
**************************************************************************/
int isum(int n, int *x)
{
int i, sum = 0;
for (i=0; i<n; i++)
sum += x[i];
return sum;
}
/*************************************************************************
* This function sums the entries in an array
**************************************************************************/
int idxsum(int n, idxtype *x)
{
int i, sum = 0;
for (i=0; i<n; i++)
sum += x[i];
return sum;
}
/*************************************************************************
* This function sums the entries in an array
**************************************************************************/
double ssum(int n, double *x)
{
int i;
double sum = 0.0;
for (i=0; i<n; i++)
sum += x[i];
return sum;
}
/*************************************************************************
* This function sums the entries in an array
**************************************************************************/
double ssum_strd(int n, double *x, int incx)
{
int i;
double sum = 0.0;
for (i=0; i<n; i++, x+=incx)
sum += *x;
return sum;
}
/*************************************************************************
* This function scales the entries in an array
**************************************************************************/
void sscale(int n, double alpha, double *x)
{
int i;
for (i=0; i<n; i++)
x[i] *= alpha;
}
/*************************************************************************
* This function computes a 2-norm
**************************************************************************/
double snorm2(int n, double *v)
{
int i;
double partial = 0;
for (i = 0; i<n; i++)
partial += v[i] * v[i];
return sqrt(partial);
}
/*************************************************************************
* This function computes a dot product
**************************************************************************/
double sdot(int n, double *x, double *y)
{
int i;
double partial = 0;
for (i = 0; i<n; i++)
partial += x[i] * y[i];
return partial;
}
/*************************************************************************
* This function computes a saxpy operation
**************************************************************************/
void saxpy(int n, double alpha, double *x, int incx, double *y, int incy)
{
int i;
for (i=0; i<n; i++, x+=incx, y+=incy)
*y += alpha*(*x);
}

View File

@ -1,161 +0,0 @@
#include "IMlib.h"
/* Byte-wise swap two items of size SIZE. */
#define QSSWAP(a, b, stmp) do { stmp = (a); (a) = (b); (b) = stmp; } while (0)
/* Discontinue quicksort algorithm when partition gets below this size.
This particular magic number was chosen to work best on a Sun 4/260. */
#define MAX_THRESH 20
/* Stack node declarations used to store unfulfilled partition obligations. */
typedef struct {
FKeyValueType *lo;
FKeyValueType *hi;
} stack_node;
/* The next 4 #defines implement a very fast in-line stack abstraction. */
#define STACK_SIZE (32 * sizeof(unsigned long int))
#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
#define STACK_NOT_EMPTY (bottom < top)
void dfkeysort(int total_elems, FKeyValueType *pbase)
{
FKeyValueType pivot, stmp;
if (total_elems == 0)
/* Avoid lossage with unsigned arithmetic below. */
return;
if (total_elems > MAX_THRESH) {
FKeyValueType *lo = pbase;
FKeyValueType *hi = &lo[total_elems - 1];
stack_node stack[STACK_SIZE]; /* Largest size needed for 32-bit int!!! */
stack_node *bottom = stack+1, *top = stack+2;
stack[1].lo = stack[1].hi = NULL;
while (STACK_NOT_EMPTY) {
FKeyValueType *left_ptr;
FKeyValueType *right_ptr;
FKeyValueType *mid = lo + ((hi - lo) >> 1);
if (mid->key > lo->key)
QSSWAP(*mid, *lo, stmp);
if (hi->key > mid->key)
QSSWAP(*mid, *hi, stmp);
else
goto jump_over;
if (mid->key > lo->key)
QSSWAP(*mid, *lo, stmp);
jump_over:;
pivot = *mid;
left_ptr = lo + 1;
right_ptr = hi - 1;
/* Here's the famous ``collapse the walls'' section of quicksort.
Gotta like those tight inner loops! They are the main reason
that this algorithm runs much faster than others. */
do {
while (left_ptr->key > pivot.key)
left_ptr++;
while (pivot.key > right_ptr->key)
right_ptr--;
if (left_ptr < right_ptr) {
QSSWAP (*left_ptr, *right_ptr, stmp);
left_ptr++;
right_ptr--;
}
else if (left_ptr == right_ptr) {
left_ptr++;
right_ptr--;
break;
}
} while (left_ptr <= right_ptr);
/* Set up pointers for next iteration. First determine whether
left and right partitions are below the threshold size. If so,
ignore one or both. Otherwise, push the larger partition's
bounds on the stack and continue sorting the smaller one. */
if ((size_t) (right_ptr - lo) <= MAX_THRESH) {
if ((size_t) (hi - left_ptr) <= MAX_THRESH)
/* Ignore both small partitions. */
POP (lo, hi);
else
/* Ignore small left partition. */
lo = left_ptr;
}
else if ((size_t) (hi - left_ptr) <= MAX_THRESH)
/* Ignore small right partition. */
hi = right_ptr;
else if ((right_ptr - lo) > (hi - left_ptr)) {
/* Push larger left partition indices. */
PUSH (lo, right_ptr);
lo = left_ptr;
}
else {
/* Push larger right partition indices. */
PUSH (left_ptr, hi);
hi = right_ptr;
}
}
}
/* Once the BASE_PTR array is partially sorted by quicksort the rest
is completely sorted using insertion sort, since this is efficient
for partitions below MAX_THRESH size. BASE_PTR points to the beginning
of the array to sort, and END_PTR points at the very last element in
the array (*not* one beyond it!). */
{
FKeyValueType *end_ptr = &pbase[total_elems - 1];
FKeyValueType *tmp_ptr = pbase;
FKeyValueType *thresh = (end_ptr < pbase + MAX_THRESH ? end_ptr : pbase + MAX_THRESH);
register FKeyValueType *run_ptr;
/* Find smallest element in first threshold and place it at the
array's beginning. This is the smallest array element,
and the operation speeds up insertion sort's inner loop. */
for (run_ptr = tmp_ptr + 1; run_ptr <= thresh; run_ptr++)
if (run_ptr->key > tmp_ptr->key)
tmp_ptr = run_ptr;
if (tmp_ptr != pbase)
QSSWAP(*tmp_ptr, *pbase, stmp);
/* Insertion sort, running from left-hand-side up to right-hand-side. */
run_ptr = pbase + 1;
while (++run_ptr <= end_ptr) {
tmp_ptr = run_ptr - 1;
while (run_ptr->key > tmp_ptr->key)
tmp_ptr--;
tmp_ptr++;
if (tmp_ptr != run_ptr) {
FKeyValueType elmnt = *run_ptr;
FKeyValueType *mptr;
for (mptr=run_ptr; mptr>tmp_ptr; mptr--)
*mptr = *(mptr-1);
*mptr = elmnt;
}
}
}
#ifdef DEBUG
{
int i;
for (i=1; i<total_elems; i++) {
if (pbase[i].key > pbase[i-1].key)
printf("Sorting Error! [%f %f]\n", pbase[i-1].key, pbase[i].key);
}
}
#endif
}

View File

@ -1,162 +0,0 @@
#include "IMlib.h"
/* Byte-wise swap two items of size SIZE. */
#define QSSWAP(a, b, stmp) do { stmp = (a); (a) = (b); (b) = stmp; } while (0)
/* Discontinue quicksort algorithm when partition gets below this size.
This particular magic number was chosen to work best on a Sun 4/260. */
#define MAX_THRESH 20
/* Stack node declarations used to store unfulfilled partition obligations. */
typedef struct {
IKeyValueType *lo;
IKeyValueType *hi;
} stack_node;
/* The next 4 #defines implement a very fast in-line stack abstraction. */
#define STACK_SIZE (32 * sizeof(unsigned long int))
#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
#define STACK_NOT_EMPTY (bottom < top)
void dkeysort(int total_elems, IKeyValueType *pbase)
{
IKeyValueType pivot, stmp;
if (total_elems == 0)
/* Avoid lossage with unsigned arithmetic below. */
return;
if (total_elems > MAX_THRESH) {
IKeyValueType *lo = pbase;
IKeyValueType *hi = &lo[total_elems - 1];
stack_node stack[STACK_SIZE]; /* Largest size needed for 32-bit int!!! */
stack_node *bottom = stack+1, *top = stack+2;
stack[1].lo = stack[1].hi = NULL;
while (STACK_NOT_EMPTY) {
IKeyValueType *left_ptr;
IKeyValueType *right_ptr;
IKeyValueType *mid = lo + ((hi - lo) >> 1);
if (mid->key > lo->key)
QSSWAP(*mid, *lo, stmp);
if (hi->key > mid->key)
QSSWAP(*mid, *hi, stmp);
else
goto jump_over;
if (mid->key > lo->key)
QSSWAP(*mid, *lo, stmp);
jump_over:;
pivot = *mid;
left_ptr = lo + 1;
right_ptr = hi - 1;
/* Here's the famous ``collapse the walls'' section of quicksort.
Gotta like those tight inner loops! They are the main reason
that this algorithm runs much faster than others. */
do {
while (left_ptr->key > pivot.key)
left_ptr++;
while (pivot.key > right_ptr->key)
right_ptr--;
if (left_ptr < right_ptr) {
QSSWAP (*left_ptr, *right_ptr, stmp);
left_ptr++;
right_ptr--;
}
else if (left_ptr == right_ptr) {
left_ptr++;
right_ptr--;
break;
}
} while (left_ptr <= right_ptr);
/* Set up pointers for next iteration. First determine whether
left and right partitions are below the threshold size. If so,
ignore one or both. Otherwise, push the larger partition's
bounds on the stack and continue sorting the smaller one. */
if ((size_t) (right_ptr - lo) <= MAX_THRESH) {
if ((size_t) (hi - left_ptr) <= MAX_THRESH)
/* Ignore both small partitions. */
POP (lo, hi);
else
/* Ignore small left partition. */
lo = left_ptr;
}
else if ((size_t) (hi - left_ptr) <= MAX_THRESH)
/* Ignore small right partition. */
hi = right_ptr;
else if ((right_ptr - lo) > (hi - left_ptr)) {
/* Push larger left partition indices. */
PUSH (lo, right_ptr);
lo = left_ptr;
}
else {
/* Push larger right partition indices. */
PUSH (left_ptr, hi);
hi = right_ptr;
}
}
}
/* Once the BASE_PTR array is partially sorted by quicksort the rest
is completely sorted using insertion sort, since this is efficient
for partitions below MAX_THRESH size. BASE_PTR points to the beginning
of the array to sort, and END_PTR points at the very last element in
the array (*not* one beyond it!). */
{
IKeyValueType *end_ptr = &pbase[total_elems - 1];
IKeyValueType *tmp_ptr = pbase;
IKeyValueType *thresh = (end_ptr < pbase + MAX_THRESH ? end_ptr : pbase + MAX_THRESH);
register IKeyValueType *run_ptr;
/* Find smallest element in first threshold and place it at the
array's beginning. This is the smallest array element,
and the operation speeds up insertion sort's inner loop. */
for (run_ptr = tmp_ptr + 1; run_ptr <= thresh; run_ptr++)
if (run_ptr->key > tmp_ptr->key)
tmp_ptr = run_ptr;
if (tmp_ptr != pbase)
QSSWAP(*tmp_ptr, *pbase, stmp);
/* Insertion sort, running from left-hand-side up to right-hand-side. */
run_ptr = pbase + 1;
while (++run_ptr <= end_ptr) {
tmp_ptr = run_ptr - 1;
while (run_ptr->key > tmp_ptr->key)
tmp_ptr--;
tmp_ptr++;
if (tmp_ptr != run_ptr) {
IKeyValueType elmnt = *run_ptr;
IKeyValueType *mptr;
for (mptr=run_ptr; mptr>tmp_ptr; mptr--)
*mptr = *(mptr-1);
*mptr = elmnt;
}
}
}
#ifdef DEBUG
{
int i;
for (i=1; i<total_elems; i++) {
if (pbase[i].key > pbase[i-1].key)
printf("Sorting Error! [%d %d]\n", pbase[i-1].key, pbase[i].key);
}
}
#endif
}

View File

@ -1,37 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* file.c
*
* This file contains some simple io functions
*
* Irene
*/
#include "IMlib.h"
/*************************************************************************
* This function opens a file
**************************************************************************/
FILE *IMfopen(char *fname, char *mode, char *msg)
{
FILE *fp;
char errmsg[256];
fp = fopen(fname, mode);
if (fp != NULL)
return fp;
sprintf(errmsg,"file: %s, mode: %s, [%s]", fname, mode, msg);
perror(msg);
exit(0);
}
/*************************************************************************
* This function closes a file
**************************************************************************/
void IMfclose(FILE *fp)
{
fclose(fp);
}

View File

@ -1,223 +0,0 @@
#include "IMlib.h"
void ifkeysort2(int, FKeyValueType *);
/* Byte-wise swap two items of size SIZE. */
#define QSSWAP(a, b, stmp) do { stmp = (a); (a) = (b); (b) = stmp; } while (0)
/* Discontinue quicksort algorithm when partition gets below this size.
This particular magic number was chosen to work best on a Sun 4/260. */
#define MAX_THRESH 20
/* Stack node declarations used to store unfulfilled partition obligations. */
typedef struct {
FKeyValueType *lo;
FKeyValueType *hi;
} stack_node;
/* The next 4 #defines implement a very fast in-line stack abstraction. */
#define STACK_SIZE (32 * sizeof(unsigned long int))
#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
#define STACK_NOT_EMPTY (bottom < top)
void ifkeysort(int total_elems, FKeyValueType *pbase)
{
int i, nflips;
FKeyValueType pivot, stmp;
for (nflips = 0, i=0; i<total_elems-1; i++) {
if (pbase[i].key > pbase[i+1].key)
nflips++;
}
if (nflips < .05*total_elems) {
ifkeysort2(total_elems, pbase);
return;
}
if (total_elems == 0)
/* Avoid lossage with unsigned arithmetic below. */
return;
if (total_elems > MAX_THRESH) {
FKeyValueType *lo = pbase;
FKeyValueType *hi = &lo[total_elems - 1];
stack_node stack[STACK_SIZE];
stack_node *bottom = stack+1, *top = stack + 2;
stack[1].lo = stack[1].hi = NULL;
while (STACK_NOT_EMPTY) {
FKeyValueType *left_ptr;
FKeyValueType *right_ptr;
FKeyValueType *mid = lo + ((hi - lo) >> 1);
if (mid->key < lo->key)
QSSWAP(*mid, *lo, stmp);
if (hi->key < mid->key)
QSSWAP(*mid, *hi, stmp);
else
goto jump_over;
if (mid->key < lo->key)
QSSWAP(*mid, *lo, stmp);
jump_over:;
pivot = *mid;
left_ptr = lo + 1;
right_ptr = hi - 1;
/* Here's the famous ``collapse the walls'' section of quicksort.
Gotta like those tight inner loops! They are the main reason
that this algorithm runs much faster than others. */
do {
while (left_ptr->key < pivot.key)
left_ptr++;
while (pivot.key < right_ptr->key)
right_ptr--;
if (left_ptr < right_ptr) {
QSSWAP (*left_ptr, *right_ptr, stmp);
left_ptr++;
right_ptr--;
}
else if (left_ptr == right_ptr) {
left_ptr++;
right_ptr--;
break;
}
} while (left_ptr <= right_ptr);
/* Set up pointers for next iteration. First determine whether
left and right partitions are below the threshold size. If so,
ignore one or both. Otherwise, push the larger partition's
bounds on the stack and continue sorting the smaller one. */
if ((size_t) (right_ptr - lo) <= MAX_THRESH) {
if ((size_t) (hi - left_ptr) <= MAX_THRESH) {
/* Ignore both small partitions. */
POP (lo, hi);
}
else
/* Ignore small left partition. */
lo = left_ptr;
}
else if ((size_t) (hi - left_ptr) <= MAX_THRESH)
/* Ignore small right partition. */
hi = right_ptr;
else if ((right_ptr - lo) > (hi - left_ptr)) {
/* Push larger left partition indices. */
PUSH (lo, right_ptr);
lo = left_ptr;
}
else {
/* Push larger right partition indices. */
PUSH (left_ptr, hi);
hi = right_ptr;
}
}
}
/* Once the BASE_PTR array is partially sorted by quicksort the rest
is completely sorted using insertion sort, since this is efficient
for partitions below MAX_THRESH size. BASE_PTR points to the beginning
of the array to sort, and END_PTR points at the very last element in
the array (*not* one beyond it!). */
{
FKeyValueType *end_ptr = &pbase[total_elems - 1];
FKeyValueType *tmp_ptr = pbase;
FKeyValueType *thresh = (end_ptr < pbase + MAX_THRESH ? end_ptr : pbase + MAX_THRESH);
register FKeyValueType *run_ptr;
/* Find smallest element in first threshold and place it at the
array's beginning. This is the smallest array element,
and the operation speeds up insertion sort's inner loop. */
for (run_ptr = tmp_ptr + 1; run_ptr <= thresh; run_ptr++)
if (run_ptr->key < tmp_ptr->key)
tmp_ptr = run_ptr;
if (tmp_ptr != pbase)
QSSWAP(*tmp_ptr, *pbase, stmp);
/* Insertion sort, running from left-hand-side up to right-hand-side. */
run_ptr = pbase + 1;
while (++run_ptr <= end_ptr) {
tmp_ptr = run_ptr - 1;
while (run_ptr->key < tmp_ptr->key)
tmp_ptr--;
tmp_ptr++;
if (tmp_ptr != run_ptr) {
FKeyValueType elmnt = *run_ptr;
FKeyValueType *mptr;
for (mptr=run_ptr; mptr>tmp_ptr; mptr--)
*mptr = *(mptr-1);
*mptr = elmnt;
}
}
}
#ifdef DEBUG
{
int i;
for (i=1; i<total_elems; i++) {
if (pbase[i].key < pbase[i-1].key)
printf("Sorting Error! [%f %f]\n", pbase[i-1].key, pbase[i].key);
}
}
#endif
}
void ifkeysort2(int total_elems, FKeyValueType *pbase)
{
FKeyValueType stmp;
FKeyValueType *end_ptr = &pbase[total_elems - 1];
FKeyValueType *tmp_ptr = pbase;
FKeyValueType *thresh = end_ptr;
register FKeyValueType *run_ptr;
/* Find smallest element in first threshold and place it at the
array's beginning. This is the smallest array element,
and the operation speeds up insertion sort's inner loop. */
for (run_ptr = tmp_ptr + 1; run_ptr <= thresh; run_ptr++)
if (run_ptr->key < tmp_ptr->key)
tmp_ptr = run_ptr;
if (tmp_ptr != pbase)
QSSWAP(*tmp_ptr, *pbase, stmp);
/* Insertion sort, running from left-hand-side up to right-hand-side. */
run_ptr = pbase + 1;
while (++run_ptr <= end_ptr) {
tmp_ptr = run_ptr - 1;
while (run_ptr->key < tmp_ptr->key)
tmp_ptr--;
tmp_ptr++;
if (tmp_ptr != run_ptr) {
FKeyValueType elmnt = *run_ptr;
FKeyValueType *mptr;
for (mptr=run_ptr; mptr>tmp_ptr; mptr--)
*mptr = *(mptr-1);
*mptr = elmnt;
}
}
#ifdef DEBUG
{
int i;
for (i=1; i<total_elems; i++) {
if (pbase[i].key < pbase[i-1].key)
printf("Sorting Error! [%f %f]\n", pbase[i-1].key, pbase[i].key);
}
}
#endif
}

View File

@ -1,152 +0,0 @@
#include "IMlib.h"
/* Byte-wise swap two items of size SIZE. */
#define QSSWAP(a, b, stmp) do { stmp = (a); (a) = (b); (b) = stmp; } while (0)
/* Discontinue quicksort algorithm when partition gets below this size.
This particular magic number was chosen to work best on a Sun 4/260. */
#define MAX_THRESH 20
/* Stack node declarations used to store unfulfilled partition obligations. */
typedef struct {
double *lo;
double *hi;
} stack_node;
/* The next 4 #defines implement a very fast in-line stack abstraction. */
#define STACK_SIZE (32 * sizeof(unsigned long int))
#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
#define STACK_NOT_EMPTY (bottom < top)
void ifloatsort(int total_elems, double *pbase)
{
double pivot, stmp;
if (total_elems == 0)
/* Avoid lossage with unsigned arithmetic below. */
return;
if (total_elems > MAX_THRESH) {
double *lo = pbase;
double *hi = &lo[total_elems - 1];
stack_node stack[STACK_SIZE];
stack_node *bottom = stack+1, *top = stack + 2;
stack[1].lo = stack[1].hi = NULL;
while (STACK_NOT_EMPTY) {
double *left_ptr;
double *right_ptr;
double *mid = lo + ((hi - lo) >> 1);
if (*mid < *lo)
QSSWAP(*mid, *lo, stmp);
if (*hi < *mid)
QSSWAP(*mid, *hi, stmp);
else
goto jump_over;
if (*mid < *lo)
QSSWAP(*mid, *lo, stmp);
jump_over:;
pivot = *mid;
left_ptr = lo + 1;
right_ptr = hi - 1;
/* Here's the famous ``collapse the walls'' section of quicksort.
Gotta like those tight inner loops! They are the main reason
that this algorithm runs much faster than others. */
do {
while (*left_ptr < pivot)
left_ptr++;
while (pivot < *right_ptr)
right_ptr--;
if (left_ptr < right_ptr) {
QSSWAP (*left_ptr, *right_ptr, stmp);
left_ptr++;
right_ptr--;
}
else if (left_ptr == right_ptr) {
left_ptr++;
right_ptr--;
break;
}
} while (left_ptr <= right_ptr);
/* Set up pointers for next iteration. First determine whether
left and right partitions are below the threshold size. If so,
ignore one or both. Otherwise, push the larger partition's
bounds on the stack and continue sorting the smaller one. */
if ((size_t) (right_ptr - lo) <= MAX_THRESH) {
if ((size_t) (hi - left_ptr) <= MAX_THRESH)
/* Ignore both small partitions. */
POP (lo, hi);
else
/* Ignore small left partition. */
lo = left_ptr;
}
else if ((size_t) (hi - left_ptr) <= MAX_THRESH)
/* Ignore small right partition. */
hi = right_ptr;
else if ((right_ptr - lo) > (hi - left_ptr)) {
/* Push larger left partition indices. */
PUSH (lo, right_ptr);
lo = left_ptr;
}
else {
/* Push larger right partition indices. */
PUSH (left_ptr, hi);
hi = right_ptr;
}
}
}
/* Once the BASE_PTR array is partially sorted by quicksort the rest
is completely sorted using insertion sort, since this is efficient
for partitions below MAX_THRESH size. BASE_PTR points to the beginning
of the array to sort, and END_PTR points at the very last element in
the array (*not* one beyond it!). */
{
double *end_ptr = &pbase[total_elems - 1];
double *tmp_ptr = pbase;
double *thresh = (end_ptr < pbase + MAX_THRESH ? end_ptr : pbase + MAX_THRESH);
register double *run_ptr;
/* Find smallest element in first threshold and place it at the
array's beginning. This is the smallest array element,
and the operation speeds up insertion sort's inner loop. */
for (run_ptr = tmp_ptr + 1; run_ptr <= thresh; run_ptr++)
if (*run_ptr < *tmp_ptr)
tmp_ptr = run_ptr;
if (tmp_ptr != pbase)
QSSWAP(*tmp_ptr, *pbase, stmp);
/* Insertion sort, running from left-hand-side up to right-hand-side. */
run_ptr = pbase + 1;
while (++run_ptr <= end_ptr) {
tmp_ptr = run_ptr - 1;
while (*run_ptr < *tmp_ptr)
tmp_ptr--;
tmp_ptr++;
if (tmp_ptr != run_ptr) {
double elmnt = *run_ptr;
double *mptr;
for (mptr=run_ptr; mptr>tmp_ptr; mptr--)
*mptr = *(mptr-1);
*mptr = elmnt;
}
}
}
}

View File

@ -1,162 +0,0 @@
#include "IMlib.h"
/* Byte-wise swap two items of size SIZE. */
#define QSSWAP(a, b, stmp) do { stmp = (a); (a) = (b); (b) = stmp; } while (0)
/* Discontinue quicksort algorithm when partition gets below this size.
This particular magic number was chosen to work best on a Sun 4/260. */
#define MAX_THRESH 20
/* Stack node declarations used to store unfulfilled partition obligations. */
typedef struct {
int *lo;
int *hi;
} stack_node;
/* The next 4 #defines implement a very fast in-line stack abstraction. */
#define STACK_SIZE (32 * sizeof(unsigned long int))
#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
#define STACK_NOT_EMPTY (bottom < top)
void iintsort(int total_elems, int *pbase)
{
int pivot, stmp;
if (total_elems == 0)
/* Avoid lossage with unsigned arithmetic below. */
return;
if (total_elems > MAX_THRESH) {
int *lo = pbase;
int *hi = &lo[total_elems - 1];
stack_node stack[STACK_SIZE]; /* Largest size needed for 32-bit int!!! */
stack_node *bottom = stack+1, *top = stack+2;
stack[1].lo = stack[1].hi = NULL;
while (STACK_NOT_EMPTY) {
int *left_ptr;
int *right_ptr;
int *mid = lo + ((hi - lo) >> 1);
if (*mid < *lo)
QSSWAP(*mid, *lo, stmp);
if (*hi < *mid)
QSSWAP(*mid, *hi, stmp);
else
goto jump_over;
if (*mid < *lo)
QSSWAP(*mid, *lo, stmp);
jump_over:;
pivot = *mid;
left_ptr = lo + 1;
right_ptr = hi - 1;
/* Here's the famous ``collapse the walls'' section of quicksort.
Gotta like those tight inner loops! They are the main reason
that this algorithm runs much faster than others. */
do {
while (*left_ptr < pivot)
left_ptr++;
while (pivot < *right_ptr)
right_ptr--;
if (left_ptr < right_ptr) {
QSSWAP (*left_ptr, *right_ptr, stmp);
left_ptr++;
right_ptr--;
}
else if (left_ptr == right_ptr) {
left_ptr++;
right_ptr--;
break;
}
} while (left_ptr <= right_ptr);
/* Set up pointers for next iteration. First determine whether
left and right partitions are below the threshold size. If so,
ignore one or both. Otherwise, push the larger partition's
bounds on the stack and continue sorting the smaller one. */
if ((size_t) (right_ptr - lo) <= MAX_THRESH) {
if ((size_t) (hi - left_ptr) <= MAX_THRESH)
/* Ignore both small partitions. */
POP (lo, hi);
else
/* Ignore small left partition. */
lo = left_ptr;
}
else if ((size_t) (hi - left_ptr) <= MAX_THRESH)
/* Ignore small right partition. */
hi = right_ptr;
else if ((right_ptr - lo) > (hi - left_ptr)) {
/* Push larger left partition indices. */
PUSH (lo, right_ptr);
lo = left_ptr;
}
else {
/* Push larger right partition indices. */
PUSH (left_ptr, hi);
hi = right_ptr;
}
}
}
/* Once the BASE_PTR array is partially sorted by quicksort the rest
is completely sorted using insertion sort, since this is efficient
for partitions below MAX_THRESH size. BASE_PTR points to the beginning
of the array to sort, and END_PTR points at the very last element in
the array (*not* one beyond it!). */
{
int *end_ptr = &pbase[total_elems - 1];
int *tmp_ptr = pbase;
int *thresh = (end_ptr < pbase + MAX_THRESH ? end_ptr : pbase + MAX_THRESH);
register int *run_ptr;
/* Find smallest element in first threshold and place it at the
array's beginning. This is the smallest array element,
and the operation speeds up insertion sort's inner loop. */
for (run_ptr = tmp_ptr + 1; run_ptr <= thresh; run_ptr++)
if (*run_ptr < *tmp_ptr)
tmp_ptr = run_ptr;
if (tmp_ptr != pbase)
QSSWAP(*tmp_ptr, *pbase, stmp);
/* Insertion sort, running from left-hand-side up to right-hand-side. */
run_ptr = pbase + 1;
while (++run_ptr <= end_ptr) {
tmp_ptr = run_ptr - 1;
while (*run_ptr < *tmp_ptr)
tmp_ptr--;
tmp_ptr++;
if (tmp_ptr != run_ptr) {
int elmnt = *run_ptr;
int *mptr;
for (mptr=run_ptr; mptr>tmp_ptr; mptr--)
*mptr = *(mptr-1);
*mptr = elmnt;
}
}
}
#ifdef DEBUG
{
int i;
for (i=1; i<total_elems; i++) {
if (pbase[i] < pbase[i-1])
printf("Sorting Error! [%d %d]\n", pbase[i-1], pbase[i]);
}
}
#endif
}

View File

@ -1,428 +0,0 @@
#include "IMlib.h"
/* Byte-wise swap two items of size SIZE. */
#define QSSWAP(a, b, stmp) do { stmp = (a); (a) = (b); (b) = stmp; } while (0)
/* Discontinue quicksort algorithm when partition gets below this size.
This particular magic number was chosen to work best on a Sun 4/260. */
#define MAX_THRESH 20
/* Stack node declarations used to store unfulfilled partition obligations. */
typedef struct {
IKeyValueType *lo;
IKeyValueType *hi;
} stack_node;
typedef struct {
idxKeyValueType *lo;
idxKeyValueType *hi;
} idxstack_node;
/* The next 4 #defines implement a very fast in-line stack abstraction. */
#define STACK_SIZE (32 * sizeof(unsigned long int))
#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
#define STACK_NOT_EMPTY (bottom < top)
void ikeysort(int total_elems, IKeyValueType *pbase)
{
int i, nflips;
IKeyValueType pivot, stmp;
for (nflips = 0, i=0; i<total_elems-1; i++) {
if (pbase[i].key > pbase[i+1].key)
nflips++;
}
if (nflips < .05*total_elems) {
ikeysort2(total_elems, pbase);
return;
}
if (total_elems == 0)
/* Avoid lossage with unsigned arithmetic below. */
return;
if (total_elems > MAX_THRESH) {
IKeyValueType *lo = pbase;
IKeyValueType *hi = &lo[total_elems - 1];
stack_node stack[STACK_SIZE];
stack_node *bottom = stack+1, *top = stack + 2;
stack[1].lo = stack[1].hi = NULL;
while (STACK_NOT_EMPTY) {
IKeyValueType *left_ptr;
IKeyValueType *right_ptr;
IKeyValueType *mid = lo + ((hi - lo) >> 1);
if (mid->key < lo->key)
QSSWAP(*mid, *lo, stmp);
if (hi->key < mid->key)
QSSWAP(*mid, *hi, stmp);
else
goto jump_over;
if (mid->key < lo->key)
QSSWAP(*mid, *lo, stmp);
jump_over:;
pivot = *mid;
left_ptr = lo + 1;
right_ptr = hi - 1;
/* Here's the famous ``collapse the walls'' section of quicksort.
Gotta like those tight inner loops! They are the main reason
that this algorithm runs much faster than others. */
do {
while (left_ptr->key < pivot.key)
left_ptr++;
while (pivot.key < right_ptr->key)
right_ptr--;
if (left_ptr < right_ptr) {
QSSWAP (*left_ptr, *right_ptr, stmp);
left_ptr++;
right_ptr--;
}
else if (left_ptr == right_ptr) {
left_ptr++;
right_ptr--;
break;
}
} while (left_ptr <= right_ptr);
/* Set up pointers for next iteration. First determine whether
left and right partitions are below the threshold size. If so,
ignore one or both. Otherwise, push the larger partition's
bounds on the stack and continue sorting the smaller one. */
if ((size_t) (right_ptr - lo) <= MAX_THRESH) {
if ((size_t) (hi - left_ptr) <= MAX_THRESH) {
/* Ignore both small partitions. */
POP (lo, hi);
}
else
/* Ignore small left partition. */
lo = left_ptr;
}
else if ((size_t) (hi - left_ptr) <= MAX_THRESH)
/* Ignore small right partition. */
hi = right_ptr;
else if ((right_ptr - lo) > (hi - left_ptr)) {
/* Push larger left partition indices. */
PUSH (lo, right_ptr);
lo = left_ptr;
}
else {
/* Push larger right partition indices. */
PUSH (left_ptr, hi);
hi = right_ptr;
}
}
}
/* Once the BASE_PTR array is partially sorted by quicksort the rest
is completely sorted using insertion sort, since this is efficient
for partitions below MAX_THRESH size. BASE_PTR points to the beginning
of the array to sort, and END_PTR points at the very last element in
the array (*not* one beyond it!). */
{
IKeyValueType *end_ptr = &pbase[total_elems - 1];
IKeyValueType *tmp_ptr = pbase;
IKeyValueType *thresh = (end_ptr < pbase + MAX_THRESH ? end_ptr : pbase + MAX_THRESH);
register IKeyValueType *run_ptr;
/* Find smallest element in first threshold and place it at the
array's beginning. This is the smallest array element,
and the operation speeds up insertion sort's inner loop. */
for (run_ptr = tmp_ptr + 1; run_ptr <= thresh; run_ptr++)
if (run_ptr->key < tmp_ptr->key)
tmp_ptr = run_ptr;
if (tmp_ptr != pbase)
QSSWAP(*tmp_ptr, *pbase, stmp);
/* Insertion sort, running from left-hand-side up to right-hand-side. */
run_ptr = pbase + 1;
while (++run_ptr <= end_ptr) {
tmp_ptr = run_ptr - 1;
while (run_ptr->key < tmp_ptr->key)
tmp_ptr--;
tmp_ptr++;
if (tmp_ptr != run_ptr) {
IKeyValueType elmnt = *run_ptr;
IKeyValueType *mptr;
for (mptr=run_ptr; mptr>tmp_ptr; mptr--)
*mptr = *(mptr-1);
*mptr = elmnt;
}
}
}
#ifdef DEBUG
{
int i;
for (i=1; i<total_elems; i++) {
if (pbase[i].key < pbase[i-1].key)
printf("Sorting Error! [%d %d]\n", pbase[i-1].key, pbase[i].key);
}
}
#endif
}
void idxkeysort(int total_elems, idxKeyValueType *pbase)
{
int i, nflips;
idxKeyValueType pivot, stmp;
for (nflips = 0, i=0; i<total_elems-1; i++) {
if (pbase[i].key > pbase[i+1].key)
nflips++;
}
if (nflips < .05*total_elems) {
idxkeysort2(total_elems, pbase);
return;
}
if (total_elems == 0)
/* Avoid lossage with unsigned arithmetic below. */
return;
if (total_elems > MAX_THRESH) {
idxKeyValueType *lo = pbase;
idxKeyValueType *hi = &lo[total_elems - 1];
idxstack_node stack[STACK_SIZE];
idxstack_node *bottom = stack+1, *top = stack + 2;
stack[1].lo = stack[1].hi = NULL;
while (STACK_NOT_EMPTY) {
idxKeyValueType *left_ptr;
idxKeyValueType *right_ptr;
idxKeyValueType *mid = lo + ((hi - lo) >> 1);
if (mid->key < lo->key)
QSSWAP(*mid, *lo, stmp);
if (hi->key < mid->key)
QSSWAP(*mid, *hi, stmp);
else
goto jump_over;
if (mid->key < lo->key)
QSSWAP(*mid, *lo, stmp);
jump_over:;
pivot = *mid;
left_ptr = lo + 1;
right_ptr = hi - 1;
/* Here's the famous ``collapse the walls'' section of quicksort.
Gotta like those tight inner loops! They are the main reason
that this algorithm runs much faster than others. */
do {
while (left_ptr->key < pivot.key)
left_ptr++;
while (pivot.key < right_ptr->key)
right_ptr--;
if (left_ptr < right_ptr) {
QSSWAP (*left_ptr, *right_ptr, stmp);
left_ptr++;
right_ptr--;
}
else if (left_ptr == right_ptr) {
left_ptr++;
right_ptr--;
break;
}
} while (left_ptr <= right_ptr);
/* Set up pointers for next iteration. First determine whether
left and right partitions are below the threshold size. If so,
ignore one or both. Otherwise, push the larger partition's
bounds on the stack and continue sorting the smaller one. */
if ((size_t) (right_ptr - lo) <= MAX_THRESH) {
if ((size_t) (hi - left_ptr) <= MAX_THRESH) {
/* Ignore both small partitions. */
POP (lo, hi);
}
else
/* Ignore small left partition. */
lo = left_ptr;
}
else if ((size_t) (hi - left_ptr) <= MAX_THRESH)
/* Ignore small right partition. */
hi = right_ptr;
else if ((right_ptr - lo) > (hi - left_ptr)) {
/* Push larger left partition indices. */
PUSH (lo, right_ptr);
lo = left_ptr;
}
else {
/* Push larger right partition indices. */
PUSH (left_ptr, hi);
hi = right_ptr;
}
}
}
/* Once the BASE_PTR array is partially sorted by quicksort the rest
is completely sorted using insertion sort, since this is efficient
for partitions below MAX_THRESH size. BASE_PTR points to the beginning
of the array to sort, and END_PTR points at the very last element in
the array (*not* one beyond it!). */
{
idxKeyValueType *end_ptr = &pbase[total_elems - 1];
idxKeyValueType *tmp_ptr = pbase;
idxKeyValueType *thresh = (end_ptr < pbase + MAX_THRESH ? end_ptr : pbase + MAX_THRESH);
register idxKeyValueType *run_ptr;
/* Find smallest element in first threshold and place it at the
array's beginning. This is the smallest array element,
and the operation speeds up insertion sort's inner loop. */
for (run_ptr = tmp_ptr + 1; run_ptr <= thresh; run_ptr++)
if (run_ptr->key < tmp_ptr->key)
tmp_ptr = run_ptr;
if (tmp_ptr != pbase)
QSSWAP(*tmp_ptr, *pbase, stmp);
/* Insertion sort, running from left-hand-side up to right-hand-side. */
run_ptr = pbase + 1;
while (++run_ptr <= end_ptr) {
tmp_ptr = run_ptr - 1;
while (run_ptr->key < tmp_ptr->key)
tmp_ptr--;
tmp_ptr++;
if (tmp_ptr != run_ptr) {
idxKeyValueType elmnt = *run_ptr;
idxKeyValueType *mptr;
for (mptr=run_ptr; mptr>tmp_ptr; mptr--)
*mptr = *(mptr-1);
*mptr = elmnt;
}
}
}
#ifdef DEBUG
{
int i;
for (i=1; i<total_elems; i++) {
if (pbase[i].key < pbase[i-1].key)
printf("Sorting Error! [%d %d]\n", pbase[i-1].key, pbase[i].key);
}
}
#endif
}
void ikeysort2(int total_elems, IKeyValueType *pbase)
{
IKeyValueType stmp;
IKeyValueType *end_ptr = &pbase[total_elems - 1];
IKeyValueType *tmp_ptr = pbase;
IKeyValueType *thresh = end_ptr;
register IKeyValueType *run_ptr;
/* Find smallest element in first threshold and place it at the
array's beginning. This is the smallest array element,
and the operation speeds up insertion sort's inner loop. */
for (run_ptr = tmp_ptr + 1; run_ptr <= thresh; run_ptr++)
if (run_ptr->key < tmp_ptr->key)
tmp_ptr = run_ptr;
if (tmp_ptr != pbase)
QSSWAP(*tmp_ptr, *pbase, stmp);
/* Insertion sort, running from left-hand-side up to right-hand-side. */
run_ptr = pbase + 1;
while (++run_ptr <= end_ptr) {
tmp_ptr = run_ptr - 1;
while (run_ptr->key < tmp_ptr->key)
tmp_ptr--;
tmp_ptr++;
if (tmp_ptr != run_ptr) {
IKeyValueType elmnt = *run_ptr;
IKeyValueType *mptr;
for (mptr=run_ptr; mptr>tmp_ptr; mptr--)
*mptr = *(mptr-1);
*mptr = elmnt;
}
}
#ifdef DEBUG
{
int i;
for (i=1; i<total_elems; i++) {
if (pbase[i].key < pbase[i-1].key)
printf("Sorting Error! [%d %d]\n", pbase[i-1].key, pbase[i].key);
}
}
#endif
}
void idxkeysort2(int total_elems, idxKeyValueType *pbase)
{
idxKeyValueType stmp;
idxKeyValueType *end_ptr = &pbase[total_elems - 1];
idxKeyValueType *tmp_ptr = pbase;
idxKeyValueType *thresh = end_ptr;
register idxKeyValueType *run_ptr;
/* Find smallest element in first threshold and place it at the
array's beginning. This is the smallest array element,
and the operation speeds up insertion sort's inner loop. */
for (run_ptr = tmp_ptr + 1; run_ptr <= thresh; run_ptr++)
if (run_ptr->key < tmp_ptr->key)
tmp_ptr = run_ptr;
if (tmp_ptr != pbase)
QSSWAP(*tmp_ptr, *pbase, stmp);
/* Insertion sort, running from left-hand-side up to right-hand-side. */
run_ptr = pbase + 1;
while (++run_ptr <= end_ptr) {
tmp_ptr = run_ptr - 1;
while (run_ptr->key < tmp_ptr->key)
tmp_ptr--;
tmp_ptr++;
if (tmp_ptr != run_ptr) {
idxKeyValueType elmnt = *run_ptr;
idxKeyValueType *mptr;
for (mptr=run_ptr; mptr>tmp_ptr; mptr--)
*mptr = *(mptr-1);
*mptr = elmnt;
}
}
#ifdef DEBUG
{
int i;
for (i=1; i<total_elems; i++) {
if (pbase[i].key < pbase[i-1].key)
printf("Sorting Error! [%d %d]\n", pbase[i-1].key, pbase[i].key);
}
}
#endif
}

View File

@ -1,152 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* memory.c
*
* This function contains various memory utility routines
*
* George Irene
*/
#include "IMlib.h"
#ifndef DMALLOC
/*************************************************************************
* The following function allocates an array of integers
**************************************************************************/
int *imalloc(int n, char *msg)
{
if (n == 0)
return NULL;
return (int *)IMmalloc(sizeof(int)*n, msg);
}
/*************************************************************************
* The following function allocates an array of integers
**************************************************************************/
idxtype *idxmalloc(int n, char *msg)
{
if (n == 0)
return NULL;
return (idxtype *)IMmalloc(sizeof(idxtype)*n, msg);
}
/*************************************************************************
* The following function allocates an array of double
**************************************************************************/
double *fmalloc(int n, char *msg)
{
if (n == 0)
return NULL;
return (double *)IMmalloc(sizeof(double)*n, msg);
}
/*************************************************************************
* The following function allocates an array of real
**************************************************************************/
realtype *realmalloc(int n, char *msg)
{
if (n == 0)
return NULL;
return (realtype *)IMmalloc(sizeof(realtype)*n, msg);
}
/*************************************************************************
* The follwoing function allocates an array of integers
**************************************************************************/
int *ismalloc(int n, int ival, char *msg)
{
if (n == 0)
return NULL;
return iset(n, ival, (int *)IMmalloc(sizeof(int)*n, msg));
}
/*************************************************************************
* The follwoing function allocates an array of integers
**************************************************************************/
idxtype *idxsmalloc(int n, idxtype ival, char *msg)
{
if (n == 0)
return NULL;
return idxset(n, ival, (idxtype *)IMmalloc(sizeof(idxtype)*n, msg));
}
/*************************************************************************
* The follwoing function allocates an array of doubles
**************************************************************************/
double *fsmalloc(int n, double ival, char *msg)
{
if (n == 0)
return NULL;
return fset(n, ival, (double *)IMmalloc(sizeof(double)*n, msg));
}
/*************************************************************************
* The follwoing function allocates an array of reals
**************************************************************************/
realtype *realsmalloc(int n, realtype rval, char *msg)
{
if (n == 0)
return NULL;
return realset(n, rval, (realtype *)IMmalloc(sizeof(realtype)*n, msg));
}
/*************************************************************************
* This function is my wrapper around malloc
**************************************************************************/
void *IMmalloc(int nbytes, char *msg)
{
void *ptr;
if (nbytes == 0)
return NULL;
ptr = (void *)malloc(nbytes);
if (ptr == NULL)
errexit("***Memory allocation failed for %s. Requested size: %d bytes", msg, nbytes);
return ptr;
}
#endif
/*************************************************************************
* This function is my wrapper around free, allows multiple pointers
**************************************************************************/
void IMfree(void **ptr1,...)
{
va_list plist;
void **ptr;
if (*ptr1 != NULL)
free(*ptr1);
*ptr1 = NULL;
va_start(plist, ptr1);
while ((ptr = va_arg(plist, void **)) != LTERM) {
if (*ptr != NULL)
free(*ptr);
*ptr = NULL;
}
va_end(plist);
}

View File

@ -1,176 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* sort.c
*
* This function contains various utility routines
*
* George
*/
#include "IMlib.h"
/*************************************************************************
* This function sorts an array of type KeyValueType in increasing order
**************************************************************************/
void ikeyvalsort_org(int n, IKeyValueType *nodes)
{
qsort((void *)nodes, (size_t)n, (size_t)sizeof(IKeyValueType), IncKeyValueCmp);
}
/*************************************************************************
* This function compares 2 KeyValueType variables for sorting in inc order
**************************************************************************/
int IncKeyValueCmp(const void *v1, const void *v2)
{
IKeyValueType *n1, *n2;
n1 = (IKeyValueType *)v1;
n2 = (IKeyValueType *)v2;
return (n1->key != n2->key ? n1->key - n2->key : n1->val - n2->val);
}
/*************************************************************************
* This function sorts an array of type KeyValueType in increasing order
**************************************************************************/
void dkeyvalsort(int n, IKeyValueType *nodes)
{
qsort((void *)nodes, (size_t)n, (size_t)sizeof(IKeyValueType), DecKeyValueCmp);
}
/*************************************************************************
* This function uses simple counting sort to return a permutation array
* corresponding to the sorted order. The keys are assumed to start from
* 0 and they are positive. This sorting is used during matching.
**************************************************************************/
void BucketSortKeysInc(int n, idxtype max, idxtype *keys, int *tperm, int *perm)
{
int i, ii;
int *counts;
counts = ismalloc(max+2, 0, "BucketSortKeysInc: counts");
for (i=0; i<n; i++)
counts[keys[i]]++;
MAKECSR(i, max+1, counts);
for (ii=0; ii<n; ii++) {
i = tperm[ii];
perm[counts[keys[i]]++] = i;
}
IMfree(&counts, LTERM);
}
/*************************************************************************
* This function compares 2 KeyValueType variables for sorting in inc order
**************************************************************************/
int DecKeyValueCmp(const void *v1, const void *v2)
{
IKeyValueType *n1, *n2;
n1 = (IKeyValueType *)v1;
n2 = (IKeyValueType *)v2;
return n2->key - n1->key;
}
/*************************************************************************
* This function does a binary search on an array for a key and returns
* the index
**************************************************************************/
int BSearch(int n, idxtype *array, int key)
{
int a=0, b=n, c;
while (b-a > 8) {
c = (a+b)>>1;
if (array[c] > key)
b = c;
else
a = c;
}
for (c=a; c<b; c++) {
if (array[c] == key)
return c;
}
errexit("Key %d not found!\n", key);
}
/*************************************************************************
* This file randomly permutes the contents of an array.
* flag == 0, don't initialize perm
* flag == 1, set p[i] = i
**************************************************************************/
void RandomPermute(int n, idxtype *p, int flag)
{
int i, u, v;
idxtype tmp;
if (flag == 1) {
for (i=0; i<n; i++)
p[i] = i;
}
for (i=0; i<n; i++) {
v = RandomInRange(n);
u = RandomInRange(n);
SWAP(p[v], p[u], tmp);
}
}
/*************************************************************************
* This file randomly permutes the contents of an array.
* flag == 0, don't initialize perm
* flag == 1, set p[i] = i
**************************************************************************/
void RandomPermuteFine(int n, int *p, int flag)
{
int i, u, v, tmp;
if (flag == 1)
for (i=0; i<n; i++)
p[i] = i;
for (i=0; i<n; i++) {
v = RandomInRange(n);
u = RandomInRange(n);
SWAP(p[v], p[u], tmp);
}
}
/*************************************************************************
* This file randomly permutes the contents of an array.
* flag == 0, don't initialize perm
* flag == 1, set p[i] = i
**************************************************************************/
void FastRandomPermute(int n, idxtype *p, int flag)
{
int i, u, v;
idxtype tmp;
if (flag == 1) {
for (i=0; i<n; i++)
p[i] = i;
}
for (i=0; i<n; i+=8) {
v = RandomInRange(n-4);
u = RandomInRange(n-4);
SWAP(p[v], p[u], tmp);
SWAP(p[v+1], p[u+1], tmp);
SWAP(p[v+2], p[u+2], tmp);
SWAP(p[v+3], p[u+3], tmp);
}
}

View File

@ -1,69 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* util.c
*
* This file contains utility functions
*
*/
#include "IMlib.h"
/*************************************************************************
* This function prints an error message and exits
**************************************************************************/
void *errexit(char *f_str,...)
{
va_list argp;
va_start(argp, f_str);
vfprintf(stderr, f_str, argp);
va_end(argp);
fprintf(stderr,"\n");
fflush(stderr);
exit(0);
}
/*************************************************************************
* This function returns the log2(x)
**************************************************************************/
int IMlog2(int a)
{
int i;
for (i=1; a > 1; i++, a = a>>1);
return i-1;
}
/*************************************************************************
* This function returns the log2(x)
**************************************************************************/
double flog2(double a)
{
return log(a)/log(2.0);
}
/*************************************************************************
* This function returns true if the a is a power of 2
**************************************************************************/
int ispow2(int a)
{
for (; a%2 != 1; a = a>>1);
return (a > 1 ? 0 : 1);
}
/*************************************************************************
* This function returns the seconds
**************************************************************************/
double seconds(void)
{
return((double) clock()/CLOCKS_PER_SEC);
}

View File

@ -1,10 +0,0 @@
aratio.c
coarsen.c
kwayfm.c
match.c
merge.c
mgridgen.c
refine.c
setup.c
LIB = $(FOAM_LIBBIN)/libMGridGen

View File

@ -1,7 +0,0 @@
TYPE_REAL=
#if defined(SP)
TYPE_REAL=-DTYPE_REAL
#endif
EXE_INC = -I../IMlib $(TYPE_REAL)
LIB_LIBS = -lIMlib

View File

@ -1,42 +0,0 @@
include ../../Makefile.in
DEBUGFLAGS =
ifeq ($(ddmalloc),yes)
INCDIR := $(INCDIR) -I$(DMALLOCDIR)/include
DEBUGFLAGS := $(DEBUGFLAGS) -DDMALLOC -DDEBUG
OPTFLAGS = -g
endif
ifeq ($(dmalloc),yes)
INCDIR := $(INCDIR) -I$(DMALLOCDIR)/include
DEBUGFLAGS := $(DEBUGFLAGS) -DDMALLOC
endif
ifeq ($(debug),yes)
DEBUGFLAGS := $(DEBUGFLAGS) -DDEBUG
OPTFLAGS = -g
endif
INCLUDES = -I./ -I$(IMLIBDIR) $(INCDIR)
CFLAGS = $(COPTIONS) $(OPTFLAGS) $(DEBUGFLAGS) $(INCLUDES)
OBJS = coarsen.o kwayfm.o match.o merge.o mgridgen.o refine.o setup.o
IOBJS = blas.o dfkeysort.o dkeysort.o file.o ifkeysort.o ifloatsort.o \
iintsort.o ikeysort.o memory.o sort.o util.o
IMOBJS = $(addprefix ../IMlib/, $(IOBJS))
.c.o:
$(CC) $(CFLAGS) -c $*.c
../../libmgrid.a: $(OBJS) $(IMOBJS)
$(AR) $@ $(OBJS) $(IMOBJS)
$(RANLIB) $@
clean:
rm -f *.o
realclean:
rm -f *.o ; rm -f ../../libmgrid.a

View File

@ -1,81 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* aratio.c
*
* This file contains the aspect ratio definition for 2D and 3D
*
* Irene
*/
#include "mgridgen.h"
ASPECTRATIOFUNCTION ARATIO1;
ASPECTRATIOFUNCTION ARATIO;
ASPECTRATIOFUNCTION ARATIO2;
/*************************************************************************
* Aspect Ratio Definition for 2-D problems
*************************************************************************/
realtype ARATIO1_2D(realtype circumf, realtype surf)
{
realtype ar;
ar = pow((circumf), 2)/(surf);
return ar;
}
realtype ARATIO_2D(realtype circumf, realtype surf)
{
realtype ar;
ar = ((circumf)*(circumf))/(surf);
return ar;
}
realtype ARATIO2_2D(realtype circumf, realtype surf)
{
realtype ar;
ar = ((circumf)*(circumf)*(circumf)*(circumf))/((surf)*(surf));
return ar;
}
/*************************************************************************
* Aspect Ratio Definition for 3-D problems
*************************************************************************/
realtype ARATIO1_3D(realtype surf, realtype vol)
{
realtype ar;
ar = pow((surf), 1.5)/(vol);
return ar;
}
realtype ARATIO_3D(realtype surf, realtype vol)
{
realtype ar;
ar = sqrt((surf)*(surf)*(surf))/(vol);
return ar;
}
realtype ARATIO2_3D(realtype surf, realtype vol)
{
realtype ar;
ar = ((surf)*(surf)*(surf))/((vol)*(vol));
return ar;
}

View File

@ -1,235 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* coarsen.c
*
* This file contains the driving routines for the coarsening process
*
* George Irene
*/
#include "mgridgen.h"
/*************************************************************************
* This function takes a graph and creates a sequence of coarser graphs
**************************************************************************/
GraphType *Coarsen(CtrlType *ctrl, GraphType *graph)
{
int j=0;
GraphType *cgraph;
cgraph = graph;
do {
IFSET(ctrl->dbglvl, DBG_COARSEN, printf("%6d %7d\n", cgraph->nvtxs,
cgraph->xadj[cgraph->nvtxs]));
switch (ctrl->CType) {
case MATCH_RM:
Match_RM(ctrl, cgraph);
break;
case MATCH_HEM:
Match_HEM(ctrl, cgraph);
break;
case MATCH_HEM_SLOW:
Match_HEM_Slow(ctrl, cgraph);
break;
case MATCH_HEM_TRUE:
Match_HEM_True(ctrl, cgraph);
break;
default:
errexit("Unknown CType: %d\n", ctrl->CType);
}
j++;
cgraph = cgraph->coarser;
} while (cgraph->nvtxs < cgraph->finer->nvtxs);
IFSET(ctrl->dbglvl, DBG_COARSEN, printf("Coarsening Info : %d %d %d\n",j,
cgraph->nvtxs, cgraph->finer->nvtxs));
return cgraph;
}
/*************************************************************************
* This function takes a graph and creates a sequence of coarser graphs
**************************************************************************/
GraphType *Coarsen_Restricted(CtrlType *ctrl, GraphType *graph)
{
int i, nvtxs;
idxtype *cmap, *where;
GraphType *cgraph;
cgraph = graph;
do {
IFSET(ctrl->dbglvl, DBG_COARSEN, printf("%6d %7d\n", cgraph->nvtxs,
cgraph->xadj[cgraph->nvtxs]));
Match_HEM_Slow_Restricted(ctrl, cgraph);
/* Propagate the where vector downwards */
nvtxs = cgraph->nvtxs;
cmap = cgraph->cmap;
where = cgraph->where;
cgraph = cgraph->coarser;
cgraph->where = idxmalloc(cgraph->nvtxs, "cgraph->where");
for (i=0; i<nvtxs; i++)
cgraph->where[cmap[i]] = where[i];
IMfree(&(cgraph->finer->where), LTERM);
} while (cgraph->nvtxs < cgraph->finer->nvtxs);
if (cgraph->nvtxs != ctrl->nparts)
printf("It appears that some domains are non-contigous [%d %d]\n",
cgraph->nvtxs, ctrl->nparts);
IMfree(&(cgraph->where), LTERM);
/* Perform any additional coarsening */
do {
IFSET(ctrl->dbglvl, DBG_COARSEN, printf("%6d %7d\n", cgraph->nvtxs,
cgraph->xadj[cgraph->nvtxs]));
Match_HEM_Slow(ctrl, cgraph);
cgraph = cgraph->coarser;
} while (cgraph->nvtxs < cgraph->finer->nvtxs);
return cgraph;
}
/*************************************************************************
* This function creates the coarser graph
**************************************************************************/
void CreateCoarseGraph(GraphType *graph, int cnvtxs, idxtype *match,
idxtype *perm)
{
int i, j, k, m, nvtxs, nedges, cnedges, v, u;
idxtype *xadj, *vwgt, *adjncy;
idxtype *cxadj, *cvwgt, *cadjncy;
realtype *vvol, *vsurf, *adjwgt, *adjwgtsum;
realtype *cvvol, *cvsurf, *cadjwgt, *cadjwgtsum;
idxtype *cmap, *htable;
GraphType *cgraph;
nvtxs = graph->nvtxs;
xadj = graph->xadj;
vwgt = graph->vwgt;
vvol = graph->vvol;
vsurf = graph->vsurf;
adjncy = graph->adjncy;
adjwgt = graph->adjwgt;
adjwgtsum = graph->adjwgtsum;
cmap = graph->cmap;
/* Initialize the coarser graph */
cgraph = SetUpCoarseGraph(graph, cnvtxs);
cxadj = cgraph->xadj;
cvwgt = cgraph->vwgt;
cvvol = cgraph->vvol;
cvsurf = cgraph->vsurf;
cadjncy = cgraph->adjncy;
cadjwgt = cgraph->adjwgt;
cadjwgtsum = cgraph->adjwgtsum;
htable = idxsmalloc(cnvtxs, -1, "htable");
cxadj[0] = cnvtxs = cnedges = 0;
for (i=0; i<nvtxs; i++) {
v = perm[i];
if (cmap[v] != cnvtxs)
continue;
u = match[v];
cvwgt[cnvtxs] = vwgt[v];
cvvol[cnvtxs] = vvol[v];
cvsurf[cnvtxs] = vsurf[v];
cadjwgtsum[cnvtxs] = adjwgtsum[v];
for (nedges=0, j=xadj[v]; j<xadj[v+1]; j++) {
k = cmap[adjncy[j]];
if ((m = htable[k]) == -1) {
cadjncy[nedges] = k;
cadjwgt[nedges] = adjwgt[j];
htable[k] = nedges++;
}
else
cadjwgt[m] += adjwgt[j];
}
if (v != u) {
cvwgt[cnvtxs] += vwgt[u];
cvvol[cnvtxs] += vvol[u];
cvsurf[cnvtxs] += vsurf[u];
cadjwgtsum[cnvtxs] += adjwgtsum[u];
for (j=xadj[u]; j<xadj[u+1]; j++) {
k = cmap[adjncy[j]];
if ((m = htable[k]) == -1) {
cadjncy[nedges] = k;
cadjwgt[nedges] = adjwgt[j];
htable[k] = nedges++;
}
else
cadjwgt[m] += adjwgt[j];
}
/* Remove the contracted adjacency weight */
if ((j = htable[cnvtxs]) != -1) {
ASSERT(cadjncy[j] == cnvtxs);
cadjwgtsum[cnvtxs] -= cadjwgt[j];
cadjncy[j] = cadjncy[--nedges];
cadjwgt[j] = cadjwgt[nedges];
htable[cnvtxs] = -1;
}
}
for (j=0; j<nedges; j++)
htable[cadjncy[j]] = -1; /* Zero out the htable */
cnedges += nedges;
cxadj[++cnvtxs] = cnedges;
cadjncy += nedges;
cadjwgt += nedges;
}
free(htable);
}
/*************************************************************************
* Setup the various arrays for the coarse graph
**************************************************************************/
GraphType *SetUpCoarseGraph(GraphType *graph, int cnvtxs)
{
int nedges;
GraphType *cgraph;
cgraph = CreateGraph();
cgraph->nvtxs = cnvtxs;
cgraph->finer = graph;
graph->coarser = cgraph;
nedges = graph->xadj[graph->nvtxs];
/* Allocate memory for the coarser graph */
cgraph->xadj = idxmalloc(cnvtxs+1, "xadj");
cgraph->vwgt = idxmalloc(cnvtxs, "vwgt");
cgraph->vvol = realmalloc(cnvtxs, "vvol");
cgraph->vsurf = realmalloc(cnvtxs, "vsurf");
cgraph->adjwgtsum = realmalloc(cnvtxs, "adjwgtsum");
cgraph->adjncy = idxmalloc(nedges, "adjncy");
cgraph->adjwgt = realmalloc(nedges, "adjwgt");
return cgraph;
}

View File

@ -1,52 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* defs.h
*
* This file contains constant definitions
*
* George Irene
*/
#define MAXLINE 1280000
/* Meaning of various options[] parameters */
#define OPTION_CTYPE 0
#define OPTION_RTYPE 1
#define OPTION_DBGLVL 2
#define OPTION_DIM 3
/* CType Schemes */
#define MATCH_RM 1
#define MATCH_HEM 2
#define MATCH_HEM_SLOW 3
#define MATCH_HEM_TRUE 4
/* RType Schemes */
#define REFINE_AR 1
#define REFINE_WAR 2
#define REFINE_SCUT 3
#define REFINE_MINMAXAVAR 4
#define REFINE_MINMAXAR 5
#define REFINE_MULTIOBJECTIVE 6
#define REFINE_MULTIOBJECTIVE2 7
#define UNMATCHED -1
#define MAXIDX (1<<30)
#define HTABLE_EMPTY -1
/* Debug Levels */
#define DBG_PROGRESS 1 /* If you should show size info per level */
#define DBG_OUTPUT 2 /* If you should output intermediate partitions */
#define DBG_COARSEN 4
#define DBG_REFINE 8
#define DBG_MOVEINFO 16
#define DBG_MERGE 32 /* If you should check merging */
#define DBG_CONTR 64 /* If you should check contributing */
#define DBG_TRACK 128 /* Track progress; Print Final Results only */

View File

@ -1,18 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* macros.h
*
* This file contains macros used in multilevel
*
* George Irene
*/
#define ARATIO1(dim, surf, vol) ((dim == 2) ? (pow((surf), 2)/(vol)) : (pow((surf), 1.5)/(vol)))
#define ARATIO(dim, surf, vol) ((dim == 2) ? ((surf)*(surf)/(vol)) : (sqrt((surf)*(surf)*(surf))/(vol)))
#define ARATIO2(dim, surf, vol) ((dim == 2) ? ((surf)*(surf)*(surf)*(surf)/(vol)*(vol)) : ((surf)*(surf)*(surf)/((vol)*(vol))))
/*************************************************************************
* This macro is used to handle dbglvl
**************************************************************************/
#define IFSET(a, flag, cmd) if ((a)&(flag)) (cmd);

View File

@ -1,343 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* match.c
*
* This file contains the matching routines coarsening
*
* George Irene
*/
#include "mgridgen.h"
/*************************************************************************
* This function finds a matching using the HEM heuristic
**************************************************************************/
void Match_RM(CtrlType *ctrl, GraphType *graph)
{
int i, ii, j, k, nvtxs, cnvtxs, maxidx;
idxtype *xadj, *vwgt, *adjncy;
idxtype *match, *cmap, *perm;
nvtxs = graph->nvtxs;
xadj = graph->xadj;
vwgt = graph->vwgt;
adjncy = graph->adjncy;
cmap = graph->cmap = idxsmalloc(nvtxs, -1, "graph->cmap");
match = idxsmalloc(nvtxs, -1, "match");
perm = idxmalloc(nvtxs, "perm");
RandomPermute(nvtxs, perm, 1);
cnvtxs = 0;
for (ii=0; ii<nvtxs; ii++) {
i = perm[ii];
if (match[i] == UNMATCHED) {
maxidx = i;
/* Find a random matching, subject to maxvwgt constraints */
for (j=xadj[i]; j<xadj[i+1]; j++) {
k = adjncy[j];
if (match[k] == UNMATCHED && vwgt[i]+vwgt[k] <= ctrl->maxsize) {
maxidx = k;
break;
}
}
cmap[i] = cmap[maxidx] = cnvtxs++;
match[i] = maxidx;
match[maxidx] = i;
}
}
CreateCoarseGraph(graph, cnvtxs, match, perm);
IMfree(&match, &perm, LTERM);
}
/*************************************************************************
* This function finds a matching using the HEM heuristic
**************************************************************************/
void Match_HEM(CtrlType *ctrl, GraphType *graph)
{
int i, ii, j, k, nvtxs, cnvtxs, maxidx, dim;
idxtype *xadj, *vwgt, *adjncy;
idxtype *match, *cmap, *perm, *tperm;
realtype curwgt, maxwgt;
realtype *vvol, *vsurf, *adjwgt, *adjwgtsum;
dim = ctrl->dim;
nvtxs = graph->nvtxs;
xadj = graph->xadj;
vwgt = graph->vwgt;
vvol = graph->vvol;
vsurf = graph->vsurf;
adjncy = graph->adjncy;
adjwgt = graph->adjwgt;
adjwgtsum = graph->adjwgtsum;
cmap = graph->cmap = idxsmalloc(nvtxs, -1, "cmap");
match = idxsmalloc(nvtxs, -1, "match");
perm = idxmalloc(nvtxs, "perm");
tperm = idxmalloc(nvtxs, "tperm");
RandomPermute(nvtxs, tperm, 1);
BucketSortKeysInc(nvtxs, vwgt[iamax(nvtxs, vwgt)], vwgt, tperm, perm);
/* RandomPermute(nvtxs, perm, 1); */
cnvtxs = 0;
/* Compute a heavy-edge style matching giving preferance to small vertices */
for (ii=0; ii<nvtxs; ii++) {
i = perm[ii];
if (match[i] == UNMATCHED) {
maxidx = i;
maxwgt = 0.0;
/* Find a heavy-edge matching, subject to maxvwgt constraints */
for (j=xadj[i]; j<xadj[i+1]; j++) {
k = adjncy[j];
curwgt = 1.0/ARATIO2(dim, vsurf[i]+vsurf[k]+adjwgtsum[i]+adjwgtsum[k]-
2.0*adjwgt[j], vvol[i]+vvol[k]);
if (match[k] == UNMATCHED && vwgt[i]+vwgt[k] <= ctrl->maxsize &&
curwgt > maxwgt) {
maxwgt = curwgt;
maxidx = k;
}
}
cmap[i] = cmap[maxidx] = cnvtxs++;
match[i] = maxidx;
match[maxidx] = i;
}
}
CreateCoarseGraph(graph, cnvtxs, match, perm);
IMfree(&tperm, &perm, &match, LTERM);
}
/*************************************************************************
* This function finds a matching using the HEM heuristic
**************************************************************************/
void Match_HEM_Slow(CtrlType *ctrl, GraphType *graph)
{
int i, ii, j, k, dim, nvtxs, cnvtxs, maxidx, nmatched;
idxtype *xadj, *vwgt, *adjncy;
idxtype *match, *cmap, *perm, *tperm;
realtype curwgt, maxwgt;
realtype *vvol, *vsurf, *adjwgt, *adjwgtsum;
dim = ctrl->dim;
nvtxs = graph->nvtxs;
xadj = graph->xadj;
vwgt = graph->vwgt;
vvol = graph->vvol;
vsurf = graph->vsurf;
adjncy = graph->adjncy;
adjwgt = graph->adjwgt;
adjwgtsum = graph->adjwgtsum;
cmap = graph->cmap = idxsmalloc(nvtxs, -1, "cmap");
match = idxsmalloc(nvtxs, -1, "match");
perm = idxmalloc(nvtxs, "perm");
tperm = idxmalloc(nvtxs, "tperm");
RandomPermute(nvtxs, tperm, 1);
BucketSortKeysInc(nvtxs, vwgt[iamax(nvtxs, vwgt)], vwgt, tperm, perm);
/* RandomPermute(nvtxs, perm, 1); */
cnvtxs = 0;
/* Compute a heavy-edge style matching giving preferance to small vertices */
for (nmatched=0, ii=0; ii<nvtxs; ii++) {
i = perm[ii];
if (match[i] == UNMATCHED) {
maxidx = i;
maxwgt = 0.0;
/* Find a heavy-edge matching, subject to maxvwgt constraints */
if (nmatched < .25*nvtxs) {
for (j=xadj[i]; j<xadj[i+1]; j++) {
k = adjncy[j];
if (match[k] == UNMATCHED) {
curwgt = 1.0/ARATIO2(dim, vsurf[i]+vsurf[k]+adjwgtsum[i]+adjwgtsum[k]
-2.0*adjwgt[j], vvol[i]+vvol[k]);
if (vwgt[i]+vwgt[k] <= ctrl->maxsize && curwgt > maxwgt) {
maxwgt = curwgt;
maxidx = adjncy[j];
}
}
}
}
if (maxidx != i)
nmatched++;
cmap[i] = cmap[maxidx] = cnvtxs++;
match[i] = maxidx;
match[maxidx] = i;
}
}
CreateCoarseGraph(graph, cnvtxs, match, perm);
IMfree(&tperm, &perm, &match, LTERM);
}
/*************************************************************************
* This function finds a matching using the HEM heuristic
**************************************************************************/
void Match_HEM_Slow_Restricted(CtrlType *ctrl, GraphType *graph)
{
int i, ii, j, k, dim, nvtxs, cnvtxs, maxidx, nmatched;
idxtype *xadj, *vwgt, *adjncy, *where;
idxtype *match, *cmap, *perm;
realtype curwgt, maxwgt;
realtype *vvol, *vsurf, *adjwgt, *adjwgtsum;
dim = ctrl->dim;
nvtxs = graph->nvtxs;
xadj = graph->xadj;
vwgt = graph->vwgt;
vvol = graph->vvol;
vsurf = graph->vsurf;
adjncy = graph->adjncy;
adjwgt = graph->adjwgt;
adjwgtsum = graph->adjwgtsum;
where = graph->where;
cmap = graph->cmap = idxsmalloc(nvtxs, -1, "cmap");
match = idxsmalloc(nvtxs, -1, "match");
perm = idxmalloc(nvtxs, "perm");
RandomPermute(nvtxs, perm, 1);
cnvtxs = 0;
/* Compute a heavy-edge style matching giving preferance to small vertices */
for (nmatched=0, ii=0; ii<nvtxs; ii++) {
i = perm[ii];
if (match[i] == UNMATCHED) {
maxidx = i;
maxwgt = 0.0;
/* Find a heavy-edge matching, subject to maxvwgt constraints */
if (nmatched < .3*nvtxs) {
for (j=xadj[i]; j<xadj[i+1]; j++) {
k = adjncy[j];
if (where[i] != where[k])
continue; /* perform a restricted matching */
curwgt = 1.0/ARATIO2(dim, vsurf[i]+vsurf[k]+adjwgtsum[i]+adjwgtsum[k]
-2.0*adjwgt[j], vvol[i]+vvol[k]);
if (match[k] == UNMATCHED && vwgt[i]+vwgt[k] <= ctrl->maxsize &&
curwgt > maxwgt) {
maxwgt = curwgt;
maxidx = k;
}
}
}
if (maxidx != i)
nmatched++;
cmap[i] = cmap[maxidx] = cnvtxs++;
match[i] = maxidx;
match[maxidx] = i;
}
}
CreateCoarseGraph(graph, cnvtxs, match, perm);
IMfree(&perm, &match, LTERM);
}
/*************************************************************************
* This function finds a matching using the HEM heuristic
**************************************************************************/
void Match_HEM_True(CtrlType *ctrl, GraphType *graph)
{
int i, ii, j, k, dim, nvtxs, cnvtxs, ncand;
idxtype *xadj, *vwgt, *adjncy;
idxtype *match, *cmap, *perm;
realtype *vvol, *vsurf, *adjwgt, *adjwgtsum;
FKeyValueType *cand;
dim = ctrl->dim;
nvtxs = graph->nvtxs;
xadj = graph->xadj;
vwgt = graph->vwgt;
vvol = graph->vvol;
vsurf = graph->vsurf;
adjncy = graph->adjncy;
adjwgt = graph->adjwgt;
adjwgtsum = graph->adjwgtsum;
cmap = graph->cmap = idxsmalloc(nvtxs, -1, "cmap");
match = idxsmalloc(nvtxs, -1, "match");
perm = idxmalloc(nvtxs, "perm");
RandomPermute(nvtxs, perm, 1);
cand = (FKeyValueType *)IMmalloc((xadj[nvtxs]/2)*sizeof(FKeyValueType), "cand");
/* insert the vertices according to their aspect ratio */
for (ncand=0, ii=0; ii<nvtxs; ii++) {
i = perm[ii];
for (j=xadj[i]; j<xadj[i+1]; j++) {
k = adjncy[j];
if (k > i || vwgt[i] + vwgt[k] > ctrl->maxsize)
continue;
cand[ncand].val1 = i;
cand[ncand].val2 = k;
cand[ncand].key = ARATIO2(dim, vsurf[i]+vsurf[k]+adjwgtsum[i]+adjwgtsum[k]
-2.0*adjwgt[j], vvol[i]+vvol[k]);
ncand++;
}
}
ifkeysort(ncand, cand);
/* Compute heaviest style matching */
idxset(nvtxs, -1, perm);
for (cnvtxs=0, ii=0; ii<ncand; ii++) {
if (cnvtxs > .25*nvtxs)
break;
i = cand[ii].val1;
k = cand[ii].val2;
if (match[i] == UNMATCHED && match[k] == UNMATCHED) {
perm[cnvtxs] = i;
perm[nvtxs-cnvtxs-1] = k;
cmap[i] = cmap[k] = cnvtxs++;
match[i] = k;
match[k] = i;
}
}
/* take care of the unmatched vertices */
for (i=0; i<nvtxs; i++) {
if (match[i] == UNMATCHED) {
perm[cnvtxs] = i;
cmap[i] = cnvtxs++;
match[i] = i;
}
}
CreateCoarseGraph(graph, cnvtxs, match, perm);
IMfree(&cand, &perm, &match, LTERM);
}

View File

@ -1,110 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* mgridgen.c
*
* This file contains the top level routines for the sparse hierarchical
* clustering algorithm.
*
* George Irene
*/
#include "mgridgen.h"
/*************************************************************************
* This function is the entry point for the SHCluster() routine.
**************************************************************************/
void MGridGen(int nvtxs, idxtype *xadj, realtype *vvol, realtype *vsurf,
idxtype *adjncy, realtype *adjwgt, int minsize, int maxsize,
int *options, int *nmoves, int *nparts, idxtype *part)
{
GraphType graph;
CtrlType ctrl;
srand(4321);
srand48(7654321L);
/*------------------------------------------------------------
* Set up the various control structures
*------------------------------------------------------------*/
ctrl.CType = options[OPTION_CTYPE];
ctrl.RType = options[OPTION_RTYPE];
ctrl.dbglvl = options[OPTION_DBGLVL];
ctrl.dim = options[OPTION_DIM];
ctrl.minsize = minsize;
ctrl.maxsize = maxsize;
ctrl.nparts = -1;
/*------------------------------------------------------------
* Set up the graph
*------------------------------------------------------------*/
SetUpGraph(&graph, nvtxs, xadj, vvol, vsurf, adjncy, adjwgt);
CreateGrid(&ctrl, &graph);
*nparts = ctrl.nparts;
icopy(nvtxs, graph.where, part);
*nmoves = graph.nmoves;
FreeGraph(&graph);
}
/*************************************************************************
* This function is the entry point for performing refinement
**************************************************************************/
void MGridGenRefine(int nvtxs, idxtype *xadj, realtype *vvol, realtype *vsurf,
idxtype *adjncy, idxtype *fusedinfo, realtype *adjwgt,
int minsize, int maxsize, int *options, int *nmoves,
int *nparts, idxtype *part)
{
int i;
GraphType graph;
CtrlType ctrl;
srand(4321);
srand48(7654321L);
/*------------------------------------------------------------
* Set up the various control structures
*------------------------------------------------------------*/
ctrl.CType = options[OPTION_CTYPE];
ctrl.RType = options[OPTION_RTYPE];
ctrl.dbglvl = options[OPTION_DBGLVL];
ctrl.dim = options[OPTION_DIM];
ctrl.minsize = minsize;
ctrl.maxsize = maxsize;
ctrl.nparts = -1;
/*------------------------------------------------------------
* Set up the graph
*------------------------------------------------------------*/
SetUpGraph(&graph, nvtxs, xadj, vvol, vsurf, adjncy, adjwgt);
graph.cmap = NULL;
graph.where = idxmalloc(graph.nvtxs, "graph.where");
for (i=0; i<graph.nvtxs; i++)
graph.where[i] = fusedinfo[i];
RefineKWayOnce(&ctrl, &graph, 10);
*nparts = ctrl.nparts;
icopy(nvtxs, graph.where, part);
*nmoves = graph.nmoves;
FreeGraph(&graph);
}
/*************************************************************************
* This function creates the coarse grid
**************************************************************************/
void CreateGrid(CtrlType *ctrl, GraphType *graph)
{
GraphType *cgraph;
cgraph = Coarsen(ctrl, graph);
RefineKWay(ctrl, graph, cgraph, 10);
}

View File

@ -1,35 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* mgridgen.h
*
* This file includes all necessary header files
*
* George Irene
*/
#include <stdio.h>
#ifdef __STDC__
#include <stdlib.h>
#else
/* #include <malloc.h> */
#endif
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdarg.h>
#include <time.h>
#include "IMlib.h"
#ifdef DMALLOC
#include <dmalloc.h>
#else
#include <malloc.h>
#endif
#include "defs.h"
#include "struct.h"
#include "macros.h"
#include "proto.h"

View File

@ -1,98 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* proto.h
*
* This file contains header files
*
* George Irene
*/
/* coarsen.c */
GraphType *Coarsen(CtrlType *, GraphType *);
GraphType *Coarsen_Restricted(CtrlType *, GraphType *);
void CreateCoarseGraph(GraphType *, int, idxtype *, idxtype *);
GraphType *SetUpCoarseGraph(GraphType *, int);
/* io.c */
void ReadGraph(GraphType *, char *);
void TransformGraph(char *);
void WritePartition(char *, idxtype *, int, int);
void PrintGraph(GraphType *);
/* kwayfm.c */
void Random_KWayARatioRefine(CtrlType *, GraphType *, int);
void Random_KWayWeightARatioRefine(CtrlType *, GraphType *, int);
void Random_KWaySCutRefine(CtrlType *, GraphType *, int);
void Random_KWayMinMaxAverageARatioRefine(CtrlType *, GraphType *, int);
void Random_KWayMinMaxARatioRefine(CtrlType *, GraphType *, int);
void Random_KWayMultiObjRefine(CtrlType *, GraphType *, int);
void Random_KWayMultiObjRefine2(CtrlType *, GraphType *, int);
void CheckParams(CtrlType *, GraphType *);
/* match.c */
void Match_RM(CtrlType *, GraphType *);
void Match_HEM(CtrlType *, GraphType *);
void Match_HEM_Slow(CtrlType *, GraphType *);
void Match_HEM_Slow_Restricted(CtrlType *ctrl, GraphType *graph);
void Match_HEM_True(CtrlType *, GraphType *);
/* merge.c */
void Cycle(CtrlType *, GraphType *, int);
void Merge(CtrlType *, GraphType *, int);
void Contribute(CtrlType *, GraphType *, int);
void Merge_ARatio(CtrlType *, GraphType *);
void Merge_WeightARatio(CtrlType *, GraphType *);
void Merge_MinMaxARatio(CtrlType *, GraphType *);
void Merge_MultiObj(CtrlType *, GraphType *);
void Merge0(CtrlType *, GraphType *);
void Contribute_ARatio(CtrlType *, GraphType *);
void Contribute_WeightARatio(CtrlType *, GraphType *);
void Contribute_MinMaxARatio(CtrlType *, GraphType *);
void Contribute_MultiObj(CtrlType *, GraphType *);
/* mgridgen.c */
void MGridGen(int, idxtype *, realtype *, realtype *, idxtype *, realtype *,
int, int, int *, int *, int *, idxtype *);
void MGridGenRefine(int, idxtype *, realtype *, realtype *, idxtype *,
idxtype *, realtype *, int , int , int *, int *, int *,
idxtype *);
void CreateGrid(CtrlType *, GraphType *);
/* refine.c */
void RefineKWay(CtrlType *, GraphType *, GraphType *, int);
void RefineKWayOnce(CtrlType *, GraphType *, int);
void ComputeKWayPartitionParams(CtrlType *, GraphType *);
void ProjectKWayPartition(GraphType *);
void ComputeGridStatistics(CtrlType *, GraphType *);
void BreakComponents(CtrlType *, GraphType *);
realtype ComputeFunction(int, CtrlType *, GraphType *);
void ComputeAllFunctions(CtrlType *, GraphType *);
/* setup.c */
void SetUpGraph(GraphType *, int, idxtype *, realtype *, realtype *, idxtype *,
realtype *);
void FreeGraph(GraphType *);
GraphType *CreateGraph(void);
/* aratio.c */
realtype ARATIO1_2D(realtype, realtype);
realtype ARATIO_2D(realtype, realtype);
realtype ARATIO2_2D(realtype, realtype);
realtype ARATIO1_3D(realtype, realtype);
realtype ARATIO_3D(realtype, realtype);
realtype ARATIO2_3D(realtype, realtype);
typedef realtype (*ASPECTRATIOFUNCTION) (realtype, realtype);
extern ASPECTRATIOFUNCTION ARATIO1;
extern ASPECTRATIOFUNCTION ARATIO;
extern ASPECTRATIOFUNCTION ARATIO2;

View File

@ -1,454 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* refine.c
*
* This file contains the driving routines for multilevel k-way refinement
*
* George Irene
*/
#include "mgridgen.h"
/*************************************************************************
* This function is the entry point of refinement
**************************************************************************/
void RefineKWay(CtrlType *ctrl, GraphType *orggraph, GraphType *graph, int npasses)
{
int i;
ctrl->nparts = graph->nvtxs;
graph->where = idxmalloc(graph->nvtxs, "graph->where");
for (i=0; i<graph->nvtxs; i++)
graph->where[i] = i;
ComputeKWayPartitionParams(ctrl, graph);
/* Get into the refinement loop */
for (;;) {
switch (ctrl->RType) {
case REFINE_AR:
Random_KWayARatioRefine(ctrl, graph, npasses);
break;
case REFINE_WAR:
Random_KWayWeightARatioRefine(ctrl, graph, npasses);
break;
case REFINE_SCUT:
Random_KWaySCutRefine(ctrl, graph, npasses);
break;
case REFINE_MINMAXAVAR:
Random_KWayMinMaxAverageARatioRefine(ctrl, graph, npasses);
break;
case REFINE_MINMAXAR:
Random_KWayMinMaxARatioRefine(ctrl, graph, npasses);
break;
case REFINE_MULTIOBJECTIVE:
Random_KWayMultiObjRefine(ctrl, graph, npasses);
break;
case REFINE_MULTIOBJECTIVE2:
Random_KWayMultiObjRefine2(ctrl, graph, npasses);
break;
default:
errexit("Unknown RType of %d\n", ctrl->RType);
}
if (graph == orggraph)
break;
else
graph = graph->finer;
ProjectKWayPartition(graph);
BreakComponents(ctrl, graph);
Merge(ctrl, graph, npasses);
ComputeKWayPartitionParams(ctrl, graph);
IFSET(ctrl->dbglvl, DBG_REFINE,
printf("Level done nparts=%d minratio=%e\n", ctrl->nparts,
graph->minratio));
}
BreakComponents(ctrl, graph);
Merge(ctrl, graph, npasses);
IMfree(&graph->pwgts, &graph->pvol, &graph->psurf, LTERM);
ComputeKWayPartitionParams(ctrl, graph);
Random_KWayMultiObjRefine(ctrl, graph, npasses);
Cycle(ctrl, graph, npasses);
IMfree(&graph->pwgts, &graph->pvol, &graph->psurf, LTERM);
IFSET(ctrl->dbglvl, DBG_REFINE, ComputeKWayPartitionParams(ctrl, graph));
IFSET(ctrl->dbglvl, DBG_REFINE,
printf("Last level done nparts=%d minratio=%e\n",
ctrl->nparts, graph->minratio));
IMfree(&graph->pwgts, &graph->pvol, &graph->psurf, LTERM);
IFSET(ctrl->dbglvl, DBG_TRACK, ComputeKWayPartitionParams(ctrl, graph));
IFSET(ctrl->dbglvl, DBG_TRACK, ComputeGridStatistics(ctrl, graph));
}
/*************************************************************************
* This function is the entry point of refinement
**************************************************************************/
void RefineKWayOnce(CtrlType *ctrl, GraphType *graph, int npasses)
{
int i, nvtxs;
int nparts, lastpart;
idxKeyValueType *pairs;
nvtxs = graph->nvtxs;
pairs = (idxKeyValueType *) IMmalloc(nvtxs * sizeof(idxKeyValueType), "pairs");
/* Find the number of elements: npart */
for (i=0; i<nvtxs; i++) {
pairs[i].key = graph->where[i];
pairs[i].val = i;
}
idxkeysort(nvtxs, pairs);
nparts = 1;
lastpart = pairs[0].key;
pairs[0].key = nparts - 1;
for (i=1; i<nvtxs; i++) {
if (pairs[i].key > lastpart) {
nparts++;
lastpart = pairs[i].key;
}
pairs[i].key = nparts - 1;
}
ctrl->nparts = nparts;
for (i=0; i<nvtxs; i++)
graph->where[pairs[i].val] = pairs[i].key;
IMfree(&pairs, LTERM);
/* Perform the refinement */
ComputeKWayPartitionParams(ctrl, graph);
switch (ctrl->RType) {
case REFINE_AR:
Random_KWayARatioRefine(ctrl, graph, npasses);
break;
case REFINE_WAR:
Random_KWayWeightARatioRefine(ctrl, graph, npasses);
break;
case REFINE_SCUT:
Random_KWaySCutRefine(ctrl, graph, npasses);
break;
case REFINE_MINMAXAVAR:
Random_KWayMinMaxAverageARatioRefine(ctrl, graph, npasses);
break;
case REFINE_MINMAXAR:
Random_KWayMinMaxARatioRefine(ctrl, graph, npasses);
break;
case REFINE_MULTIOBJECTIVE:
Random_KWayMultiObjRefine(ctrl, graph, npasses);
break;
case REFINE_MULTIOBJECTIVE2:
Random_KWayMultiObjRefine2(ctrl, graph, npasses);
break;
default:
errexit("Unknown RType of %d\n", ctrl->RType);
}
BreakComponents(ctrl, graph);
Merge(ctrl, graph, npasses);
IMfree(&graph->pwgts, &graph->pvol, &graph->psurf, LTERM);
ComputeKWayPartitionParams(ctrl, graph);
Random_KWayMultiObjRefine(ctrl, graph, npasses);
Cycle(ctrl, graph, npasses);
IMfree(&graph->pwgts, &graph->pvol, &graph->psurf, LTERM);
IFSET(ctrl->dbglvl, DBG_REFINE, ComputeKWayPartitionParams(ctrl, graph));
IFSET(ctrl->dbglvl, DBG_REFINE,
printf("Last level done nparts=%d minratio=%e\n", ctrl->nparts, graph->minratio));
IMfree(&graph->pwgts, &graph->pvol, &graph->psurf, LTERM);
IFSET(ctrl->dbglvl, DBG_TRACK, ComputeKWayPartitionParams(ctrl, graph));
IFSET(ctrl->dbglvl, DBG_TRACK, ComputeGridStatistics(ctrl, graph));
}
/*************************************************************************
* This function computes the parameters required for the partitioning
**************************************************************************/
void ComputeKWayPartitionParams(CtrlType *ctrl, GraphType *graph)
{
int i, j, me, nvtxs, nparts;
idxtype *xadj, *vwgt, *adjncy, *where, *pwgts;
realtype *vvol, *vsurf, *adjwgt, *pvol, *psurf;
nvtxs = graph->nvtxs;
xadj = graph->xadj;
vwgt = graph->vwgt;
vvol = graph->vvol;
vsurf = graph->vsurf;
adjncy = graph->adjncy;
adjwgt = graph->adjwgt;
where = graph->where;
nparts = ctrl->nparts;
pwgts = graph->pwgts = idxsmalloc(nparts, 0, "pwgts");
pvol = graph->pvol = realsmalloc(nparts, 0.0, "pvol");
psurf = graph->psurf = realsmalloc(nparts, 0.0, "psurf");
for (i=0; i<nvtxs; i++) {
me = where[i];
pwgts[me] += vwgt[i];
pvol[me] += vvol[i];
psurf[me] += vsurf[i];
for (j=xadj[i]; j<xadj[i+1]; j++) {
if (where[adjncy[j]] != me)
psurf[me] += adjwgt[j];
}
}
graph->minratio = ComputeFunction(ctrl->RType, ctrl, graph);
}
/*************************************************************************
* This function projects a partition, and at the same time computes the
* parameters for refinement.
**************************************************************************/
void ProjectKWayPartition(GraphType *graph)
{
int i, nvtxs;
idxtype *where, *cwhere, *cmap;
GraphType *cgraph;
nvtxs = graph->nvtxs;
cmap = graph->cmap;
where = graph->where = idxmalloc(nvtxs, "where");
cgraph = graph->coarser;
cwhere = cgraph->where;
/* Go through and project partition */
for (i=0; i<nvtxs; i++)
where[i] = cwhere[cmap[i]];
FreeGraph(cgraph);
IMfree(&(graph->coarser), LTERM);
}
/*************************************************************************
* This function computes the statistics for the grid
**************************************************************************/
void ComputeGridStatistics(CtrlType *ctrl, GraphType *graph)
{
int i, j, dim, nparts, nvtxs, from, to;
idxtype *pwgts, *counts;
idxtype *xadj, *adjncy, *where;
realtype ed, min, max, sum, wsum, ratio, surf;
realtype *pvol, *psurf;
dim = ctrl->dim;
nparts = ctrl->nparts;
where = graph->where;
nvtxs = graph->nvtxs;
xadj = graph->xadj;
adjncy = graph->adjncy;
pwgts = graph->pwgts;
pvol = graph->pvol;
psurf = graph->psurf;
counts = idxsmalloc(ctrl->maxsize+1, 0, "counts");
min = max = sum = ARATIO(dim, psurf[0], pvol[0]);
wsum = 1.0*pwgts[0]*ARATIO(dim, psurf[0], pvol[0]);
surf = psurf[0];
counts[pwgts[0]]++;
for (i=1; i<nparts; i++) {
ratio = ARATIO(dim, psurf[i], pvol[i]);
sum += ratio;
wsum += 1.0*pwgts[i]*ratio;
surf += psurf[i];
if (min > ratio)
min = ratio;
if (max < ratio)
max = ratio;
counts[pwgts[i]]++;
}
for (ed=0.0, i=0; i<nvtxs; i++) {
from = where[i];
for (j=xadj[i]; j<xadj[i+1]; j++) {
to = where[adjncy[j]];
if (to != from)
ed = ed + 1.0;
}
}
ed = ed/2;
printf("Npoints: %d, Coarsening Factor: %f\n", nparts, 1.0*graph->nvtxs/(1.0*nparts));
printf("Aspect Ratios: Min : %e, Max : %e\n", min, max);
printf("Aspect Ratios: Sum : %e, Wsum: %e\n", sum, wsum);
printf("Aspect Ratios: Surf: %e, Avg : %e\n", surf, sum/(1.0*nparts));
printf("Graph mincut : %e\n", ed);
printf("Cell size: min=%d, max=%d\n", ctrl->minsize, ctrl->maxsize);
printf("CellSizeDist: ");
for (i=1; i<=ctrl->maxsize; i++)
if (counts[i] != 0)
printf("[%2d %4d] ", i, counts[i]);
printf("\n");
IMfree(&counts,LTERM);
}
/*************************************************************************
* This function finds all the connected components induced by the
* partitioning vector and creates new partitions for each one of the
* components
**************************************************************************/
void BreakComponents(CtrlType *ctrl, GraphType *graph)
{
int i, j, k, me, nvtxs, nparts, first, last, nleft, ncmps;
idxtype *xadj, *adjncy, *where;
idxtype *touched, *perm, *todo, *cind, *cptr;
nvtxs = graph->nvtxs;
xadj = graph->xadj;
adjncy = graph->adjncy;
where = graph->where;
nparts = ctrl->nparts;
touched = idxsmalloc(nvtxs+1, 0, "touched");
cptr = idxmalloc(nvtxs+1, "cptr");
cind = idxmalloc(nvtxs+1, "cind");
perm = idxmalloc(nvtxs+1, "perm");
todo = idxmalloc(nvtxs+1, "todo");
for (i=0; i<nvtxs; i++)
perm[i] = todo[i] = i;
/* Find the connected componends induced by the partition */
ncmps = -1;
first = last = 0;
nleft = nvtxs;
while (nleft > 0) {
if (first == last) { /* Find another starting vertex */
cptr[++ncmps] = first;
ASSERT(touched[todo[0]] == 0);
i = todo[0];
cind[last++] = i;
touched[i] = 1;
me = where[i];
}
i = cind[first++];
k = perm[i];
j = todo[k] = todo[--nleft];
perm[j] = k;
for (j=xadj[i]; j<xadj[i+1]; j++) {
k = adjncy[j];
if (where[k] == me && !touched[k]) {
cind[last++] = k;
touched[k] = 1;
}
}
}
cptr[++ncmps] = first;
/* printf("I found %d components, for this %d-way partition\n", ncmps, nparts); */
if (ncmps > nparts) {
for (i=0; i<ncmps; i++) {
for (j=cptr[i]; j<cptr[i+1]; j++)
where[cind[j]] = i;
}
ctrl->nparts = ncmps;
}
IMfree(&touched, &cptr, &cind, &perm, &todo, LTERM);
}
/*************************************************************************
* This function computes the value of the RType function for the grid
**************************************************************************/
realtype ComputeFunction(int RType, CtrlType *ctrl, GraphType *graph)
{
int i, dim, nparts;
idxtype *pwgts;
realtype new, ratio;
realtype *pvol, *psurf;
dim = ctrl->dim;
nparts = ctrl->nparts;
pvol = graph->pvol;
psurf = graph->psurf;
pwgts = graph->pwgts;
switch (RType) {
case REFINE_AR:
ratio = ARATIO(dim, psurf[0], pvol[0]);
for (i=1; i<nparts; i++)
ratio += ARATIO(dim, psurf[i], pvol[i]);
break;
case REFINE_WAR:
ratio = 1.0*pwgts[0]*ARATIO(dim, psurf[0], pvol[0]);
for (i=1; i<nparts; i++)
ratio += 1.0*pwgts[i]*ARATIO(dim, psurf[i], pvol[i]);
break;
case REFINE_SCUT:
ratio = psurf[0];
for (i=1; i<nparts; i++)
ratio += psurf[i];
break;
case REFINE_MINMAXAVAR:
case REFINE_MINMAXAR:
case REFINE_MULTIOBJECTIVE:
case REFINE_MULTIOBJECTIVE2:
ratio = ARATIO(dim, psurf[0], pvol[0]);
for (i=1; i<nparts; i++) {
new = ARATIO(dim, psurf[i], pvol[i]);
if (new > ratio)
ratio = new;
}
break;
default:
errexit("Unknown RType of %d\n", ctrl->RType);
}
return(ratio);
}
/*************************************************************************
* This function computes the values of the RType functions for the grid
**************************************************************************/
void ComputeAllFunctions(CtrlType *ctrl, GraphType *graph)
{
realtype ratio;
ratio = ComputeFunction(1, ctrl, graph);
printf("\t RTYPE=1 %e\n",ratio);
ratio = ComputeFunction(2, ctrl, graph);
printf("\t RTYPE=2 %e\n",ratio);
ratio = ComputeFunction(3, ctrl, graph);
printf("\t RTYPE=3 %e\n",ratio);
ratio = ComputeFunction(4, ctrl, graph);
printf("\t RTYPE=4 %e\n",ratio);
ratio = ComputeFunction(5, ctrl, graph);
printf("\t RTYPE=5 %e\n",ratio);
}

View File

@ -1,85 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* setup.c
*
* This file contains setup functions for mgridgen
*
* George Irene
*/
#include "mgridgen.h"
/*************************************************************************
* This function sets up the graph from the user input
**************************************************************************/
void SetUpGraph(GraphType *graph, int nvtxs, idxtype *xadj, realtype *vvol,
realtype *vsurf, idxtype *adjncy, realtype *adjwgt)
{
int i, j;
graph->nvtxs = nvtxs;
graph->xadj = idxmalloc(nvtxs+1, "xadj");
graph->vwgt = idxsmalloc(nvtxs, 1, "vwgt");
graph->vvol = realmalloc(nvtxs, "vvol");
graph->vsurf = realmalloc(nvtxs, "vsurf");
graph->adjncy = idxmalloc(xadj[nvtxs], "adjncy");
graph->adjwgt = realmalloc(xadj[nvtxs], "adjwgt");
graph->adjwgtsum = realsmalloc(nvtxs, 0.0, "adjwgtsum");
graph->pwgts = NULL;
graph->pvol = NULL;
graph->psurf = NULL;
idxcopy(nvtxs+1, xadj, graph->xadj);
realcopy(nvtxs, vvol, graph->vvol);
realcopy(nvtxs, vsurf, graph->vsurf);
idxcopy(xadj[nvtxs], adjncy, graph->adjncy);
realcopy(xadj[nvtxs], adjwgt, graph->adjwgt);
for (i=0; i<nvtxs; i++)
for (j=xadj[i]; j<xadj[i+1]; j++)
graph->adjwgtsum[i] += adjwgt[j];
}
/*************************************************************************
* This function frees the memory that was allocated for the graph
**************************************************************************/
void FreeGraph(GraphType *graph)
{
IMfree(&graph->xadj, &graph->vwgt, &graph->vvol, &graph->vsurf,
&graph->adjncy, &graph->adjwgt, &graph->adjwgtsum, &graph->cmap,
&graph->where, &graph->pwgts, &graph->pvol, &graph->psurf, LTERM);
}
/*************************************************************************
* This function creates a CoarseGraphType data structure and initializes
* the various fields
**************************************************************************/
GraphType *CreateGraph(void)
{
GraphType *graph;
graph = (GraphType *)IMmalloc(sizeof(GraphType), "CreateGraph: graph");
graph->nvtxs = -1;
graph->nmoves = -1;
graph->xadj = NULL;
graph->vwgt = NULL;
graph->vvol = NULL;
graph->vsurf = NULL;
graph->adjncy = NULL;
graph->adjwgt = NULL;
graph->adjwgtsum = NULL;
graph->cmap = NULL;
graph->where = NULL;
graph->pwgts = NULL;
graph->pvol = NULL;
graph->psurf = NULL;
return graph;
}

View File

@ -1,57 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* struct.h
*
* This file contains data structures for the mgridgen routines.
*
* George Irene
*/
/*************************************************************************
* This data structure holds the input graph
**************************************************************************/
struct graphdef {
int nvtxs; /* The # of vertices in the graph */
idxtype *xadj; /* Pointers to the locally stored vertices */
idxtype *adjncy; /* Array that stores the adjacency lists of nvtxs */
idxtype *vwgt; /* Vertex weights */
realtype *vvol; /* The volume of the vertex */
realtype *vsurf; /* The surface of the vertex (applicable only to boundary elements) */
realtype *adjwgt; /* Array that stores the weights of the adjacency lists */
realtype *adjwgtsum; /* The sum of the adjacent weights (surace volume) */
idxtype *cmap; /* Used for coarsening */
idxtype *where; /* Partitioning vector */
idxtype *pwgts; /* The weight of the partitions */
int nmoves; /* The number of moves during refinement */
realtype *pvol; /* The volume of the partitions */
realtype *psurf; /* The surface area of the partitions */
realtype minratio; /* The value of the objective function */
struct graphdef *finer;
struct graphdef *coarser;
};
typedef struct graphdef GraphType;
/*************************************************************************
* The following structure stores information used by SHC
**************************************************************************/
struct controldef {
int dbglvl; /* Controls the debuging output of the program */
int CType; /* The type of coarsening */
int RType; /* The type of refinement */
int minsize; /* The bounds on the number of elements per partition */
int maxsize;
int nparts; /* The number of discovered partitions */
int dim; /* The number of dimensions for mesh 2D or 3D */
};
typedef struct controldef CtrlType;

View File

@ -1,16 +0,0 @@
include ../Makefile.in
default:
(cd IMlib ; $(make) )
(cd Lib ; $(make) )
(cd Programs ; $(make) )
clean:
(cd IMlib ; $(make) clean )
(cd Lib ; $(make) clean )
(cd Programs ; $(make) clean )
realclean:
(cd IMlib ; $(make) realclean )
(cd Lib ; $(make) realclean )
(cd Programs ; $(make) realclean )

View File

@ -1,56 +0,0 @@
include ../../Makefile.in
MGRIDLIB = ../../libmgrid.a
ifeq ($(ddmalloc),yes)
DEBUGFLAGS := $(DEBUGFLAGS) -DDMALLOC -DDEBUG
INCDIR := $(INCDIR) -I$(DMALLOCDIR)/include
LIBDIR := $(LIBDIR) -L$(DMALLOCDIR)/lib
LIBS := $(LIBS) -ldmalloc
OPTFLAGS = -g
endif
ifeq ($(dmalloc),yes)
DEBUGFLAGS := $(DEBUGFLAGS) -DDMALLOC
INCDIR := $(INCDIR) -I$(DMALLOCDIR)/include
LIBDIR := $(LIBDIR) -L$(DMALLOCDIR)/lib
LIBS := $(LIBS) -ldmalloc
endif
ifeq ($(debug),yes)
DEBUGFLAGS := $(DEBUGFLAGS) -DDEBUG
OPTFLAGS = -g
endif
INCLUDES = $(INCDIR) -I$(IMLIBDIR) -I../Lib
CFLAGS = $(COPTIONS) $(OPTFLAGS) $(DEBUGFLAGS) $(INCLUDES)
LD = $(CC) $(LDOPTIONS) $(LIBDIR)
MGRIDOBJS = mgridgen.o io.o
TRANSOBJS = transform.o io.o
EXTROBJS = extract.o io.o
.c.o:
$(CC) $(CFLAGS) -c $*.c
default: $(BINDIR)/mgridgen #$(BINDIR)/transform $(BINDIR)/extract
$(BINDIR)/mgridgen: $(MGRIDOBJS) $(MGRIDLIB)
$(LD) -o $@ $(MGRIDOBJS) $(LIBS)
chmod 744 $@
## $(BINDIR)/transform : $(TRANSOBJS) $(MGRIDLIB)
## $(LD) -o $@ $(TRANSOBJS) $(LIBS)
## $(BINDIR)/extract : $(EXTROBJS) $(MGRIDLIB)
## $(LD) -o $@ $(EXTROBJS) $(LIBS)
clean:
rm -f *.o
realclean:
rm -f *.o ;\
rm -f $(BINDIR)/mgridgen

View File

@ -1,198 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* extract.c
*
* This file is the driver routine for extracting the graph
* for each of the fused elements I used these graphs to call onmetis
*
* Irene
*/
#include "mgridgen.h"
void WriteGraph(int, idxtype *, idxtype *, idxtype, realtype, int, int);
void ExtractGraph(int, idxtype *, idxtype *, idxtype *, realtype *, realtype *,
realtype *, int, idxtype *);
/*************************************************************************
* Let the game begin
**************************************************************************/
int main(int argc, char *argv[])
{
int nvtxs, nedges;
int options[10], nmoves, nparts, minsize, maxsize;
idxtype *part;
idxtype *xadj, *adjncy, *vwgt;
realtype *vvol, *vsurf, *adjwgt;
GraphType graph;
char filename[256];
double tmr;
if (argc != 8) {
printf("Usage: %s <GraphFile> <Dim> <CType> <RType> <minsize> <maxsize> <dbglvl>\n", argv[0]);
printf("Where:\n");
printf("\tDim: \t2 -> 2-D Mesh\n");
printf("\t \t3 -> 3-D Mesh\n");
printf("\tCType: \t1 -> Random\n");
printf("\t \t2 -> HEM\n");
printf("\t \t3 -> Slow HEM\n");
printf("\t \t4 -> Slow Heaviest\n");
printf("\tRType: \t1 -> Aspect Ratio refinement\n");
printf("\t \t2 -> Weighted Aspect Ratio refinement\n");
printf("\t \t3 -> Surface cut refinement\n");
printf("\t \t4 -> Minimum Aspect Ratio & Average refinement\n");
printf("\t \t5 -> Minimum Aspect Ratio refinement\n");
printf("\t \t6 -> 4+2 Minimum & Weighted Aspect Ratio refinement\n");
printf("\tminsize:\tA lower bound on the cell size (suggested)\n");
printf("\tmaxsize:\tAn upper bound on the cell size (strict)\n");
printf("--------------------------------------------------------------------\n");
printf("Recomended usage: %s <GraphFile> <Dim> 4 6 ? ? 32\n", argv[0]);
printf("--------------------------------------------------------------------\n");
exit(0);
}
strcpy(filename, argv[1]);
options[OPTION_DIM] = atoi(argv[2]);
options[OPTION_CTYPE] = atoi(argv[3]);
options[OPTION_RTYPE] = atoi(argv[4]);
minsize = atoi(argv[5]);
maxsize = atoi(argv[6]);
options[OPTION_DBGLVL] = atoi(argv[7]);
ReadGraph(&graph, filename);
printf("Parameters: %s, Dim=%d [%2d %2d] CType=%d RType=%d Nvtxs=%d Nedges=%d\n", filename,
options[OPTION_DIM], minsize, maxsize, options[OPTION_CTYPE], options[OPTION_RTYPE],
graph.nvtxs, graph.xadj[graph.nvtxs]);
/* Keep graph info */
nvtxs = graph.nvtxs;
nedges = graph.xadj[nvtxs];
part = imalloc(nvtxs, "main: part");
xadj = imalloc(nvtxs+1, "main: xadj");
adjncy = imalloc(nedges, "main: adjncy");
vwgt = imalloc(nvtxs, "main: vwgt");
vvol = fmalloc(nvtxs, "main:vvol");
vsurf = fmalloc(nvtxs, "main:vsurf");
adjwgt = fmalloc(nedges, "main:adjwgt");
icopy(nvtxs+1, graph.xadj, xadj);
icopy(nedges, graph.adjncy, adjncy);
iset(nvtxs, 1, vwgt);
fcopy(nvtxs, graph.vvol, vvol);
fcopy(nvtxs, graph.vsurf, vsurf);
fcopy(nedges, graph.adjwgt, adjwgt);
cleartimer(tmr);
starttimer(tmr);
MGridGen(graph.nvtxs, graph.xadj, graph.vvol, graph.vsurf, graph.adjncy, graph.adjwgt,
minsize, maxsize, options, &nmoves, &nparts, part);
stoptimer(tmr);
printf("Total Time: %lf\n", gettimer(tmr));
WritePartition("partitions", part, graph.nvtxs, nparts);
ExtractGraph(nvtxs, xadj, adjncy, vwgt, vvol, vsurf, adjwgt, nparts, part);
IMfree(&graph.xadj, &graph.vvol, &graph.vsurf, &graph.adjncy, &graph.adjwgt, &part, LTERM);
return(0);
}
/***************************************************************************/
void ExtractGraph(int nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt,
realtype *vvol, realtype *vsurf, realtype *adjwgt,
int nparts, idxtype *part)
{
int i, j, k, l, last, ipart;
int nfvtxs, nedges;
idxtype *map, *fxadj, *fadjncy;
idxtype *ptr, *ind, *pwgts;
realtype aratio;
realtype *pvol, *psurf;
/* Create a part-to-vertex mapping; compute pwgts, psurf, pvol */
ptr = ismalloc(nparts+1, 0, "ExtractGraph: ptr");
ind = imalloc(nvtxs, "ExtractGraph: ind");
pwgts = ismalloc(nparts, 0, "ExtractGraph: pwgts");
pvol = fsmalloc(nparts, 0.0, "ExtractGraph: pvol");
psurf = fsmalloc(nparts, 0.0, "ExtractGraph: psurf");
for (i=0; i<nvtxs; i++) {
ipart = part[i];
ptr[ipart]++;
pwgts[ipart] += vwgt[i];
pvol[ipart] += vvol[i];
psurf[ipart] += vsurf[i];
for (j=xadj[i]; j<xadj[i+1]; j++) {
if (part[adjncy[j]] != ipart)
psurf[ipart] += adjwgt[j];
}
}
nfvtxs = iamax(nparts, ptr);
nfvtxs = ptr[nfvtxs];
nedges = xadj[nvtxs];
MAKECSR(i, nparts, ptr);
for (i=0; i<nvtxs; i++) {
ipart = part[i];
ind[ptr[ipart]] = i;
ptr[ipart]++;
}
for (ipart=nparts; ipart>0; ipart--)
ptr[ipart] = ptr[ipart-1];
ptr[0] = 0;
/* Create the connectivity graph for each of the fused elements */
fxadj = ismalloc(nfvtxs+1, 0, "FusedElementGraph: fxadj");
fadjncy = imalloc(nedges, "FusedElementGraph: fadjncy");
map = ismalloc(nvtxs, -1, "FusedElementGraph: map");
for (ipart=0; ipart<nparts; ipart++) {
for (nfvtxs=0, l=ptr[ipart]; l<ptr[ipart+1]; l++, nfvtxs++)
map[ind[l]] = nfvtxs;
for (fxadj[0]=last=0, l=ptr[ipart]; l<ptr[ipart+1]; l++) {
i = ind[l];
for (j=xadj[i]; j<xadj[i+1]; j++) {
k=adjncy[j];
if (part[k] == ipart && k != i )
fadjncy[last++] = map[k];
}
fxadj[l+1-ptr[ipart]] = last;
}
aratio = ARATIO(3, psurf[ipart], pvol[ipart]);
WriteGraph(nfvtxs, fxadj, fadjncy, pwgts[ipart], aratio, nparts, ipart);
iset(nvtxs, -1, map);
}
IMfree(ptr, ind, fxadj, fadjncy, map, LTERM);
}
void WriteGraph(int nvtxs, idxtype *xadj, idxtype *adjncy, idxtype pwgts,
realtype aratio, int nparts, int mypart)
{
int i, j;
char filename[20];
FILE *fp;
sprintf(filename,"test.graph%d.%d",nparts,mypart);
fp = fopen(filename, "w");
fprintf(fp, "%d %d", nvtxs, xadj[nvtxs]/2);
for (i=0; i<nvtxs; i++) {
fprintf(fp, "\n");
for (j=xadj[i]; j<xadj[i+1]; j++)
fprintf(fp, " %d", adjncy[j]+1);
}
fprintf(fp, "\n pwgts=%d aratio=%f\n", pwgts, aratio);
fclose(fp);
}

View File

@ -1,186 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* io.c
*
* This file contains routines related to I/O
*
* George Irene
*/
#include "mgridgen.h"
/*************************************************************************
* This function reads the spd matrix
**************************************************************************/
void ReadGraph(GraphType *graph, char *filename)
{
int i, k, nvtxs, nedges;
idxtype *xadj, *adjncy;
realtype *vvol, *vsurf, *adjwgt;
char line[MAXLINE+1], delim[] = " \t", *token;
FILE *fpin;
if ((fpin = fopen(filename, "r")) == NULL) {
printf("Failed to open file %s\n", filename);
exit(0);
}
do {
fgets(line, MAXLINE, fpin);
} while (line[0] == '%' && !feof(fpin));
if (feof(fpin)) {
graph->nvtxs = 0;
return;
}
sscanf(line, "%d %d", &nvtxs, &nedges);
nedges *= 2;
graph->nvtxs = nvtxs;
xadj = graph->xadj = idxsmalloc(nvtxs+1, 0, "ReadGraph: xadj");
vvol = graph->vvol = realmalloc(nvtxs, "ReadGraph: vvol");
vsurf = graph->vsurf = realsmalloc(nvtxs, 0.0, "ReadGraph: vsurf");
adjncy = graph->adjncy = idxmalloc(nedges+1, "ReadGraph: adjncy");
adjwgt = graph->adjwgt = realmalloc(nedges+1, "ReadGraph: adjwgt");
/* Start reading the graph file */
for (xadj[0]=0, k=0, i=0; i<nvtxs; i++) {
do {
fgets(line, MAXLINE, fpin);
} while (line[0] == '%' && !feof(fpin));
if (strlen(line) == MAXLINE)
errexit("\nBuffer for fgets not big enough!\n");
/* Parse the string and get the arguments */
token = strtok(line, delim);
vvol[i] = atof(token);
while ((token = strtok(NULL, delim))) {
adjncy[k] = atoi(token) - 1;
if (adjncy[k] == i)
vsurf[i] = atof(strtok(NULL, delim));
else
adjwgt[k++] = atof(strtok(NULL, delim));
}
xadj[i+1] = k;
}
fclose(fpin);
if (k != nedges)
errexit("ReadGraph: Something wrong with the edges from input file %d %d",
nedges, k);
}
/*************************************************************************
* Reads a matrix in mgridgen format and transforms it to a metis format
**************************************************************************/
void TransformGraph(char *filename)
{
int i, length, nvtxs, nedges;
idxtype adjncy;
realtype vvol, vsurf, adjwgt;
char line[MAXLINE+1], delim[] = " \t", *token;
char *tfilename;
FILE *fpin, *fpin2;
length = strlen(filename);
tfilename = (char *)malloc ((length +5) * sizeof(char));
strcpy(tfilename, filename);
strcat(tfilename, ".FORMETIS");
if ((fpin = fopen(filename, "r")) == NULL) {
printf("Failed to open file %s\n", filename);
exit(0);
}
if ((fpin2 = fopen(tfilename, "w")) == NULL) {
printf("Failed to open file %s\n", tfilename);
exit(0);
}
do {
fgets(line, MAXLINE, fpin);
} while (line[0] == '%' && !feof(fpin));
if (feof(fpin))
return;
sscanf(line, "%d %d", &nvtxs, &nedges);
fprintf(fpin2, "%d %d\n", nvtxs, nedges);
/* Start reading the graph file */
for (i=0; i<nvtxs; i++) {
do {
fgets(line, MAXLINE, fpin);
} while (line[0] == '%' && !feof(fpin));
if (strlen(line) == MAXLINE)
errexit("\nBuffer for fgets not big enough!\n");
/* Parse the string and get the arguments */
token = strtok(line, delim);
vvol = atof(token);
while ((token = strtok(NULL, delim))) {
adjncy = atoi(token);
if (adjncy == i+1)
vsurf = atof(strtok(NULL, delim));
else {
fprintf(fpin2, "%d ", adjncy);
adjwgt = atof(strtok(NULL, delim));
}
}
fprintf(fpin2, "\n");
}
fclose(fpin);
fclose(fpin2);
}
/*************************************************************************
* This function writes out the partition vector
**************************************************************************/
void WritePartition(char *fname, idxtype *part, int n, int nparts)
{
int i;
char filename[256];
FILE *fpout;
sprintf(filename,"%s.part.%d",fname, nparts);
if ((fpout = fopen(filename, "w")) == NULL)
errexit("Problems in opening the partition file: %s", filename);
for (i=0; i<n; i++)
fprintf(fpout,"%d\n",part[i]);
fclose(fpout);
}
/*************************************************************************
* This function prints out the graph
**************************************************************************/
void PrintGraph(GraphType *graph)
{
int i, j, nvtxs;
idxtype *xadj, *adjncy;
realtype *adjwgt;
nvtxs = graph->nvtxs;
xadj = graph->xadj;
adjncy = graph->adjncy;
adjwgt = graph->adjwgt;
for (i=0; i<nvtxs; i++) {
printf("%e %e ", graph->vvol[i], graph->vsurf[i]);
for (j=xadj[i]; j<xadj[i+1]; j++)
printf("%d %3f ", adjncy[j]+1, adjwgt[j]);
printf("\n");
}
}

View File

@ -1,78 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* mgridgen.c
*
* This file contains the driving routine for MGRIDGEN
*
* George Irene
*/
#include "mgridgen.h"
/*************************************************************************
* Let the game begin
**************************************************************************/
int main(int argc, char *argv[])
{
int options[10], nmoves, nparts, minsize, maxsize;
idxtype *part;
GraphType graph;
char filename[256];
double tmr;
if (argc != 8) {
printf("Usage: %s <GraphFile> <Dim> <CType> <RType> <minsize> <maxsize> <dbglvl>\n", argv[0]);
printf("Where:\n");
printf("\tDim: \t2 -> 2-D Mesh\n");
printf("\t \t3 -> 3-D Mesh\n");
printf("\tCType: \t1 -> Random\n");
printf("\t \t2 -> HEM\n");
printf("\t \t3 -> Slow HEM\n");
printf("\t \t4 -> Slow Heaviest\n");
printf("\tRType: \t1 -> Aspect Ratio refinement\n");
printf("\t \t2 -> Weighted Aspect Ratio refinement\n");
printf("\t \t3 -> Surface cut refinement\n");
printf("\t \t4 -> Minimum Aspect Ratio & Average refinement\n");
printf("\t \t5 -> Minimum Aspect Ratio refinement\n");
printf("\t \t6 -> 4+2 Minimum & Weighted Aspect Ratio refinement\n");
printf("\t \t7 -> 5+2 Minimum & Weighted Aspect Ratio refinement\n");
printf("\tminsize:\tA lower bound on the cell size (suggested)\n");
printf("\tmaxsize:\tAn upper bound on the cell size (strict)\n");
printf("--------------------------------------------------------------------\n");
printf("Recomended usage: %s <GraphFile> <Dim> 4 6 ? ? 128\n", argv[0]);
printf("--------------------------------------------------------------------\n");
exit(0);
}
strcpy(filename, argv[1]);
options[OPTION_DIM] = atoi(argv[2]);
options[OPTION_CTYPE] = atoi(argv[3]);
options[OPTION_RTYPE] = atoi(argv[4]);
minsize = atoi(argv[5]);
maxsize = atoi(argv[6]);
options[OPTION_DBGLVL] = atoi(argv[7]);
ReadGraph(&graph, filename);
printf("------------------------ PARAMETERS --------------------------------------\n");
printf("%s, Dim=%d [%2d %2d] CType=%d RType=%d Nvtxs=%d Nedges=%d\n", filename,
options[OPTION_DIM], minsize, maxsize, options[OPTION_CTYPE], options[OPTION_RTYPE],
graph.nvtxs, graph.xadj[graph.nvtxs]);
part = idxmalloc(graph.nvtxs, "main: part");
cleartimer(tmr);
starttimer(tmr);
MGridGen(graph.nvtxs, graph.xadj, graph.vvol, graph.vsurf, graph.adjncy, graph.adjwgt,
minsize, maxsize, options, &nmoves, &nparts, part);
stoptimer(tmr);
printf("Total Time: %lf\n", gettimer(tmr));
WritePartition(filename, part, graph.nvtxs, nparts);
IMfree(&graph.xadj, &graph.vvol, &graph.vsurf, &graph.adjncy, &graph.adjwgt, &part, LTERM);
return(0);
}

View File

@ -1,34 +0,0 @@
/* To process the output files of mgridgen and onmetis */
#include <stdio.h>
#include <stdlib.h>
int MAXLINE = 100;
int main(int argc, char *argv[])
{
char line1[MAXLINE+1], line2[MAXLINE+1], line[MAXLINE+MAXLINE+2];
FILE *fpin1, *fpin2, *fpout;
fpin1 = fopen(argv[1], "r");
fpin2 = fopen(argv[2], "r");
fpout = fopen(argv[3], "w");
printf("%s %s %s\n", argv[1], argv[2], argv[3]);
do {
fgets(line1, MAXLINE, fpin1);
fgets(line2, MAXLINE, fpin2);
strcpy(line, line1);
line[strlen(line1)-1]=' ';
strcat(line, line2);
fputs(line, fpout);
} while (line1 != NULL);
fclose(fpin1);
fclose(fpin2);
fclose(fpout);
return(0);
}

View File

@ -1,32 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* transform.c
*
* This file is the driver for Transform
*
* Started 4/14/99
* George
*
*/
/*************************************************************************
* Let the game begin
**************************************************************************/
int main(int argc, char *argv[])
{
char filename[256];
if (argc != 2) {
printf("Usage: %s <GraphFile>\n", argv[0]);
exit(0);
}
strcpy(filename, argv[1]);
TransformGraph(filename);
printf("Parameters: %s\n", filename);
return(0);
}

View File

@ -1,16 +0,0 @@
default:
(cd MGridGen ; make)
serial:
(cd MGridGen ; make)
parallel:
(cd MGridGen ; make)
(cd ParMGridGen ; make)
clean:
(cd MGridGen ; make clean)
(cd ParMGridGen ; make clean )
realclean:
(cd MGridGen ; make realclean )
(cd ParMGridGen ; make realclean )

View File

@ -1,64 +0,0 @@
#--------------------------------------------------------------------------
# Which make to use
make = gmake
# Which compiler to use
# CC is the compiler for the serial code
# PARCC is the compiter for the parallel code
CC = cc
PARCC = cc
# What optimization level to use
OPTFLAGS = -O3
# What options to be used by the compiler
COPTIONS =
# Which loader to use
LD = cc
PARLD = cc
# What options to be used by the loader
LDOPTIONS = -O3
# Where to put the executable
BINDIR = ../..
# Additional libraries
DMALLOCDIR = /usr/local
IMLIBDIR = ../../MGridGen/IMlib
# Include directories for the compiler
INCDIR =
# In which directories to look for any additional libraries
LIBDIR = -L../.. \
-L/usr/lib32/
# Set some flags
DEBUGFLAGS =
# What additional libraries to link the programs with (eg., -lmpi)
LIBS = -lmgrid -lm
PARLIBS = -lparmgrid -lmgrid -lmpi -lm
# What archiving to use
AR = ar rv
# What to use for indexing the archive
#RANLIB = ranlib
RANLIB = ar -ts
#--------------------------------------------------------------------------
#
# Do not change any of the following
#
VERNUM = 1.0
#*************************************************************************
# Compilation flags
#*************************************************************************
ddmalloc = no
dmalloc = no
debug = no

View File

@ -1,11 +0,0 @@
include ../../Makefile.in
default:
(cd ParMETISLib ; $(make) )
clean:
(cd ParMETISLib ; $(make) clean )
realclean:
(cd ParMETISLib ; $(make) realclean )

View File

@ -1,18 +0,0 @@
coarsen.c
comm.c
debug.c
diffuse.c
drivers.c
edge_refine.c
fused.c
grsetup.c
iidxsort.c
ikeysort.c
memory.c
remap.c
setup.c
timer.c
util.c
var.c
LIB = $(FOAM_LIBBIN)/libParMETISLib

View File

@ -1,9 +0,0 @@
TYPE_REAL=
#if WM_PRECISION_OPTION==SP
TYPE_REAL=TYPE_REAL
#endif
include $(RULES)/mplib$(WM_MPLIB)
EXE_INC = $(PFLAGS) $(PINC) -D$(TYPE_REAL)
LIB_LIBS = $(PLIBS)

View File

@ -1,41 +0,0 @@
include ../../../Makefile.in
INCLUDES = $(INCDIR) -I./
DEBUGFLAGS =
ifeq ($(ddmalloc),yes)
INCLUDES := $(INCLUDES) -I$(DMALLOCDIR)/include
DEBUGFLAGS := $(DEBUGFLAGS) -DDMALLOC -DDEBUG
OPTFLAGS = -g
endif
ifeq ($(dmalloc),yes)
INCLUDES := $(INCLUDES) -I$(DMALLOCDIR)/include
DEBUGFLAGS := $(DEBUGFLAGS) -DDMALLOC
endif
ifeq ($(debug),yes)
DEBUGFLAGS := $(DEBUGFLAGS) -DDEBUG
OPTFLAGS = -g
endif
CFLAGS = $(COPTIONS) $(OPTFLAGS) $(DEBUGFLAGS) $(INCLUDES)
OBJS = fused.o comm.o util.o memory.o debug.o setup.o diffuse.o grsetup.o timer.o \
coarsen.o edge_refine.o drivers.o remap.o iidxsort.o ikeysort.o var.o
.c.o:
$(PARCC) $(CFLAGS) -c $*.c
../libIMparmetis.a: $(OBJS)
$(AR) $@ $(OBJS)
$(RANLIB) $@
clean:
rm -f *.o
realclean:
rm -f *.o ; rm -f ../libIMparmetis.a

View File

@ -1,309 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* coarsen.c
*
* This file contains code that finds a matching and performs the coarsening
*
* George Irene
*/
#include "parmetis.h"
/*************************************************************************
* This function finds a HEM matching between local vertices only
**************************************************************************/
void LocalMatch_HEM(CtrlType *ctrl, GraphType *graph, WorkSpaceType *wspace)
{
int i, ii, j, k, nvtxs, cnvtxs, firstvtx, maxi;
idxtype *xadj, *ladjncy, *vtxdist;
idxtype *perm, *match;
realtype *adjwgt;
graph->match_type = MATCH_LOCAL;
IFSET(ctrl->dbglvl, DBG_TIME, MPI_Barrier(ctrl->comm));
IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->MatchTmr));
nvtxs = graph->nvtxs;
xadj = graph->xadj;
ladjncy = graph->adjncy;
adjwgt = graph->adjwgt;
vtxdist = graph->vtxdist;
firstvtx = vtxdist[ctrl->mype];
match = graph->match = idxmalloc(nvtxs+graph->nrecv, "HEM_Match: match");
idxset(nvtxs, UNMATCHED, match);
idxset(graph->nrecv, 0, match+nvtxs); /* Easy way to handle remote vertices */
/*************************************************************
* Go now and find a local matching
*************************************************************/
perm = wspace->indices;
FastRandomPermute(nvtxs, perm, 1);
cnvtxs = 0;
for (ii=0; ii<nvtxs; ii++) {
i = perm[ii];
if (match[i] == UNMATCHED) { /* Unmatched */
maxi = -1;
/* Find a heavy-edge matching, if the weight of the vertex is OK */
if (graph->vwgt[i] < graph->maxvwgt) {
for (j=xadj[i]; j<xadj[i+1]; j++) {
if (match[ladjncy[j]] == UNMATCHED && graph->vwgt[ladjncy[j]] <= graph->maxvwgt &&
(maxi == -1 || adjwgt[maxi] < adjwgt[j]))
maxi = j;
}
}
if (maxi != -1) {
k = ladjncy[maxi];
if (i <= k) {
match[i] = firstvtx+k + KEEP_BIT;
match[k] = firstvtx+i;
}
else {
match[i] = firstvtx+k;
match[k] = firstvtx+i + KEEP_BIT;
}
}
else {
match[i] = (firstvtx+i) + KEEP_BIT;
}
cnvtxs++;
}
}
CommInterfaceData(ctrl, graph, match, wspace->indices, match+nvtxs);
#ifdef DEBUG_MATCH
PrintVector2(ctrl, nvtxs, firstvtx, match, "Match1");
#endif
if (ctrl->dbglvl&DBG_MATCHINFO) {
PrintVector2(ctrl, nvtxs, firstvtx, match, "Match");
myprintf(ctrl, "Cnvtxs: %d\n", cnvtxs);
rprintf(ctrl, "Done with matching...\n");
}
IFSET(ctrl->dbglvl, DBG_TIME, MPI_Barrier(ctrl->comm));
IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->MatchTmr));
IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->ContractTmr));
Local_CreateCoarseGraph(ctrl, graph, wspace, cnvtxs);
IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->ContractTmr));
}
/*************************************************************************
* This function creates the coarser graph
**************************************************************************/
void Local_CreateCoarseGraph(CtrlType *ctrl, GraphType *graph, WorkSpaceType *wspace, int cnvtxs)
{
int i, j, k, l, nvtxs, nedges, firstvtx, cfirstvtx;
int npes=ctrl->npes, mype=ctrl->mype;
int cnedges, v, u;
idxtype *xadj, *vwgt, *vsize, *ladjncy, *vtxdist, *where;
idxtype *match, *cmap;
idxtype *cxadj, *cvwgt, *cvsize, *cadjncy, *cvtxdist, *cwhere;
realtype *adjwgt;
realtype *cadjwgt;
GraphType *cgraph;
int mask=(1<<13)-1, htable[8192], htableidx[8192];
nvtxs = graph->nvtxs;
vtxdist = graph->vtxdist;
xadj = graph->xadj;
vwgt = graph->vwgt;
vsize = graph->vsize;
ladjncy = graph->adjncy;
adjwgt = graph->adjwgt;
where = graph->where;
match = graph->match;
firstvtx = vtxdist[mype];
cmap = graph->cmap = idxmalloc(nvtxs+graph->nrecv, "CreateCoarseGraph: cmap");
/* Initialize the coarser graph */
cgraph = CreateGraph();
cgraph->nvtxs = cnvtxs;
cgraph->maxvwgt = graph->maxvwgt;
cgraph->level = graph->level+1;
cgraph->finer = graph;
graph->coarser = cgraph;
/*************************************************************
* Obtain the vtxdist of the coarser graph
**************************************************************/
cvtxdist = cgraph->vtxdist = idxmalloc(npes+1, "CreateCoarseGraph: cvtxdist");
cvtxdist[npes] = cnvtxs; /* Use last position in the cvtxdist as a temp buffer */
MPI_Allgather((void *)(cvtxdist+npes), 1, IDX_DATATYPE, (void *)cvtxdist, 1, IDX_DATATYPE, ctrl->comm);
MAKECSR(i, npes, cvtxdist);
cgraph->gnvtxs = cvtxdist[npes];
#ifdef DEBUG_CONTRACT
PrintVector(ctrl, npes+1, 0, cvtxdist, "cvtxdist");
#endif
/*************************************************************
* Construct the cmap vector
**************************************************************/
cfirstvtx = cvtxdist[mype];
/* Create the cmap of what you know so far locally */
cnvtxs = 0;
for (i=0; i<nvtxs; i++) {
if (match[i] >= KEEP_BIT) {
k = match[i] - KEEP_BIT;
if (k<firstvtx+i)
continue; /* i has been matched via the (k,i) side */
cmap[i] = cfirstvtx + cnvtxs++;
if (k != firstvtx+i) {
cmap[k-firstvtx] = cmap[i];
match[k-firstvtx] += KEEP_BIT; /* Add the KEEP_BIT to simplify coding */
}
}
}
CommInterfaceData(ctrl, graph, cmap, wspace->indices, cmap+nvtxs);
#ifdef DEBUG_CONTRACT
PrintVector(ctrl, nvtxs, firstvtx, cmap, "Cmap");
#endif
/*************************************************************
* Finally, create the coarser graph
**************************************************************/
/* Allocate memory for the coarser graph, and fire up coarsening */
cxadj = cgraph->xadj = idxmalloc(cnvtxs+1, "CreateCoarserGraph: cxadj");
cvwgt = cgraph->vwgt = idxmalloc(cnvtxs, "CreateCoarserGraph: cvwgt");
if (vsize != NULL)
cvsize = cgraph->vsize = idxmalloc(cnvtxs, "CreateCoarserGraph: cvsize");
if (where != NULL)
cwhere = cgraph->where = idxmalloc(cnvtxs, "CreateCoarserGraph: cwhere");
cadjncy = idxmalloc(graph->nedges, "CreateCoarserGraph: cadjncy");
cadjwgt = realmalloc(graph->nedges, "CreateCoarserGraph: cadjwgt");
iset(8192, -1, htable);
cxadj[0] = cnvtxs = cnedges = 0;
for (i=0; i<nvtxs; i++) {
v = firstvtx+i;
u = match[i]-KEEP_BIT;
if (v > u)
continue; /* I have already collapsed it as (u,v) */
/* Collapse the v vertex first, which you know that is local */
cvwgt[cnvtxs] = vwgt[i];
if (vsize != NULL)
cvsize[cnvtxs] = vsize[i];
if (where != NULL)
cwhere[cnvtxs] = where[i];
nedges = 0;
for (j=xadj[i]; j<xadj[i+1]; j++) {
k = cmap[ladjncy[j]];
if (k != cfirstvtx+cnvtxs) { /* If this is not an internal edge */
l = k&mask;
if (htable[l] == -1) { /* Seeing this for first time */
htable[l] = k;
htableidx[l] = cnedges+nedges;
cadjncy[cnedges+nedges] = k;
cadjwgt[cnedges+nedges++] = adjwgt[j];
}
else if (htable[l] == k) {
cadjwgt[htableidx[l]] += adjwgt[j];
}
else { /* Now you have to go and do a search. Expensive case */
for (l=0; l<nedges; l++) {
if (cadjncy[cnedges+l] == k)
break;
}
if (l < nedges) {
cadjwgt[cnedges+l] += adjwgt[j];
}
else {
cadjncy[cnedges+nedges] = k;
cadjwgt[cnedges+nedges++] = adjwgt[j];
}
}
}
}
/* Collapse the u vertex next */
if (v != u) {
u -= firstvtx;
cvwgt[cnvtxs] += vwgt[u];
if (vsize != NULL)
cvsize[cnvtxs] += vsize[u];
if (where != NULL && cwhere[cnvtxs] != where[u])
myprintf(ctrl, "Something went wrong with the where local matching! %d %d\n", cwhere[cnvtxs], where[u]);
for (j=xadj[u]; j<xadj[u+1]; j++) {
k = cmap[ladjncy[j]];
if (k != cfirstvtx+cnvtxs) { /* If this is not an internal edge */
l = k&mask;
if (htable[l] == -1) { /* Seeing this for first time */
htable[l] = k;
htableidx[l] = cnedges+nedges;
cadjncy[cnedges+nedges] = k;
cadjwgt[cnedges+nedges++] = adjwgt[j];
}
else if (htable[l] == k) {
cadjwgt[htableidx[l]] += adjwgt[j];
}
else { /* Now you have to go and do a search. Expensive case */
for (l=0; l<nedges; l++) {
if (cadjncy[cnedges+l] == k)
break;
}
if (l < nedges) {
cadjwgt[cnedges+l] += adjwgt[j];
}
else {
cadjncy[cnedges+nedges] = k;
cadjwgt[cnedges+nedges++] = adjwgt[j];
}
}
}
}
}
cnedges += nedges;
for (j=cxadj[cnvtxs]; j<cnedges; j++)
htable[cadjncy[j]&mask] = -1; /* reset the htable */
cxadj[++cnvtxs] = cnedges;
}
cgraph->nedges = cnedges;
cgraph->adjncy = idxmalloc(cnedges, "CreateCoarserGraph: cadjncy");
cgraph->adjwgt = realmalloc(cnedges, "CreateCoarserGraph: cadjwgt");
idxcopy(cnedges, cadjncy, cgraph->adjncy);
realcopy(cnedges, cadjwgt, cgraph->adjwgt);
IMfree(&cadjncy, &cadjwgt, &graph->where, LTERM); /* Note that graph->where works fine even if it is NULL */
}

View File

@ -1,179 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* comm.c
*
* This function provides various high level communication functions
*
* George Irene
*/
#include "parmetis.h"
/*************************************************************************
* This function performs the gather/scatter for the boundary vertices
**************************************************************************/
void CommInterfaceData(CtrlType *ctrl, GraphType *graph, idxtype *data,
idxtype *sendvector, idxtype *recvvector)
{
int i, k, nnbrs, firstvtx;
idxtype *peind, *sendptr, *sendind, *recvptr;
firstvtx = graph->vtxdist[ctrl->mype];
nnbrs = graph->nnbrs;
peind = graph->peind;
sendptr = graph->sendptr;
sendind = graph->sendind;
recvptr = graph->recvptr;
/* Issue the receives first */
for (i=0; i<nnbrs; i++) {
MPI_Irecv((void *)(recvvector+recvptr[i]), recvptr[i+1]-recvptr[i], IDX_DATATYPE,
peind[i], 1, ctrl->comm, ctrl->rreq+i);
}
/* Issue the sends next */
k = sendptr[nnbrs];
for (i=0; i<k; i++)
sendvector[i] = data[sendind[i]-firstvtx];
for (i=0; i<nnbrs; i++) {
MPI_Isend((void *)(sendvector+sendptr[i]), sendptr[i+1]-sendptr[i], IDX_DATATYPE,
peind[i], 1, ctrl->comm, ctrl->sreq+i);
}
/* OK, now get into the loop waiting for the operations to finish */
MPI_Waitall(nnbrs, ctrl->rreq, ctrl->statuses);
MPI_Waitall(nnbrs, ctrl->sreq, ctrl->statuses);
}
/*************************************************************************
* This function performs the gather/scatter for the boundary vertices
**************************************************************************/
void CommChangedInterfaceData(CtrlType *ctrl, GraphType *graph,
int nchanged, idxtype *changed, idxtype *data,
KeyValueType *sendpairs, KeyValueType *recvpairs, idxtype *psendptr)
{
int i, j, k, n, penum, nnbrs;
idxtype *peind, *sendptr, *recvptr, *pexadj, *peadjncy, *peadjloc;
KeyValueType *pairs;
nnbrs = graph->nnbrs;
peind = graph->peind;
sendptr = graph->sendptr;
recvptr = graph->recvptr;
pexadj = graph->pexadj;
peadjncy = graph->peadjncy;
peadjloc = graph->peadjloc;
/* Issue the receives first */
for (i=0; i<nnbrs; i++) {
MPI_Irecv((void *)(recvpairs+recvptr[i]), 2*(recvptr[i+1]-recvptr[i]), IDX_DATATYPE,
peind[i], 1, ctrl->comm, ctrl->rreq+i);
}
if (nchanged != 0) {
idxcopy(ctrl->npes, sendptr, psendptr);
/* Copy the changed values into the sendvector */
for (i=0; i<nchanged; i++) {
j = changed[i];
for (k=pexadj[j]; k<pexadj[j+1]; k++) {
penum = peadjncy[k];
sendpairs[psendptr[penum]].key = peadjloc[k];
sendpairs[psendptr[penum]].val = data[j];
psendptr[penum]++;
}
}
for (i=0; i<nnbrs; i++) {
MPI_Isend((void *)(sendpairs+sendptr[i]), 2*(psendptr[i]-sendptr[i]), IDX_DATATYPE,
peind[i], 1, ctrl->comm, ctrl->sreq+i);
}
}
else {
for (i=0; i<nnbrs; i++)
MPI_Isend((void *)(sendpairs), 0, IDX_DATATYPE, peind[i], 1, ctrl->comm, ctrl->sreq+i);
}
/* OK, now get into the loop waiting for the operations to finish */
for (i=0; i<nnbrs; i++) {
MPI_Wait(ctrl->rreq+i, &(ctrl->status));
MPI_Get_count(&ctrl->status, IDX_DATATYPE, &n);
if (n != 0) {
n = n/2;
pairs = recvpairs+graph->recvptr[i];
for (k=0; k<n; k++)
data[pairs[k].key] = pairs[k].val;
}
}
MPI_Waitall(nnbrs, ctrl->sreq, ctrl->statuses);
}
/*************************************************************************
* This function computes the max of a single element
**************************************************************************/
int GlobalSEMax(CtrlType *ctrl, int value)
{
int max;
MPI_Allreduce((void *)&value, (void *)&max, 1, MPI_INT, MPI_MAX, ctrl->comm);
return max;
}
/*************************************************************************
* This function computes the max of a single element
**************************************************************************/
double GlobalSEMaxDouble(CtrlType *ctrl, double value)
{
double max;
MPI_Allreduce((void *)&value, (void *)&max, 1, MPI_DOUBLE, MPI_MAX, ctrl->comm);
return max;
}
/*************************************************************************
* This function computes the max of a single element
**************************************************************************/
int GlobalSEMin(CtrlType *ctrl, int value)
{
int min;
MPI_Allreduce((void *)&value, (void *)&min, 1, MPI_INT, MPI_MIN, ctrl->comm);
return min;
}
/*************************************************************************
* This function computes the max of a single element
**************************************************************************/
int GlobalSESum(CtrlType *ctrl, int value)
{
int sum;
MPI_Allreduce((void *)&value, (void *)&sum, 1, MPI_INT, MPI_SUM, ctrl->comm);
return sum;
}
/*************************************************************************
* This function computes the max of a single element
**************************************************************************/
realtype GlobalSESumReal(CtrlType *ctrl, realtype value)
{
realtype sum;
MPI_Allreduce((void *)&value, (void *)&sum, 1, REAL_DATATYPE, MPI_SUM, ctrl->comm);
return sum;
}

View File

@ -1,34 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* debug.c
*
* This file contains various functions that are used to display debuging
* information
*
* George Irene
*/
#include "parmetis.h"
/*************************************************************************
* This function prints a vector stored in each processor
**************************************************************************/
void PrintVector2(CtrlType *ctrl, int n, int first, idxtype *vec, char *title)
{
int i, penum;
for (penum=0; penum<ctrl->npes; penum++) {
if (ctrl->mype == penum) {
if (ctrl->mype == 0)
printf("%s\n", title);
printf("\t%3d. ", ctrl->mype);
for (i=0; i<n; i++)
printf("[%d %d.%hd] ", first+i, (vec[i]>=KEEP_BIT ? 1 : 0), (vec[i]>=KEEP_BIT ? vec[i]-KEEP_BIT : vec[i]));
printf("\n");
fflush(stdout);
}
MPI_Barrier(ctrl->comm);
}
}

View File

@ -1,68 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* defs.h
*
* This file contains constant definitions
*
* George Irene
*/
#define LTERM (void **) 0 /* List terminator for GKfree() */
#define NGD_PASSES 20
#define OPTION_IPART 1
#define OPTION_FOLDF 2
#define OPTION_DBGLVL 3
#define XYZ_XCOORD 1
#define XYZ_SPFILL 2
/* Type of initial partitioning algorithms */
#define IPART_SER 1
#define IPART_RB 2
/* Type of initial vertex separator algorithms */
#define ISEP_EDGE 1
#define ISEP_NODE 2
#define UNMATCHED -1
#define MAYBE_MATCHED -2
#define TOO_HEAVY -3
#define MAX_PES 8192
#define MAX_INT (1<<30)
#define HTABLE_EMPTY -1
#define NGR_PASSES 4 /* Number of greedy refinement passes */
#define NIPARTS 8 /* Number of random initial partitions */
#define NLGR_PASSES 5 /* Number of GR refinement during IPartition */
#define IGNORE_FRACTION 0.9 /* What fraction of vertices will not be colored */
#define KEEP_BIT (idxtype)536870912 /* 1<<29 */
#define COARSEN_FRACTION 0.75 /* Node reduction between succesive coarsening levels */
#define COARSEN_FRACTION2 0.55 /* Node reduction between succesive coarsening levels */
#define UNBALANCE_FRACTION 1.05
#define ORDER_UNBALANCE_FRACTION 1.05
#define MAXVWGT_FACTOR 1.4
#define MATCH_LOCAL 1
#define MATCH_GLOBAL 2
#define EDGE_WEIGHT 1
#define NOEDGE_WEIGHT 2
/* Debug Levels */
#define DBG_TIME 1 /* Perform timing analysis */
#define DBG_INFO 2 /* Perform timing analysis */
#define DBG_PROGRESS 4 /* Show the coarsening progress */
#define DBG_REFINEINFO 8 /* Show info on communication during folding */
#define DBG_MATCHINFO 16 /* Show info on matching */
#define DBG_RMOVEINFO 32 /* Show info on communication during folding */
#define DBG_REMAP 64 /* Determines if remapping will take place */
#define DBG_TRACK 128 /* IRENE */

View File

@ -1,64 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* diffuse.c
*
* This is the entry point of parallel difussive repartitioning routines
*
* George Irene
*/
#include "parmetis.h"
/***********************************************************************************
* This function is the entry point of the parallel multilevel local diffusion
* algorithm. It uses parallel undirected diffusion followed by adaptive k-way
* refinement. This function utilizes local coarsening.
************************************************************************************/
void ParMETIS_RepartLDiffusion(idxtype *vtxdist, idxtype *xadj, idxtype *adjncy,
idxtype *vwgt, realtype *adjwgt, int *wgtflag, int *numflag, int *options,
int *edgecut, idxtype *part, MPI_Comm *comm)
{
int npes, mype;
CtrlType ctrl;
WorkSpaceType wspace;
GraphType *graph;
MPI_Comm_size(*comm, &npes);
MPI_Comm_rank(*comm, &mype);
if (npes == 1) { /* Take care the npes = 1 case */
idxset(vtxdist[1], 0, part);
*edgecut = 0;
return;
}
if (*numflag == 1)
ChangeNumbering(vtxdist, xadj, adjncy, part, npes, mype, 1);
SetUpCtrl(&ctrl, npes, options, *comm);
ctrl.CoarsenTo = amin(vtxdist[npes]+1, 70*npes);
graph = SetUpGraph(&ctrl, vtxdist, xadj, vwgt, adjncy, adjwgt, *wgtflag);
graph->vsize = idxsmalloc(graph->nvtxs, 1, "Par_KMetis: vsize");
PreAllocateMemory(&ctrl, graph, &wspace);
IFSET(ctrl.dbglvl, DBG_TRACK, printf("%d ParMETIS_RepartLDiffusion about to call AdaptiveUndirected_Partition\n",mype));
AdaptiveUndirected_Partition(&ctrl, graph, &wspace);
IFSET(ctrl.dbglvl, DBG_TRACK, printf("%d ParMETIS_RepartLDiffusion about to call ReMapGraph\n",mype));
ReMapGraph(&ctrl, graph, 0, &wspace);
idxcopy(graph->nvtxs, graph->where, part);
*edgecut = graph->mincut;
IMfree(&graph->vsize, LTERM);
FreeInitialGraphAndRemap(graph, *wgtflag);
FreeWSpace(&wspace);
FreeCtrl(&ctrl);
if (*numflag == 1)
ChangeNumbering(vtxdist, xadj, adjncy, part, npes, mype, 0);
}

View File

@ -1,55 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* drivers.c
*
* This file contains the driving routines for the various parallel
* multilevel partitioning and repartitioning algorithms
*
* George Irene
*/
#include "parmetis.h"
/*************************************************************************
* This function is the driver for the adaptive refinement mode of ParMETIS
**************************************************************************/
void AdaptiveUndirected_Partition(CtrlType *ctrl, GraphType *graph, WorkSpaceType *wspace)
{
int i;
SetUp(ctrl, graph, wspace);
IFSET(ctrl->dbglvl, DBG_PROGRESS, rprintf(ctrl, "[%6d %8d %5d %5d][%d][%d,%d]\n",
graph->gnvtxs, GlobalSESum(ctrl, graph->nedges), GlobalSEMin(ctrl, graph->nvtxs),
GlobalSEMax(ctrl, graph->nvtxs), ctrl->CoarsenTo, graph->maxvwgt,
GlobalSEMax(ctrl, graph->vwgt[idxamax(graph->nvtxs, graph->vwgt)])));
if (graph->gnvtxs < 1.3*ctrl->CoarsenTo || (graph->finer != NULL && graph->gnvtxs > graph->finer->gnvtxs*COARSEN_FRACTION)) {
/* Set the initial partition */
IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->InitPartTmr));
graph->where = idxmalloc(graph->nvtxs+graph->nrecv, "Adaptive_Partition: graph->where");
for (i=0; i<graph->nvtxs; i++)
graph->where[i] = ctrl->mype;
IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->InitPartTmr));
ComputePartitionParams(ctrl, graph, wspace);
KWayAdaptiveRefineClean(ctrl, graph, wspace, NGR_PASSES, UNBALANCE_FRACTION);
}
else { /* Coarsen it and the partition it */
IFSET(ctrl->dbglvl, DBG_TRACK, printf("%d AdaptiveUndirected_Partition about to call LocalMatch_HEM\n",ctrl->mype));
LocalMatch_HEM(ctrl, graph, wspace);
AdaptiveUndirected_Partition(ctrl, graph->coarser, wspace);
ProjectPartition(ctrl, graph, wspace);
ComputePartitionParams(ctrl, graph, wspace);
if (1.0*ctrl->nparts*graph->gpwgts[idxamax(ctrl->nparts, graph->gpwgts)]/(1.0*idxsum(ctrl->nparts, graph->gpwgts)) - UNBALANCE_FRACTION > 0.004)
KWayAdaptiveRefineClean(ctrl, graph, wspace, NGR_PASSES, UNBALANCE_FRACTION);
else
KWayRefineClean(ctrl, graph, wspace, NGR_PASSES, UNBALANCE_FRACTION);
}
}

View File

@ -1,826 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* refine.c
*
* This file contains code that performs the k-way refinement
*
* George Irene
*/
#include "parmetis.h"
#define DEBUG_PROJECT_
#define DEBUG_COMPUTEPPARAM_
#define ProperSide(c, from, other) \
(((c) == 0 && (from)-(other) < 0) || ((c) == 1 && (from)-(other) > 0))
/*************************************************************************
* This function projects a partition.
**************************************************************************/
void ProjectPartition(CtrlType *ctrl, GraphType *graph, WorkSpaceType *wspace)
{
int i, nvtxs, nnbrs, firstvtx, cfirstvtx;
idxtype *match, *cmap, *where, *cwhere;
idxtype *peind, *slens, *rlens;
KeyValueType *rcand, *scand;
GraphType *cgraph;
IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->ProjectTmr));
cgraph = graph->coarser;
cwhere = cgraph->where;
cfirstvtx = cgraph->vtxdist[ctrl->mype];
nvtxs = graph->nvtxs;
match = graph->match;
cmap = graph->cmap;
where = graph->where = idxmalloc(nvtxs+graph->nrecv, "ProjectPartition: graph->where");
firstvtx = graph->vtxdist[ctrl->mype];
if (graph->match_type == MATCH_GLOBAL) { /* Only if global matching is on */
/*------------------------------------------------------------
/ Start the transmission of the remote where information
/------------------------------------------------------------*/
scand = wspace->pairs;
nnbrs = graph->nnbrs;
peind = graph->peind;
slens = graph->slens;
rlens = graph->rlens;
rcand = graph->rcand;
/* Issue the receives first */
for (i=0; i<nnbrs; i++) {
if (slens[i+1]-slens[i] > 0) /* Issue a receive only if you are getting something */
MPI_Irecv((void *)(scand+slens[i]), 2*(slens[i+1]-slens[i]), IDX_DATATYPE, peind[i], 1, ctrl->comm, ctrl->rreq+i);
}
#ifdef DEBUG_PROJECT
PrintPairs(ctrl, rlens[nnbrs], rcand, "rcand");
#endif
/* Put the where[rcand[].key] into the val field */
for (i=0; i<rlens[nnbrs]; i++) {
ASSERT(ctrl, rcand[i].val >= 0 && rcand[i].val < cgraph->nvtxs);
rcand[i].val = cwhere[rcand[i].val];
}
#ifdef DEBUG_PROJECT
PrintPairs(ctrl, rlens[nnbrs], rcand, "rcand");
PrintVector(ctrl, nvtxs, firstvtx, cmap, "cmap");
#endif
/* Issue the sends next */
for (i=0; i<nnbrs; i++) {
if (rlens[i+1]-rlens[i] > 0) /* Issue a send only if you are sending something */
MPI_Isend((void *)(rcand+rlens[i]), 2*(rlens[i+1]-rlens[i]), IDX_DATATYPE, peind[i], 1, ctrl->comm, ctrl->sreq+i);
}
}
/*------------------------------------------------------------
/ Project local vertices first
/------------------------------------------------------------*/
for (i=0; i<nvtxs; i++) {
if (match[i] >= KEEP_BIT) {
ASSERT(ctrl, cmap[i]-cfirstvtx>=0 && cmap[i]-cfirstvtx<cgraph->nvtxs);
where[i] = cwhere[cmap[i]-cfirstvtx];
}
}
if (graph->match_type == MATCH_GLOBAL) { /* Only if global matching is on */
/*------------------------------------------------------------
/ Wait for the nonblocking operations to finish
/------------------------------------------------------------*/
for (i=0; i<nnbrs; i++) {
if (rlens[i+1]-rlens[i] > 0)
MPI_Wait(ctrl->sreq+i, &ctrl->status);
}
for (i=0; i<nnbrs; i++) {
if (slens[i+1]-slens[i] > 0)
MPI_Wait(ctrl->rreq+i, &ctrl->status);
}
#ifdef DEBUG_PROJECT
PrintPairs(ctrl, slens[nnbrs], scand, "scand");
#endif
/*------------------------------------------------------------
/ Project received vertices now
/------------------------------------------------------------*/
for (i=0; i<slens[nnbrs]; i++) {
ASSERTP(ctrl, scand[i].key-firstvtx>=0 && scand[i].key-firstvtx<graph->nvtxs, (ctrl, "%d %d %d\n", scand[i].key, firstvtx, graph->nvtxs));
where[scand[i].key-firstvtx] = scand[i].val;
}
}
FreeGraph(graph->coarser);
graph->coarser = NULL;
IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->ProjectTmr));
}
/*************************************************************************
* This function computes the initial id/ed
**************************************************************************/
void ComputePartitionParams(CtrlType *ctrl, GraphType *graph, WorkSpaceType *wspace)
{
int i, j, k, nvtxs, firstvtx;
idxtype *xadj, *ladjncy, *vtxdist, *lpwgts, *gpwgts;
realtype *adjwgt;
idxtype *where, *swhere, *rwhere;
RInfoType *rinfo, *myrinfo;
EdgeType *edegrees;
int me, other;
IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->KWayInitTmr));
nvtxs = graph->nvtxs;
vtxdist = graph->vtxdist;
xadj = graph->xadj;
ladjncy = graph->adjncy;
adjwgt = graph->adjwgt;
where = graph->where;
rinfo = graph->rinfo = (RInfoType *)IMmalloc(sizeof(RInfoType)*nvtxs, "ComputePartitionParams: rinfo");
lpwgts = graph->lpwgts = idxsmalloc(ctrl->nparts, 0, "ComputePartitionParams: lpwgts");
gpwgts = graph->gpwgts = idxmalloc(ctrl->nparts, "ComputePartitionParams: gpwgts");
firstvtx = vtxdist[ctrl->mype];
/*------------------------------------------------------------
/ Send/Receive the where information of interface vertices
/------------------------------------------------------------*/
swhere = wspace->indices;
rwhere = where + nvtxs;
CommInterfaceData(ctrl, graph, where, swhere, rwhere);
#ifdef DEBUG_COMPUTEPPARAM
PrintVector(ctrl, nvtxs, firstvtx, where, "where");
#endif
ASSERT(ctrl, wspace->nlarge >= xadj[nvtxs]);
/*------------------------------------------------------------
/ Compute now the id/ed degrees
/------------------------------------------------------------*/
graph->lmincut = 0;
for (i=0; i<nvtxs; i++) {
me = where[i];
myrinfo = rinfo+i;
lpwgts[me] += graph->vwgt[i];
myrinfo->degrees = wspace->degrees + xadj[i];
myrinfo->ndegrees = 0;
myrinfo->id = myrinfo->ed = 0.0;
for (j=xadj[i]; j<xadj[i+1]; j++) {
if (me == where[ladjncy[j]])
myrinfo->id += adjwgt[j];
else
myrinfo->ed += adjwgt[j];
}
if (myrinfo->ed > 0.0) { /* Time to do some serious work */
graph->lmincut += myrinfo->ed;
edegrees = myrinfo->degrees;
for (j=xadj[i]; j<xadj[i+1]; j++) {
other = where[ladjncy[j]];
if (me != other) {
for (k=0; k<myrinfo->ndegrees; k++) {
if (edegrees[k].edge == other) {
edegrees[k].ewgt += adjwgt[j];
break;
}
}
if (k == myrinfo->ndegrees) {
edegrees[k].edge = other;
edegrees[k].ewgt = adjwgt[j];
myrinfo->ndegrees++;
}
ASSERT(ctrl, myrinfo->ndegrees <= xadj[i+1]-xadj[i]);
}
}
}
}
#ifdef DEBUG_COMPUTEPPARAM
PrintVector(ctrl, ctrl->nparts, 0, lpwgts, "lpwgts");
#endif
/* Finally, sum-up the partition weights */
MPI_Allreduce((void *)lpwgts, (void *)gpwgts, ctrl->nparts, IDX_DATATYPE, MPI_SUM, ctrl->comm);
graph->mincut = GlobalSESumReal(ctrl, graph->lmincut)/2;
#ifdef DEBUG_COMPUTEPPARAM
PrintVector(ctrl, ctrl->nparts, 0, gpwgts, "gpwgts");
#endif
IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->KWayInitTmr));
}
/*************************************************************************
* This function performs k-way refinement
**************************************************************************/
void KWayRefineClean(CtrlType *ctrl, GraphType *graph, WorkSpaceType *wspace, int npasses, float ubfraction)
{
int i, ii, j, k, pass, nvtxs, firstvtx, otherlastvtx, c, nmoves,
nlupd, nsupd, nnbrs, nchanged;
int npes = ctrl->npes, mype = ctrl->mype, nparts = ctrl->nparts;
idxtype *xadj, *ladjncy, *vtxdist;
realtype *adjwgt;
idxtype *where, *lpwgts, *gpwgts;
idxtype *peind, *recvptr, *sendptr;
idxtype *update, *supdate, *rupdate, *pe_updates, *htable;
idxtype *changed, *pperm, *perm;
KeyValueType *swchanges, *rwchanges;
int *nupds_pe;
RInfoType *rinfo, *myrinfo;
EdgeType *degrees;
int from, me, other, vwgt, badminpwgt, badmaxpwgt;
realtype oldcut;
IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->KWayTmr));
nvtxs = graph->nvtxs;
vtxdist = graph->vtxdist;
xadj = graph->xadj;
ladjncy = graph->adjncy;
adjwgt = graph->adjwgt;
firstvtx = vtxdist[mype];
where = graph->where;
rinfo = graph->rinfo;
lpwgts = graph->lpwgts;
gpwgts = graph->gpwgts;
nnbrs = graph->nnbrs;
peind = graph->peind;
recvptr = graph->recvptr;
sendptr = graph->sendptr;
changed = idxmalloc(nvtxs, "KWayRefine: changed");
rwchanges = wspace->pairs;
swchanges = rwchanges + recvptr[nnbrs];
update = idxmalloc(nvtxs, "KWayRefine: update");
supdate = wspace->indices;
rupdate = supdate + recvptr[nnbrs];
nupds_pe = imalloc(npes, "KWayRefine: nupds_pe");
htable = idxsmalloc(nvtxs+graph->nrecv, 0, "KWayRefine: lhtable");
badminpwgt = (1.0/ubfraction)*idxsum(nparts, gpwgts)/nparts;
badmaxpwgt = ubfraction*idxsum(nparts, gpwgts)/nparts;
perm = idxmalloc(nvtxs, "KWayRefine: perm");
for (i=0; i<nvtxs; i++)
perm[i] = i;
pperm = idxmalloc(nparts, "KWayRefine: pperm");
for (i=0; i<nparts; i++)
pperm[i] = i;
IFSET(ctrl->dbglvl, DBG_REFINEINFO, rprintf(ctrl, "K-way refinement %2d [%5d, %5d], [%5d, %5d] Cut: %f, \tBalance: %6.3f\n",
graph->level, gpwgts[idxamin(nparts, gpwgts)], gpwgts[idxamax(nparts, gpwgts)], badminpwgt, badmaxpwgt, graph->mincut,
1.0*nparts*gpwgts[idxamax(nparts, gpwgts)]/(1.0*idxsum(nparts, gpwgts))));
for (pass=0; pass<npasses; pass++) {
if (mype == 0)
RandomPermute(nparts, pperm, 0);
MPI_Bcast((void *)pperm, nparts, IDX_DATATYPE, 0, ctrl->comm);
oldcut = graph->mincut;
/* PrintVector(ctrl, nvtxs, firstvtx, where, "where"); */
FastRandomPermute(nvtxs, perm, 0);
for (c=0; c<2; c++) {
nlupd = nsupd = nmoves = nchanged = 0;
for (ii=0; ii<nvtxs; ii++) {
i = perm[ii];
if (rinfo[i].ed >= rinfo[i].id) { /* Total ED is too high */
degrees = rinfo[i].degrees;
from = where[i];
vwgt = graph->vwgt[i];
if (gpwgts[from]-vwgt < badminpwgt)
continue; /* This cannot be moved! */
for (k=0; k<rinfo[i].ndegrees; k++) {
other = degrees[k].edge;
if (ProperSide(c, pperm[from], pperm[other]) && gpwgts[other]+vwgt <= badmaxpwgt)
break;
}
if (k < rinfo[i].ndegrees) { /* You actually found one */
for (j=k+1; j<rinfo[i].ndegrees; j++) {
other = degrees[j].edge;
if (ProperSide(c, pperm[from], pperm[other]) &&
((degrees[j].ewgt > degrees[k].ewgt && gpwgts[other]+vwgt <= badmaxpwgt) ||
(degrees[j].ewgt == degrees[k].ewgt && gpwgts[other] < gpwgts[degrees[k].edge])))
k = j;
}
other = degrees[k].edge;
if (degrees[k].ewgt > rinfo[i].id ||
/* (degrees[k].ewgt-rinfo[i].id > -vwgt && gpwgts[other]+vwgt < 0.8*badminpwgt) || */
(degrees[k].ewgt == rinfo[i].id &&
(other == mype || gpwgts[from] > badmaxpwgt || gpwgts[other] < badminpwgt || (from != mype && (gpwgts[from] - gpwgts[other] >= vwgt))))) {
/* Update where, weight, and ID/ED information of the vertex you moved */
where[i] = other;
INC_DEC(lpwgts[other], lpwgts[from], vwgt);
INC_DEC(gpwgts[other], gpwgts[from], vwgt);
if (htable[i] == 0) { /* make sure you do the update */
htable[i] = 1;
update[nlupd++] = i;
}
/* Put the vertices adjacent to i into the update array */
for (j=xadj[i]; j<xadj[i+1]; j++) {
k = ladjncy[j];
if (htable[k] == 0) {
htable[k] = 1;
if (k<nvtxs)
update[nlupd++] = k;
else
supdate[nsupd++] = k;
}
}
nmoves++;
if (graph->pexadj[i+1]-graph->pexadj[i] > 0)
changed[nchanged++] = i;
}
}
}
}
/* myprintf(ctrl, "nmoves: %d, nlupd: %d, nsupd: %d\n", nmoves, nlupd, nsupd); */
/* Tell everybody interested what the new where[] info is for the interface vertices */
CommChangedInterfaceData(ctrl, graph, nchanged, changed, where, swchanges, rwchanges, wspace->pv4);
IFSET(ctrl->dbglvl, DBG_RMOVEINFO, rprintf(ctrl, "\t[%d %d], [%5d, %5d], [%d %d %d]\n",
pass, c, badminpwgt, badmaxpwgt,
GlobalSESum(ctrl, nmoves), GlobalSESum(ctrl, nsupd), GlobalSESum(ctrl, nlupd)));
/*-------------------------------------------------------------
/ Time to communicate with processors to send the vertices
/ whose degrees need to be update.
/-------------------------------------------------------------*/
/* Issue the receives first */
for (i=0; i<nnbrs; i++) {
MPI_Irecv((void *)(rupdate+sendptr[i]), sendptr[i+1]-sendptr[i], IDX_DATATYPE,
peind[i], 1, ctrl->comm, ctrl->rreq+i);
}
/* Issue the sends next. This needs some preporcessing */
for (i=0; i<nsupd; i++) {
htable[supdate[i]] = 0;
supdate[i] = graph->imap[supdate[i]];
}
iidxsort(nsupd, supdate);
for (j=i=0; i<nnbrs; i++) {
otherlastvtx = vtxdist[peind[i]+1];
for (k=j; k<nsupd && supdate[k] < otherlastvtx; k++);
MPI_Isend((void *)(supdate+j), k-j, IDX_DATATYPE, peind[i], 1, ctrl->comm, ctrl->sreq+i);
j = k;
}
/* OK, now get into the loop waiting for the send/recv operations to finish */
MPI_Waitall(nnbrs, ctrl->rreq, ctrl->statuses);
for (i=0; i<nnbrs; i++)
MPI_Get_count(ctrl->statuses+i, IDX_DATATYPE, nupds_pe+i);
MPI_Waitall(nnbrs, ctrl->sreq, ctrl->statuses);
/*-------------------------------------------------------------
/ Place the recieved to-be updated vertices into update[]
/-------------------------------------------------------------*/
for (i=0; i<nnbrs; i++) {
pe_updates = rupdate+sendptr[i];
for (j=0; j<nupds_pe[i]; j++) {
k = pe_updates[j];
if (htable[k-firstvtx] == 0) {
htable[k-firstvtx] = 1;
update[nlupd++] = k-firstvtx;
}
}
}
/*-------------------------------------------------------------
/ Update the rinfo of the vertices in the update[] array
/-------------------------------------------------------------*/
for (ii=0; ii<nlupd; ii++) {
i = update[ii];
ASSERT(ctrl, htable[i] == 1);
htable[i] = 0;
me = where[i];
myrinfo = rinfo+i;
graph->lmincut -= myrinfo->ed;
myrinfo->ndegrees = 0;
myrinfo->id = myrinfo->ed = 0.0;
degrees = myrinfo->degrees;
for (j=xadj[i]; j<xadj[i+1]; j++) {
other = where[ladjncy[j]];
if (me != other) {
myrinfo->ed += adjwgt[j];
for (k=0; k<myrinfo->ndegrees; k++) {
if (degrees[k].edge == other) {
degrees[k].ewgt += adjwgt[j];
break;
}
}
if (k == myrinfo->ndegrees) {
degrees[k].edge = other;
degrees[k].ewgt = adjwgt[j];
myrinfo->ndegrees++;
}
ASSERT(ctrl, myrinfo->ndegrees <= xadj[i+1]-xadj[i]);
}
else {
myrinfo->id += adjwgt[j];
}
}
graph->lmincut += myrinfo->ed;
}
}
/* Finally, sum-up the partition weights */
MPI_Allreduce((void *)lpwgts, (void *)gpwgts, nparts, IDX_DATATYPE, MPI_SUM, ctrl->comm);
graph->mincut = GlobalSESumReal(ctrl, graph->lmincut)/2;
IFSET(ctrl->dbglvl, DBG_REFINEINFO, rprintf(ctrl, "\t[%5d, %5d], [%5d, %5d] Cut: %f\n",
gpwgts[idxamin(nparts, gpwgts)], gpwgts[idxamax(nparts, gpwgts)], badminpwgt, badmaxpwgt, graph->mincut));
if (graph->mincut == oldcut && ubfraction > 1.00)
break;
}
IMfree(&update, &nupds_pe, &htable, &changed, &pperm, &perm, LTERM);
IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->KWayTmr));
}
/*************************************************************************
* This function performs k-way refinement
**************************************************************************/
void KWayAdaptiveRefineClean(CtrlType *ctrl, GraphType *graph, WorkSpaceType *wspace, int npasses, float ubfraction)
{
int i, ii, j, k, pass, nvtxs, firstvtx, otherlastvtx, c, nmoves,
nlupd, nsupd, nnbrs, nchanged;
int npes = ctrl->npes, mype = ctrl->mype, nparts = ctrl->nparts;
idxtype *xadj, *ladjncy, *vtxdist;
realtype *adjwgt;
idxtype *where, *lpwgts, *gpwgts;
idxtype *peind, *recvptr, *sendptr;
idxtype *update, *supdate, *rupdate, *pe_updates, *htable;
idxtype *changed, *pperm, *perm, *tocheck;
KeyValueType *swchanges, *rwchanges;
int *nupds_pe;
RInfoType *rinfo, *myrinfo;
EdgeType *degrees;
int from, me, other, to, vwgt, vsize, badminpwgt, badmaxpwgt, ntodo, ndone;
realtype oldcut;
IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->KWayTmr));
nvtxs = graph->nvtxs;
vtxdist = graph->vtxdist;
xadj = graph->xadj;
ladjncy = graph->adjncy;
adjwgt = graph->adjwgt;
firstvtx = vtxdist[mype];
where = graph->where;
rinfo = graph->rinfo;
lpwgts = graph->lpwgts;
gpwgts = graph->gpwgts;
nnbrs = graph->nnbrs;
peind = graph->peind;
recvptr = graph->recvptr;
sendptr = graph->sendptr;
changed = idxmalloc(nvtxs, "KWayRefine: changed");
rwchanges = wspace->pairs;
swchanges = rwchanges + recvptr[nnbrs];
update = idxmalloc(nvtxs, "KWayRefine: update");
supdate = wspace->indices;
rupdate = supdate + recvptr[nnbrs];
nupds_pe = imalloc(npes, "KWayRefine: nupds_pe");
htable = idxsmalloc(nvtxs+graph->nrecv, 0, "KWayRefine: lhtable");
tocheck = idxmalloc(nvtxs, "KWayRefine: tocheck");
badminpwgt = (1.0/ubfraction)*idxsum(nparts, gpwgts)/nparts;
badmaxpwgt = ubfraction*idxsum(nparts, gpwgts)/nparts;
perm = idxmalloc(nvtxs, "KWayRefine: perm");
for (i=0; i<nvtxs; i++)
perm[i] = i;
pperm = idxmalloc(nparts, "KWayRefine: pperm");
for (i=0; i<nparts; i++)
pperm[i] = i;
IFSET(ctrl->dbglvl, DBG_REFINEINFO, rprintf(ctrl, "K-way adaptive refinement %2d [%5d, %5d], [%5d, %5d] Cut: %f, \tBalance: %6.3f\n",
graph->level, gpwgts[idxamin(nparts, gpwgts)], gpwgts[idxamax(nparts, gpwgts)], badminpwgt, badmaxpwgt, graph->mincut,
1.0*nparts*gpwgts[idxamax(nparts, gpwgts)]/(1.0*idxsum(nparts, gpwgts))));
for (pass=0; pass<npasses; pass++) {
if (mype == 0)
RandomPermute(nparts, pperm, 0);
MPI_Bcast((void *)pperm, nparts, IDX_DATATYPE, 0, ctrl->comm);
oldcut = graph->mincut;
FastRandomPermute(nvtxs, perm, 0);
for (c=0; c<2; c++) {
nlupd = nsupd = nmoves = nchanged = ntodo = 0;
/* Go once through the vertices, and moves the one that are OK */
for (ii=0; ii<nvtxs; ii++) {
i = perm[ii];
if (rinfo[i].ed >= rinfo[i].id) { /* Total ED is too high */
degrees = rinfo[i].degrees;
from = where[i];
vwgt = graph->vwgt[i];
vsize = graph->vsize[i];
if (gpwgts[from]-vwgt < badminpwgt)
continue; /* This cannot be moved! */
for (k=0; k<rinfo[i].ndegrees; k++) {
other = degrees[k].edge;
if (ProperSide(c, pperm[from], pperm[other]) && gpwgts[other]+vwgt <= badmaxpwgt)
break;
}
if (k < rinfo[i].ndegrees) { /* You actually found one */
for (j=k+1; j<rinfo[i].ndegrees; j++) {
other = degrees[j].edge;
if (ProperSide(c, pperm[from], pperm[other]) &&
((degrees[j].ewgt > degrees[k].ewgt && gpwgts[other]+vwgt <= badmaxpwgt) ||
(degrees[j].ewgt == degrees[k].ewgt && gpwgts[other] < gpwgts[degrees[k].edge])))
k = j;
}
other = degrees[k].edge;
if (degrees[k].ewgt > rinfo[i].id ||
(degrees[k].ewgt-rinfo[i].id > -vsize && gpwgts[other]+vwgt < 0.8*badminpwgt) ||
(degrees[k].ewgt == rinfo[i].id &&
(other == mype || gpwgts[from] > badmaxpwgt || gpwgts[other] < badminpwgt || (from != mype && (gpwgts[from] - gpwgts[other] >= vwgt))))) {
/*
myprintf(ctrl, " Node: %3d, Gain: %3d, From: %d, To: %d, Vwgt: %3d, Fwgt: %3d, Twgt: %3d, Max/Min: %d %d\n", i, degrees[k].ewgt-rinfo[i].id, from, other, vwgt, gpwgts[from], gpwgts[other], badminpwgt, badmaxpwgt);
*/
/* Update where, weight, and ID/ED information of the vertex you moved */
where[i] = other;
INC_DEC(lpwgts[other], lpwgts[from], vwgt);
INC_DEC(gpwgts[other], gpwgts[from], vwgt);
if (htable[i] == 0) { /* make sure you do the update */
htable[i] = 1;
update[nlupd++] = i;
}
/* Put the vertices adjacent to i into the update array */
for (j=xadj[i]; j<xadj[i+1]; j++) {
k = ladjncy[j];
if (htable[k] == 0) {
htable[k] = 1;
if (k<nvtxs)
update[nlupd++] = k;
else
supdate[nsupd++] = k;
}
}
nmoves++;
if (graph->pexadj[i+1]-graph->pexadj[i] > 0)
changed[nchanged++] = i;
}
}
}
if (gpwgts[where[i]] > badmaxpwgt)
tocheck[ntodo++] = i;
}
MPI_Allreduce((void *)lpwgts, (void *)gpwgts, nparts, IDX_DATATYPE, MPI_SUM, ctrl->comm);
IFSET(ctrl->dbglvl, DBG_REFINEINFO, rprintf(ctrl, "\tLeft todo: \t%d %d\t Balance: %5.3f\n", GlobalSESum(ctrl, ntodo), GlobalSEMax(ctrl, ntodo),
1.0*nparts*gpwgts[idxamax(nparts, gpwgts)]/(1.0*idxsum(nparts, gpwgts))));
/* Go through the vertices for the second time, and move negative gain for balance */
ndone = 0;
for (ii=0; ii<ntodo; ii++) {
i = tocheck[ii];
from = where[i];
vwgt = graph->vwgt[i];
if (gpwgts[from] > badmaxpwgt) {
degrees = rinfo[i].degrees;
for (k=0; k<rinfo[i].ndegrees; k++) {
other = degrees[k].edge;
if (ProperSide(c, pperm[from], pperm[other]) && gpwgts[other]+vwgt <= gpwgts[from])
break;
}
if (k < rinfo[i].ndegrees) { /* You actually found one */
ndone += vwgt;
for (j=k+1; j<rinfo[i].ndegrees; j++) {
other = degrees[j].edge;
to = degrees[k].edge;
if (ProperSide(c, pperm[from], pperm[other])) {
if (gpwgts[other] < badminpwgt && (gpwgts[to] > badminpwgt || degrees[j].ewgt > degrees[k].ewgt))
k = j;
else if (gpwgts[to] > badminpwgt &&
((degrees[j].ewgt > degrees[k].ewgt && gpwgts[other]+vwgt <= gpwgts[from]) ||
(degrees[j].ewgt == degrees[k].ewgt && gpwgts[other] < gpwgts[to])))
k = j;
}
}
other = degrees[k].edge;
/*
myprintf(ctrl, "*Node: %3d, Gain: %3d, From: %d, To: %d, Vwgt: %3d, Fwgt: %3d, Twgt: %3d, Max/Min: %d %d\n", i, degrees[k].ewgt-rinfo[i].id, from, other, vwgt, gpwgts[from], gpwgts[other], badminpwgt, badmaxpwgt);
*/
/* Update where, weight, and ID/ED information of the vertex you moved */
where[i] = other;
INC_DEC(lpwgts[other], lpwgts[from], vwgt);
INC_DEC(gpwgts[other], gpwgts[from], vwgt);
if (htable[i] == 0) { /* make sure you do the update */
htable[i] = 1;
update[nlupd++] = i;
}
/* Put the vertices adjacent to i into the update array */
for (j=xadj[i]; j<xadj[i+1]; j++) {
k = ladjncy[j];
if (htable[k] == 0) {
htable[k] = 1;
if (k<nvtxs)
update[nlupd++] = k;
else
supdate[nsupd++] = k;
}
}
nmoves++;
if (graph->pexadj[i+1]-graph->pexadj[i] > 0)
changed[nchanged++] = i;
}
}
}
MPI_Allreduce((void *)lpwgts, (void *)gpwgts, nparts, IDX_DATATYPE, MPI_SUM, ctrl->comm);
IFSET(ctrl->dbglvl, DBG_REFINEINFO, rprintf(ctrl, "\tActual done: \t%d %d\t Balance: %5.3f\n", GlobalSESum(ctrl, ndone), GlobalSEMax(ctrl, ndone),
1.0*nparts*gpwgts[idxamax(nparts, gpwgts)]/(1.0*idxsum(nparts, gpwgts))));
/* myprintf(ctrl, "nmoves: %d, nlupd: %d, nsupd: %d\n", nmoves, nlupd, nsupd); */
/* Tell everybody interested what the new where[] info is for the interface vertices */
CommChangedInterfaceData(ctrl, graph, nchanged, changed, where, swchanges, rwchanges, wspace->pv4);
IFSET(ctrl->dbglvl, DBG_RMOVEINFO, rprintf(ctrl, "\t[%d %d], [%5d, %5d], [%d %d %d]\n",
pass, c, badminpwgt, badmaxpwgt,
GlobalSESum(ctrl, nmoves), GlobalSESum(ctrl, nsupd), GlobalSESum(ctrl, nlupd)));
/*-------------------------------------------------------------
/ Time to communicate with processors to send the vertices
/ whose degrees need to be update.
/-------------------------------------------------------------*/
/* Issue the receives first */
for (i=0; i<nnbrs; i++) {
MPI_Irecv((void *)(rupdate+sendptr[i]), sendptr[i+1]-sendptr[i], IDX_DATATYPE,
peind[i], 1, ctrl->comm, ctrl->rreq+i);
}
/* Issue the sends next. This needs some preporcessing */
for (i=0; i<nsupd; i++) {
htable[supdate[i]] = 0;
supdate[i] = graph->imap[supdate[i]];
}
iidxsort(nsupd, supdate);
for (j=i=0; i<nnbrs; i++) {
otherlastvtx = vtxdist[peind[i]+1];
for (k=j; k<nsupd && supdate[k] < otherlastvtx; k++);
MPI_Isend((void *)(supdate+j), k-j, IDX_DATATYPE, peind[i], 1, ctrl->comm, ctrl->sreq+i);
j = k;
}
/* OK, now get into the loop waiting for the send/recv operations to finish */
MPI_Waitall(nnbrs, ctrl->rreq, ctrl->statuses);
for (i=0; i<nnbrs; i++)
MPI_Get_count(ctrl->statuses+i, IDX_DATATYPE, nupds_pe+i);
MPI_Waitall(nnbrs, ctrl->sreq, ctrl->statuses);
/*-------------------------------------------------------------
/ Place the recieved to-be updated vertices into update[]
/-------------------------------------------------------------*/
for (i=0; i<nnbrs; i++) {
pe_updates = rupdate+sendptr[i];
for (j=0; j<nupds_pe[i]; j++) {
k = pe_updates[j];
if (htable[k-firstvtx] == 0) {
htable[k-firstvtx] = 1;
update[nlupd++] = k-firstvtx;
}
}
}
/*-------------------------------------------------------------
/ Update the rinfo of the vertices in the update[] array
/-------------------------------------------------------------*/
for (ii=0; ii<nlupd; ii++) {
i = update[ii];
ASSERT(ctrl, htable[i] == 1);
htable[i] = 0;
me = where[i];
myrinfo = rinfo+i;
graph->lmincut -= myrinfo->ed;
myrinfo->ndegrees = myrinfo->id = myrinfo->ed = 0;
degrees = myrinfo->degrees;
for (j=xadj[i]; j<xadj[i+1]; j++) {
other = where[ladjncy[j]];
if (me != other) {
myrinfo->ed += adjwgt[j];
for (k=0; k<myrinfo->ndegrees; k++) {
if (degrees[k].edge == other) {
degrees[k].ewgt += adjwgt[j];
break;
}
}
if (k == myrinfo->ndegrees) {
degrees[k].edge = other;
degrees[k].ewgt = adjwgt[j];
myrinfo->ndegrees++;
}
ASSERT(ctrl, myrinfo->ndegrees <= xadj[i+1]-xadj[i]);
}
else {
myrinfo->id += adjwgt[j];
}
}
graph->lmincut += myrinfo->ed;
}
}
graph->mincut = GlobalSESum(ctrl, graph->lmincut)/2;
IFSET(ctrl->dbglvl, DBG_REFINEINFO, rprintf(ctrl, "\t[%5d, %5d], [%5d, %5d] Cut: %f\n",
gpwgts[idxamin(nparts, gpwgts)], gpwgts[idxamax(nparts, gpwgts)], badminpwgt, badmaxpwgt, graph->mincut));
if (graph->mincut == oldcut)
break;
}
MPI_Allreduce((void *)lpwgts, (void *)gpwgts, nparts, IDX_DATATYPE, MPI_SUM, ctrl->comm);
IMfree(&update, &nupds_pe, &htable, &changed, &perm, &pperm, &tocheck, LTERM);
IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->KWayTmr));
}

View File

@ -1,194 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* fused.c
*
* This is the creation of the fused element graph
*
* Started 04/18/00
* Irene
*/
#include "parmetis.h"
/***********************************************************************************
* This function creates the fused-element-graph and returns the partition
************************************************************************************/
void ParMETIS_FusedElementGraph(idxtype *vtxdist, idxtype *xadj, realtype *vvol,
realtype *vsurf, idxtype *adjncy, idxtype *vwgt, realtype *adjwgt,
int *wgtflag, int *numflag, int *nparts, int *options,
idxtype *part, MPI_Comm *comm)
{
int npes, mype, nvtxs;
CtrlType ctrl;
WorkSpaceType wspace;
GraphType *graph;
MPI_Comm_size(*comm, &npes);
MPI_Comm_rank(*comm, &mype);
nvtxs = vtxdist[mype+1]-vtxdist[mype];
/* IFSET(options[OPTION_DBGLVL], DBG_TRACK, printf("%d ParMETIS_FEG npes=%d\n",mype, npes)); */
SetUpCtrl(&ctrl, *nparts, options, *comm);
ctrl.CoarsenTo = amin(vtxdist[npes]+1, 25*amax(npes, *nparts));
graph = SetUpGraph(&ctrl, vtxdist, xadj, vwgt, adjncy, adjwgt, *wgtflag);
graph->where = part;
PreAllocateMemory(&ctrl, graph, &wspace);
IFSET(ctrl.dbglvl, DBG_TIME, InitTimers(&ctrl));
IFSET(ctrl.dbglvl, DBG_TIME, MPI_Barrier(ctrl.gcomm));
IFSET(ctrl.dbglvl, DBG_TIME, starttimer(ctrl.TotalTmr));
CreateFusedElementGraph(&ctrl, graph, &wspace, numflag);
idxcopy(nvtxs, graph->where, part);
IFSET(ctrl.dbglvl, DBG_TIME, MPI_Barrier(ctrl.gcomm));
IFSET(ctrl.dbglvl, DBG_TIME, stoptimer(ctrl.TotalTmr));
if (((*wgtflag)&2) == 0)
IMfree(&graph->vwgt, LTERM);
IMfree(&graph->lperm, &graph->peind, &graph->pexadj, &graph->peadjncy,
&graph->peadjloc, &graph->recvptr, &graph->recvind, &graph->sendptr,
&graph->imap, &graph->sendind, &graph, LTERM);
FreeWSpace(&wspace);
FreeCtrl(&ctrl);
}
/**********************************************************************************/
void CreateFusedElementGraph(CtrlType *ctrl, GraphType *graph, WorkSpaceType *wspace, int *numflag)
{
int i, j, k, l;
int *nparts, ipart, mypart, newpart;
int wgtflag, edgecut, npes, mype, nvtxs, nedges, counter;
int gnfvtxs, nfvtxs, firstfvtx;
int foptions[10];
idxtype *fptr, *find;
idxtype *part, *fpart, *spart, *rpart;
idxtype *vtxdist, *xadj, *adjncy;
idxtype *fvtxdist, *fxadj, *fadjncy;
idxtype *map;
realtype *fadjwgt;
MPI_Comm *comm;
npes = ctrl->npes;
mype = ctrl->mype;
nparts = &(ctrl->nparts);
comm = &(ctrl->comm);
vtxdist = graph->vtxdist;
xadj = graph->xadj;
adjncy = graph->adjncy;
nvtxs = vtxdist[mype+1]-vtxdist[mype];
nedges = xadj[nvtxs];
SetUp(ctrl, graph, wspace);
/* Communicate number of parts found */
fvtxdist = idxmalloc(npes+1, "FusedElementGraph: fvtxdist");
MPI_Allgather((void *)nparts, 1, MPI_INT, (void *)fvtxdist, 1, MPI_INT, *comm);
MAKECSR(i, npes, fvtxdist);
firstfvtx = fvtxdist[mype];
nfvtxs = fvtxdist[mype+1]-fvtxdist[mype];
gnfvtxs = fvtxdist[npes];
ASSERT(ctrl, nfvtxs == *nparts);
part = idxmalloc(nvtxs+graph->nrecv, "FusedElementGraph: part");
idxcopy(nvtxs, graph->where, part);
spart = wspace->indices;
rpart = part + nvtxs;
CommInterfaceData(ctrl, graph, part, spart, rpart);
/* Create a part-to-vertex mapping */
/* map = idxsmalloc(gnfvtxs, -1, "FusedElementGraph: map"); */ /* TOO GENEROUS !! */
/* fptr = idxsmalloc(*nparts+1, 0, "FusedElementGraph: fptr"); */
/* find = idxmalloc(nvtxs, "FusedElementGraph: find"); */
if (gnfvtxs + nvtxs + (*nparts+1) <= wspace->maxcore) {
map = wspace->core;
idxset(gnfvtxs, -1, map);
fptr = map + gnfvtxs;
}
else {
map = idxsmalloc(gnfvtxs, -1, "FusedElementGraph: map");
fptr = wspace->core;
}
idxset((*nparts+1), 0, fptr);
find = fptr + (*nparts+1);
for (i=0; i<nvtxs; i++)
fptr[part[i]-firstfvtx]++;
MAKECSR(i, *nparts, fptr);
for (i=0; i<nvtxs; i++) {
ipart = part[i] - firstfvtx;
find[fptr[ipart]] = i;
fptr[ipart]++;
}
for (ipart=*nparts; ipart>0; ipart--)
fptr[ipart] = fptr[ipart-1];
fptr[0] = 0;
/* Create the fused graph for the local edges */
fxadj = idxsmalloc(nfvtxs+1, 0, "FusedElementGraph: fxadj");
fadjncy = idxmalloc(nedges, "FusedElementGraph: fadjncy");
fadjwgt = realsmalloc(nedges, 0, "FusedElementGraph: fadjwgt");
fxadj[0] = 0;
for (ipart=0; ipart<*nparts; ipart++) {
counter = 0;
mypart = ipart + firstfvtx;
for (l=fptr[ipart]; l<fptr[ipart+1]; l++) {
i = find[l];
for (j=xadj[i]; j<xadj[i+1]; j++) {
k=adjncy[j];
newpart=part[k];
if (newpart != mypart && map[newpart] == -1) { /* edge is not created yet */
map[newpart] = fxadj[ipart]+counter;
fadjncy[fxadj[ipart]+counter] = newpart;
fadjwgt[map[newpart]] = 1; /* alternatively = adjwgt[k] */
counter++;
}
else if (newpart != mypart && map[newpart] != -1) /* edge is already there */
fadjwgt[map[newpart]]++;
}
}
fxadj[ipart+1] = fxadj[ipart] + counter;
for (i=fxadj[ipart]; i<fxadj[ipart+1]; i++)
map[fadjncy[i]] = -1;
}
/* Now change the weights of the interface edges */
ChangeWeights(nfvtxs, fvtxdist, fxadj, fadjncy, fadjwgt, *comm);
/* Repartition the graph using fused elements */
foptions[0] = 1;
foptions[3] = 0;
/* fpart = idxmalloc(nfvtxs, "TestParMetis: fpart"); */
fpart = map; /* it is OK since nfvtxs < gnfvtxs */
wgtflag = 1;
ParMETIS_RepartLDiffusion(fvtxdist, fxadj, fadjncy, NULL, fadjwgt,
&wgtflag, numflag, foptions, &edgecut, fpart, comm);
/* Project the partitioning back to the original graph */
for (ipart=0; ipart<nfvtxs; ipart++) {
ASSERTP(ctrl, fpart[ipart] >= 0 && fpart[ipart] < npes, (ctrl, "%d %d %d\n", ipart , fpart[ipart], npes) );
for (i=fptr[ipart]; i<fptr[ipart+1]; i++)
graph->where[find[i]]=fpart[ipart];
}
if (gnfvtxs + nvtxs + (*nparts+1) > wspace->maxcore)
IMfree(&map, LTERM);
IMfree(&fvtxdist, &fxadj, &fadjncy, &fadjwgt, &part, LTERM);
}

View File

@ -1,144 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* grsetup.c
*
* This file contain various graph setting up routines
*
* George Irene
*/
#include "parmetis.h"
/*************************************************************************
* This function setsup the CtrlType structure
**************************************************************************/
GraphType *SetUpGraph(CtrlType *ctrl, idxtype *vtxdist, idxtype *xadj,
idxtype *vwgt, idxtype *adjncy, realtype *adjwgt, int wgtflag)
{
int tvwgt;
GraphType *graph;
graph = CreateGraph();
graph->level = 0;
graph->gnvtxs = vtxdist[ctrl->npes];
graph->nvtxs = vtxdist[ctrl->mype+1]-vtxdist[ctrl->mype];
graph->nedges = xadj[graph->nvtxs];
graph->xadj = xadj;
graph->vwgt = vwgt;
graph->adjncy = adjncy;
graph->adjwgt = adjwgt;
graph->vtxdist = vtxdist;
if ((wgtflag&2) == 0)
graph->vwgt = idxsmalloc(graph->nvtxs, 1, "Par_KMetis: vwgt");
if ((wgtflag&1) == 0)
graph->adjwgt = realsmalloc(graph->nedges, 1, "Par_KMetis: vwgt");
tvwgt = GlobalSESum(ctrl, idxsum(graph->nvtxs, graph->vwgt));
graph->maxvwgt = MAXVWGT_FACTOR*tvwgt/ctrl->CoarsenTo;
return graph;
}
/*************************************************************************
* This function setsup the CtrlType structure
**************************************************************************/
void SetUpCtrl(CtrlType *ctrl, int nparts, int *options, MPI_Comm comm)
{
MPI_Comm_dup(comm, &(ctrl->gcomm));
MPI_Comm_rank(ctrl->gcomm, &ctrl->mype);
MPI_Comm_size(ctrl->gcomm, &ctrl->npes);
if (options[0] == 1) { /* Get user specified options */
ctrl->dbglvl = options[OPTION_DBGLVL];
ctrl->foldf = options[OPTION_FOLDF];
ctrl->ipart = options[OPTION_IPART];
}
else { /* Assign default options */
ctrl->dbglvl = 0;
ctrl->foldf = 0;
ctrl->ipart = IPART_RB;
}
ctrl->nparts = nparts; /* Set the # of partitions is de-coupled from the # of domains */
ctrl->comm = ctrl->gcomm;
ctrl->xyztype = XYZ_SPFILL;
srand(ctrl->mype);
srand48(ctrl->mype);
}
/*************************************************************************
* This function changes the numbering from 1 to 0 or 0 to 1
**************************************************************************/
void ChangeNumbering(idxtype *vtxdist, idxtype *xadj, idxtype *adjncy, idxtype *part, int npes, int mype, int from)
{
int i, nvtxs, nedges;
if (from == 1) { /* Change it from 1 to 0 */
for (i=0; i<npes+1; i++)
vtxdist[i]--;
nvtxs = vtxdist[mype+1]-vtxdist[mype];
for (i=0; i<nvtxs+1; i++)
xadj[i]--;
nedges = xadj[nvtxs];
for (i=0; i<nedges; i++)
adjncy[i]--;
}
else { /* Change it from 0 to 1 */
nvtxs = vtxdist[mype+1]-vtxdist[mype];
nedges = xadj[nvtxs];
for (i=0; i<npes+1; i++)
vtxdist[i]++;
for (i=0; i<nvtxs+1; i++)
xadj[i]++;
for (i=0; i<nedges; i++)
adjncy[i]++;
for (i=0; i<nvtxs; i++)
part[i]++;
}
}
/*************************************************************************
* This function computes movement statistics for adaptive refinement
* schemes
**************************************************************************/
void ComputeMoveStatistics(CtrlType *ctrl, GraphType *graph, int *nmoved, int *maxin, int *maxout)
{
int i, j, nvtxs;
idxtype *where;
idxtype *lpvtxs, *gpvtxs;
nvtxs = graph->nvtxs;
where = graph->where;
lpvtxs = idxsmalloc(ctrl->nparts, 0, "ComputeMoveStatistics: lpvtxs");
gpvtxs = idxsmalloc(ctrl->nparts, 0, "ComputeMoveStatistics: gpvtxs");
for (j=i=0; i<nvtxs; i++) {
lpvtxs[where[i]]++;
if (where[i] != ctrl->mype)
j++;
}
/* PrintVector(ctrl, ctrl->npes, 0, lpvtxs, "Lpvtxs: "); */
MPI_Allreduce((void *)lpvtxs, (void *)gpvtxs, ctrl->nparts, IDX_DATATYPE, MPI_SUM, ctrl->comm);
*nmoved = GlobalSESum(ctrl, j);
*maxout = GlobalSEMax(ctrl, j);
*maxin = GlobalSEMax(ctrl, gpvtxs[ctrl->mype]-(nvtxs-j));
IMfree(&lpvtxs, &gpvtxs, LTERM);
}

View File

@ -1,152 +0,0 @@
#include "parmetis.h"
/* Byte-wise swap two items of size SIZE. */
#define QSSWAP(a, b, stmp) do { stmp = (a); (a) = (b); (b) = stmp; } while (0)
/* Discontinue quicksort algorithm when partition gets below this size.
This particular magic number was chosen to work best on a Sun 4/260. */
#define MAX_THRESH 20
/* Stack node declarations used to store unfulfilled partition obligations. */
typedef struct {
idxtype *lo;
idxtype *hi;
} stack_node;
/* The next 4 #defines implement a very fast in-line stack abstraction. */
#define STACK_SIZE (8 * sizeof(unsigned long int))
#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
#define STACK_NOT_EMPTY (stack < top)
void iidxsort(int total_elems, idxtype *pbase)
{
idxtype pivot, stmp;
if (total_elems == 0)
/* Avoid lossage with unsigned arithmetic below. */
return;
if (total_elems > MAX_THRESH) {
idxtype *lo = pbase;
idxtype *hi = &lo[total_elems - 1];
stack_node stack[STACK_SIZE]; /* Largest size needed for 32-bit int!!! */
stack_node *top = stack + 1;
while (STACK_NOT_EMPTY) {
idxtype *left_ptr;
idxtype *right_ptr;
idxtype *mid = lo + ((hi - lo) >> 1);
if (*mid < *lo)
QSSWAP(*mid, *lo, stmp);
if (*hi < *mid)
QSSWAP(*mid, *hi, stmp);
else
goto jump_over;
if (*mid < *lo)
QSSWAP(*mid, *lo, stmp);
jump_over:;
pivot = *mid;
left_ptr = lo + 1;
right_ptr = hi - 1;
/* Here's the famous ``collapse the walls'' section of quicksort.
Gotta like those tight inner loops! They are the main reason
that this algorithm runs much faster than others. */
do {
while (*left_ptr < pivot)
left_ptr++;
while (pivot < *right_ptr)
right_ptr--;
if (left_ptr < right_ptr) {
QSSWAP (*left_ptr, *right_ptr, stmp);
left_ptr++;
right_ptr--;
}
else if (left_ptr == right_ptr) {
left_ptr++;
right_ptr--;
break;
}
} while (left_ptr <= right_ptr);
/* Set up pointers for next iteration. First determine whether
left and right partitions are below the threshold size. If so,
ignore one or both. Otherwise, push the larger partition's
bounds on the stack and continue sorting the smaller one. */
if ((size_t) (right_ptr - lo) <= MAX_THRESH) {
if ((size_t) (hi - left_ptr) <= MAX_THRESH)
/* Ignore both small partitions. */
POP (lo, hi);
else
/* Ignore small left partition. */
lo = left_ptr;
}
else if ((size_t) (hi - left_ptr) <= MAX_THRESH)
/* Ignore small right partition. */
hi = right_ptr;
else if ((right_ptr - lo) > (hi - left_ptr)) {
/* Push larger left partition indices. */
PUSH (lo, right_ptr);
lo = left_ptr;
}
else {
/* Push larger right partition indices. */
PUSH (left_ptr, hi);
hi = right_ptr;
}
}
}
/* Once the BASE_PTR array is partially sorted by quicksort the rest
is completely sorted using insertion sort, since this is efficient
for partitions below MAX_THRESH size. BASE_PTR points to the beginning
of the array to sort, and END_PTR points at the very last element in
the array (*not* one beyond it!). */
{
idxtype *end_ptr = &pbase[total_elems - 1];
idxtype *tmp_ptr = pbase;
idxtype *thresh = (end_ptr < pbase + MAX_THRESH ? end_ptr : pbase + MAX_THRESH);
register idxtype *run_ptr;
/* Find smallest element in first threshold and place it at the
array's beginning. This is the smallest array element,
and the operation speeds up insertion sort's inner loop. */
for (run_ptr = tmp_ptr + 1; run_ptr <= thresh; run_ptr++)
if (*run_ptr < *tmp_ptr)
tmp_ptr = run_ptr;
if (tmp_ptr != pbase)
QSSWAP(*tmp_ptr, *pbase, stmp);
/* Insertion sort, running from left-hand-side up to right-hand-side. */
run_ptr = pbase + 1;
while (++run_ptr <= end_ptr) {
tmp_ptr = run_ptr - 1;
while (*run_ptr < *tmp_ptr)
tmp_ptr--;
tmp_ptr++;
if (tmp_ptr != run_ptr) {
idxtype elmnt = *run_ptr;
idxtype *mptr;
for (mptr=run_ptr; mptr>tmp_ptr; mptr--)
*mptr = *(mptr-1);
*mptr = elmnt;
}
}
}
}

View File

@ -1,151 +0,0 @@
#include "parmetis.h"
/* Byte-wise swap two items of size SIZE. */
#define QSSWAP(a, b, stmp) do { stmp = (a); (a) = (b); (b) = stmp; } while (0)
/* Discontinue quicksort algorithm when partition gets below this size.
This particular magic number was chosen to work best on a Sun 4/260. */
#define MAX_THRESH 20
/* Stack node declarations used to store unfulfilled partition obligations. */
typedef struct {
KeyValueType *lo;
KeyValueType *hi;
} stack_node;
/* The next 4 #defines implement a very fast in-line stack abstraction. */
#define STACK_SIZE (8 * sizeof(unsigned long int))
#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
#define STACK_NOT_EMPTY (stack < top)
void ikeysort(int total_elems, KeyValueType *pbase)
{
KeyValueType pivot, stmp;
if (total_elems == 0)
/* Avoid lossage with unsigned arithmetic below. */
return;
if (total_elems > MAX_THRESH) {
KeyValueType *lo = pbase;
KeyValueType *hi = &lo[total_elems - 1];
stack_node stack[STACK_SIZE]; /* Largest size needed for 32-bit int!!! */
stack_node *top = stack + 1;
while (STACK_NOT_EMPTY) {
KeyValueType *left_ptr;
KeyValueType *right_ptr;
KeyValueType *mid = lo + ((hi - lo) >> 1);
if (mid->key < lo->key)
QSSWAP(*mid, *lo, stmp);
if (hi->key < mid->key)
QSSWAP(*mid, *hi, stmp);
else
goto jump_over;
if (mid->key < lo->key)
QSSWAP(*mid, *lo, stmp);
jump_over:;
pivot = *mid;
left_ptr = lo + 1;
right_ptr = hi - 1;
/* Here's the famous ``collapse the walls'' section of quicksort.
Gotta like those tight inner loops! They are the main reason
that this algorithm runs much faster than others. */
do {
while (left_ptr->key < pivot.key)
left_ptr++;
while (pivot.key < right_ptr->key)
right_ptr--;
if (left_ptr < right_ptr) {
QSSWAP (*left_ptr, *right_ptr, stmp);
left_ptr++;
right_ptr--;
}
else if (left_ptr == right_ptr) {
left_ptr++;
right_ptr--;
break;
}
} while (left_ptr <= right_ptr);
/* Set up pointers for next iteration. First determine whether
left and right partitions are below the threshold size. If so,
ignore one or both. Otherwise, push the larger partition's
bounds on the stack and continue sorting the smaller one. */
if ((size_t) (right_ptr - lo) <= MAX_THRESH) {
if ((size_t) (hi - left_ptr) <= MAX_THRESH)
/* Ignore both small partitions. */
POP (lo, hi);
else
/* Ignore small left partition. */
lo = left_ptr;
}
else if ((size_t) (hi - left_ptr) <= MAX_THRESH)
/* Ignore small right partition. */
hi = right_ptr;
else if ((right_ptr - lo) > (hi - left_ptr)) {
/* Push larger left partition indices. */
PUSH (lo, right_ptr);
lo = left_ptr;
}
else {
/* Push larger right partition indices. */
PUSH (left_ptr, hi);
hi = right_ptr;
}
}
}
/* Once the BASE_PTR array is partially sorted by quicksort the rest
is completely sorted using insertion sort, since this is efficient
for partitions below MAX_THRESH size. BASE_PTR points to the beginning
of the array to sort, and END_PTR points at the very last element in
the array (*not* one beyond it!). */
{
KeyValueType *end_ptr = &pbase[total_elems - 1];
KeyValueType *tmp_ptr = pbase;
KeyValueType *thresh = (end_ptr < pbase + MAX_THRESH ? end_ptr : pbase + MAX_THRESH);
register KeyValueType *run_ptr;
/* Find smallest element in first threshold and place it at the
array's beginning. This is the smallest array element,
and the operation speeds up insertion sort's inner loop. */
for (run_ptr = tmp_ptr + 1; run_ptr <= thresh; run_ptr++)
if (run_ptr->key < tmp_ptr->key)
tmp_ptr = run_ptr;
if (tmp_ptr != pbase)
QSSWAP(*tmp_ptr, *pbase, stmp);
/* Insertion sort, running from left-hand-side up to right-hand-side. */
run_ptr = pbase + 1;
while (++run_ptr <= end_ptr) {
tmp_ptr = run_ptr - 1;
while (run_ptr->key < tmp_ptr->key)
tmp_ptr--;
tmp_ptr++;
if (tmp_ptr != run_ptr) {
KeyValueType elmnt = *run_ptr;
KeyValueType *mptr;
for (mptr=run_ptr; mptr>tmp_ptr; mptr--)
*mptr = *(mptr-1);
*mptr = elmnt;
}
}
}
}

View File

@ -1,136 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* macros.h
*
* This file contains macros used in multilevel
*
* George
*/
/*************************************************************************
* The following macro returns a random number in the specified range
**************************************************************************/
#define RandomInRange(u) ((int)(drand48()*((double)(u))))
#define RandomInRangeFast(u) ((rand()>>2)%(u))
#define amax(a, b) ((a) >= (b) ? (a) : (b))
#define amin(a, b) ((a) >= (b) ? (b) : (a))
#define AND(a, b) ((a) < 0 ? ((-(a))&(b)) : ((a)&(b)))
#define OR(a, b) ((a) < 0 ? -((-(a))|(b)) : ((a)|(b)))
#define XOR(a, b) ((a) < 0 ? -((-(a))^(b)) : ((a)^(b)))
#define SWAP(a, b, tmp) \
do {(tmp) = (a); (a) = (b); (b) = (tmp);} while(0)
#define INC_DEC(a, b, val) \
do {(a) += (val); (b) -= (val);} while(0)
#define scopy(n, a, b) memcpy((b), (a), sizeof(float)*(n))
#define idxcopy(n, a, b) memcpy((b), (a), sizeof(idxtype)*(n))
#define realcopy(n, a, b) memcpy((b), (a), sizeof(realtype)*(n))
#define HASHFCT(key, size) ((key)%(size))
/*************************************************************************
* Timer macros
**************************************************************************/
#define cleartimer(tmr) (tmr = 0.0)
#define starttimer(tmr) (tmr -= MPI_Wtime())
#define stoptimer(tmr) (tmr += MPI_Wtime())
#define gettimer(tmr) (tmr)
/*************************************************************************
* This macro is used to handle dbglvl
**************************************************************************/
#define IFSET(a, flag, cmd) if ((a)&(flag)) (cmd);
/*************************************************************************
* These macros are used for debuging memory leaks
**************************************************************************/
#ifdef DMALLOC
#define imalloc(n, msg) (malloc(sizeof(int)*(n)))
#define fmalloc(n, msg) (malloc(sizeof(float)*(n)))
#define idxmalloc(n, msg) (malloc(sizeof(idxtype)*(n)))
#define realmalloc(n, msg) ((realtype *)malloc(sizeof(realtype)*(n)))
#define ismalloc(n, val, msg) (iset((n), (val), malloc(sizeof(int)*(n))))
#define idxsmalloc(n, val, msg) (idxset((n), (val), malloc(sizeof(idxtype)*(n))))
#define realsmalloc(n, val, msg) (realset((n), (val), (realtype *)malloc(sizeof(realtype)*(n))))
#define IMmalloc(a, b) (malloc(a))
#endif
#ifdef DMALLOC
# define MALLOC_CHECK(ptr) \
if (malloc_verify((ptr)) == DMALLOC_VERIFY_ERROR) { \
printf("***MALLOC_CHECK failed on line %d of file %s: " #ptr "\n", \
__LINE__, __FILE__); \
abort(); \
}
#else
# define MALLOC_CHECK(ptr) ;
#endif
/*************************************************************************
* This macro converts a length array in a CSR one
**************************************************************************/
#define MAKECSR(i, n, a) \
do { \
for (i=1; i<n; i++) a[i] += a[i-1]; \
for (i=n; i>0; i--) a[i] = a[i-1]; \
a[0] = 0; \
} while(0)
#ifdef DEBUG
# define ASSERT(ctrl, expr) \
if (!(expr)) { \
myprintf(ctrl, "***ASSERTION failed on line %d of file %s: " #expr "\n", \
__LINE__, __FILE__); \
abort(); \
}
#else
# define ASSERT(ctrl, expr) ;
#endif
#ifdef DEBUG
# define ASSERTP(ctrl, expr,msg) \
if (!(expr)) { \
myprintf(ctrl, "***ASSERTION failed on line %d of file %s:" #expr "\n", \
__LINE__, __FILE__); \
myprintf msg ; \
abort(); \
}
#else
# define ASSERTP(ctrl, expr,msg) ;
#endif
#ifdef DEBUGS
# define ASSERTS(expr) \
if (!(expr)) { \
printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \
__LINE__, __FILE__); \
abort(); \
}
#else
# define ASSERTS(expr) ;
#endif
#ifdef DEBUGS
# define ASSERTSP(expr, msg) \
if (!(expr)) { \
printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \
__LINE__, __FILE__); \
printf msg ; \
abort(); \
}
#else
# define ASSERTSP(expr, msg) ;
#endif

View File

@ -1,241 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* memory.c
*
* This file contains routines that deal with memory allocation
*
* George Irene
*/
#include "parmetis.h"
/*************************************************************************
* This function allocate various pools of memory
**************************************************************************/
void PreAllocateMemory(CtrlType *ctrl, GraphType *graph, WorkSpaceType *wspace)
{
wspace->nlarge = 2*graph->nedges;
/* wspace->maxcore = (7 + sizeof(realtype)/sizeof(idxtype))*graph->nedges; */
wspace->maxcore = graph->nedges*(2*sizeof(KeyValueType) + 2*sizeof(idxtype) + sizeof(EdgeType));
wspace->core = (idxtype *) IMmalloc(wspace->maxcore, "PreAllocateMemory: wspace->core");
wspace->pairs = (KeyValueType *)wspace->core;
wspace->indices = (idxtype *)(wspace->pairs + wspace->nlarge);
wspace->degrees = (EdgeType *)(wspace->indices + wspace->nlarge);
wspace->pv1 = idxmalloc(ctrl->nparts+ctrl->npes+1, "PreAllocateMemory: wspace->pv?");
wspace->pv2 = idxmalloc(ctrl->nparts+ctrl->npes+1, "PreAllocateMemory: wspace->pv?");
wspace->pv3 = idxmalloc(ctrl->nparts+ctrl->npes+1, "PreAllocateMemory: wspace->pv?");
wspace->pv4 = idxmalloc(ctrl->nparts+ctrl->npes+1, "PreAllocateMemory: wspace->pv?");
wspace->pepairs1 = (KeyValueType *)IMmalloc(sizeof(KeyValueType)*(ctrl->nparts+ctrl->npes+1), "PreAllocateMemory: wspace->pepairs?");
wspace->pepairs2 = (KeyValueType *)IMmalloc(sizeof(KeyValueType)*(ctrl->nparts+ctrl->npes+1), "PreAllocateMemory: wspace->pepairs?");
}
/*************************************************************************
* This function de-allocate various pools of memory
**************************************************************************/
void FreeWSpace(WorkSpaceType *wspace)
{
IMfree(&wspace->core,
&wspace->pv1,
&wspace->pv2,
&wspace->pv3,
&wspace->pv4,
&wspace->pepairs1,
&wspace->pepairs2,
LTERM);
}
/*************************************************************************
* This function de-allocates memory allocated for the control structures
**************************************************************************/
void FreeCtrl(CtrlType *ctrl)
{
MPI_Comm_free(&(ctrl->gcomm));
}
/*************************************************************************
* This function creates a CoarseGraphType data structure and initializes
* the various fields
**************************************************************************/
GraphType *CreateGraph(void)
{
GraphType *graph;
graph = (GraphType *)IMmalloc(sizeof(GraphType), "CreateCoarseGraph: graph");
InitGraph(graph);
return graph;
}
/*************************************************************************
* This function creates a CoarseGraphType data structure and initializes
* the various fields
**************************************************************************/
void InitGraph(GraphType *graph)
{
graph->gnvtxs = graph->nvtxs = graph->nedges = graph->nsep = -1;
graph->nnbrs = graph->nrecv = graph->nsend = graph->nlocal = -1;
graph->xadj = graph->vwgt = graph->vsize = graph->adjncy = NULL;
graph->adjwgt = NULL;
graph->vtxdist = NULL;
graph->match = graph->cmap = NULL;
graph->label = NULL;
graph->peind = NULL;
graph->sendptr = graph->sendind = graph->recvptr = graph->recvind = NULL;
graph->imap = NULL;
graph->pexadj = graph->peadjncy = graph->peadjloc = NULL;
graph->lperm = NULL;
graph->slens = graph->rlens = NULL;
graph->rcand = NULL;
graph->where = graph->lpwgts = graph->gpwgts = NULL;
graph->rinfo = NULL;
graph->nrinfo = NULL;
graph->sepind = NULL;
graph->coarser = graph->finer = NULL;
}
/*************************************************************************
* This function deallocates any memory stored in a graph
**************************************************************************/
void FreeGraph(GraphType *graph)
{
IMfree(&graph->xadj,
&graph->vwgt,
&graph->vsize,
&graph->adjncy,
&graph->adjwgt,
&graph->vtxdist,
&graph->match,
&graph->cmap,
&graph->lperm,
&graph->label,
&graph->where,
&graph->rinfo,
&graph->nrinfo,
&graph->sepind,
&graph->lpwgts,
&graph->gpwgts,
&graph->peind,
&graph->sendptr,
&graph->sendind,
&graph->recvptr,
&graph->recvind,
&graph->imap,
&graph->rlens,
&graph->slens,
&graph->rcand,
&graph->pexadj,
&graph->peadjncy,
&graph->peadjloc,
LTERM);
free(graph);
}
/*************************************************************************
* This function deallocates any memory stored in a graph
**************************************************************************/
void FreeGraphContent(GraphType *graph)
{
IMfree(&graph->xadj,
&graph->vwgt,
&graph->vsize,
&graph->adjncy,
&graph->adjwgt,
&graph->vtxdist,
&graph->match,
&graph->cmap,
&graph->lperm,
&graph->where,
&graph->label,
&graph->rinfo,
&graph->nrinfo,
&graph->lpwgts,
&graph->gpwgts,
&graph->peind,
&graph->sendptr,
&graph->sendind,
&graph->recvptr,
&graph->recvind,
&graph->imap,
&graph->rlens,
&graph->slens,
&graph->rcand,
&graph->pexadj,
&graph->peadjncy,
&graph->peadjloc,
LTERM);
}
/*************************************************************************
* This function deallocates any memory stored in a graph
**************************************************************************/
void FreeInitialGraphAndRemap(GraphType *graph, int wgtflag)
{
int i, nedges;
idxtype *adjncy, *imap;
nedges = graph->nedges;
adjncy = graph->adjncy;
imap = graph->imap;
if (imap != NULL) {
for (i=0; i<nedges; i++)
adjncy[i] = imap[adjncy[i]]; /* Apply local to global transformation */
}
/* Free Metis's things */
IMfree(&graph->match,
&graph->cmap,
&graph->lperm,
&graph->where,
&graph->label,
&graph->rinfo,
&graph->nrinfo,
&graph->lpwgts,
&graph->gpwgts,
&graph->sepind,
&graph->peind,
&graph->sendptr,
&graph->sendind,
&graph->recvptr,
&graph->recvind,
&graph->imap,
&graph->rlens,
&graph->slens,
&graph->rcand,
&graph->pexadj,
&graph->peadjncy,
&graph->peadjloc,
LTERM);
if ((wgtflag&2) == 0)
IMfree(&graph->vwgt, &graph->vsize, LTERM);
if ((wgtflag&1) == 0)
IMfree(&graph->adjwgt, LTERM);
free(graph);
}

View File

@ -1,33 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* parmetis.h
*
* This file includes all necessary header files
*
* George Irene
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdarg.h>
#include <time.h>
#include <mpi.h>
#ifdef DMALLOC
#include <dmalloc.h>
#else
#include <malloc.h>
#endif
#include "rename.h"
#include "defs.h"
#include "struct.h"
#include "defs.h"
#include "macros.h"
#include "proto.h"

View File

@ -1,139 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* proto.h
*
* This file contains header files
*
* George Irene
*/
/* coarsen.c */
void LocalMatch_HEM(CtrlType *, GraphType *, WorkSpaceType *);
void Local_CreateCoarseGraph(CtrlType *, GraphType *, WorkSpaceType *, int);
/* comm.c */
void CommInterfaceData(CtrlType *, GraphType *, idxtype *, idxtype *, idxtype *);
void CommChangedInterfaceData(CtrlType *, GraphType *, int, idxtype *, idxtype *, KeyValueType *, KeyValueType *, idxtype *);
int GlobalSEMax(CtrlType *, int);
double GlobalSEMaxDouble(CtrlType *, double);
int GlobalSEMin(CtrlType *, int);
int GlobalSESum(CtrlType *, int);
realtype GlobalSESumReal(CtrlType *, realtype);
/* debug.c */
void PrintVector2(CtrlType *, int, int, idxtype *, char *);
/* diffuse.c */
void ParMETIS_RepartLDiffusion(idxtype *, idxtype *, idxtype *, idxtype *, realtype *, int *, int *, int *, int *, idxtype *, MPI_Comm *);
/* drivers.c */
void AdaptiveUndirected_Partition(CtrlType *, GraphType *, WorkSpaceType *);
/* edge_refine.c */
void ProjectPartition(CtrlType *, GraphType *, WorkSpaceType *);
void ComputePartitionParams(CtrlType *, GraphType *, WorkSpaceType *);
void KWayRefineClean(CtrlType *, GraphType *, WorkSpaceType *, int, float);
void KWayAdaptiveRefineClean(CtrlType *, GraphType *, WorkSpaceType *, int, float);
/* fused.c */
void ParMETIS_FusedElementGraph(idxtype *, idxtype *, realtype *, realtype *, idxtype *, idxtype *,
realtype *, int *, int *, int *, int*, idxtype *, MPI_Comm *);
void CreateFusedElementGraph(CtrlType *, GraphType *, WorkSpaceType *, int *);
/* grsetup.c */
GraphType *SetUpGraph(CtrlType *, idxtype *, idxtype *, idxtype *, idxtype *, realtype *, int);
void SetUpCtrl(CtrlType *ctrl, int, int *, MPI_Comm);
void ChangeNumbering(idxtype *, idxtype *, idxtype *, idxtype *, int, int, int);
void ComputeMoveStatistics(CtrlType *, GraphType *, int *, int *, int *);
/* iidxsort.c */
void iidxsort(int, idxtype *);
/* ikeysort.c */
void ikeysort(int, KeyValueType *);
/* memory.c */
void PreAllocateMemory(CtrlType *, GraphType *, WorkSpaceType *);
void FreeWSpace(WorkSpaceType *);
void FreeCtrl(CtrlType *);
GraphType *CreateGraph(void);
void InitGraph(GraphType *);
void FreeGraph(GraphType *);
void FreeGraphContent(GraphType *);
void FreeInitialGraphAndRemap(GraphType *, int);
/* remap.c */
void ReMapGraph(CtrlType *, GraphType *, int, WorkSpaceType *);
void ComputeTotalVReMap1(CtrlType *, idxtype *, idxtype *, WorkSpaceType *);
/* setup.c */
void SetUp(CtrlType *, GraphType *, WorkSpaceType *);
/* timer.c */
void InitTimers(CtrlType *);
void PrintTimingInfo(CtrlType *);
void PrintTimer(CtrlType *, timer, char *);
/* util.c */
void errexit(char *,...);
void myprintf(CtrlType *, char *f_str,...);
void rprintf(CtrlType *, char *f_str,...);
#ifndef DMALLOC
int *imalloc(int, char *);
idxtype *idxmalloc(int, char *);
float *fmalloc(int, char *);
realtype *realmalloc(int, char *);
int *ismalloc(int, int, char *);
idxtype *idxsmalloc(int, idxtype, char *);
realtype *realsmalloc(int, realtype, char *);
#endif
int *iset(int n, int val, int *x);
idxtype *idxset(int n, idxtype val, idxtype *x);
realtype *realset(int n, realtype val, realtype *x);
int idxamax(int n, idxtype *x);
int idxamin(int n, idxtype *x);
int charsum(int n, char *x);
int isum(int n, int *x);
int idxsum(int, idxtype *);
float snorm2(int, float *);
float sdot(int n, float *, float *);
void saxpy(int, float, float *, float *);
void ikeyvalsort_org(int, KeyValueType *);
int IncKeyValueCmp(const void *, const void *);
void dkeyvalsort(int, KeyValueType *);
int DecKeyValueCmp(const void *, const void *);
int BSearch(int, idxtype *, int);
void RandomPermute(int, idxtype *, int);
void FastRandomPermute(int, idxtype *, int);
int ispow2(int);
int log2(int);
/* var.c */
void ChangeWeights(int, idxtype *, idxtype *, idxtype *, realtype *, MPI_Comm);
/*
void iintsort(int, int *);
void ikeyvalsort(int, KeyValueType *);
double drand48();
void srand48(long);
*/

View File

@ -1,149 +0,0 @@
/*
* remap.c
*
* This file contains code that computes the assignment of processors to
* partition numbers so that it will minimize the redistribution cost
*
* George Irene
*/
#include "parmetis.h"
/*************************************************************************
* This function remaps that graph so that it will minimize the
* redistribution cost
**************************************************************************/
void ReMapGraph(CtrlType *ctrl, GraphType *graph, int rtype, WorkSpaceType *wspace)
{
int i, nvtxs;
idxtype *where, *vsize, *map, *lpwgts;
if (ctrl->npes != ctrl->nparts)
return;
IFSET(ctrl->dbglvl, DBG_TIME, MPI_Barrier(ctrl->comm));
IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->RemapTmr));
nvtxs = graph->nvtxs;
where = graph->where;
vsize = graph->vsize;
map = wspace->pv1;
lpwgts = idxset(ctrl->npes, 0, wspace->pv2);
if (vsize == NULL) {
for (i=0; i<nvtxs; i++)
lpwgts[where[i]]++;
}
else {
for (i=0; i<nvtxs; i++)
lpwgts[where[i]] += vsize[i];
}
ComputeTotalVReMap1(ctrl, lpwgts, map, wspace);
for (i=0; i<nvtxs; i++)
where[i] = map[where[i]];
IFSET(ctrl->dbglvl, DBG_TIME, MPI_Barrier(ctrl->comm));
IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->RemapTmr));
}
/*************************************************************************
* This function computes the assignment using the the objective the
* minimization of the total volume of data that needs to move
**************************************************************************/
void ComputeTotalVReMap1(CtrlType *ctrl, idxtype *lpwgts, idxtype *map, WorkSpaceType *wspace)
{
int i, j, k, npes, mype, nkeys, nmapped, nsaved;
idxtype mywgt, *rowmap, *orgwgt;
KeyValueType *order;
MPI_Status status;
mype = ctrl->mype;
npes = ctrl->npes;
/* Root processor allocates memory for all the lpwgts */
if (mype == 0) {
order = (KeyValueType *)IMmalloc(sizeof(KeyValueType)*npes*npes, "ComputeTotalVReMap: order");
orgwgt = idxmalloc(npes, "ComputeTotalVReMap1: orgwgt");
}
else
order = (KeyValueType *)IMmalloc(sizeof(KeyValueType)*npes, "ComputeTotalVReMap: order");
for (nkeys=0, i=0; i<npes; i++) {
if (lpwgts[i] > 0) {
order[nkeys].key = -lpwgts[i];
order[nkeys++].val = mype*npes+i;
}
}
/* Gather the weight of the initial assignment */
mywgt = lpwgts[mype];
MPI_Gather(&mywgt, 1, IDX_DATATYPE, orgwgt, 1, IDX_DATATYPE, 0, ctrl->comm);
/* Get into a loop receiving the items in order array */
if (mype != 0) {
MPI_Send((void *)order, 2*nkeys, IDX_DATATYPE, 0, 1, ctrl->comm);
}
else {
for (i=1; i<npes; i++) {
MPI_Recv((void *)(order+nkeys), 2*npes, IDX_DATATYPE, i, 1, ctrl->comm, &status);
MPI_Get_count(&status, IDX_DATATYPE, &k);
nkeys += k/2;
}
/* Sort them in decreasing order wrt to their absolute values */
ikeysort(nkeys, order);
rowmap = idxset(npes, -1, wspace->pv3);
idxset(npes, -1, map);
nsaved = 0;
for (nmapped=k=0; k<nkeys && nmapped<npes; k++) {
i = order[k].val/npes;
j = order[k].val%npes;
if (map[j] == -1 && rowmap[i] == -1) {
map[j] = i;
rowmap[i] = j;
nmapped++;
nsaved += (-order[k].key - orgwgt[i]);
}
}
/* Map unmapped partitions */
if (nmapped < npes) {
for (i=j=0; j<npes && nmapped<npes; j++) {
if (map[j] == -1) {
for (; i<npes; i++) {
if (rowmap[i] == -1) {
map[j] = i;
rowmap[i] = j;
nmapped++;
nsaved += - orgwgt[i];
break;
}
}
}
}
}
ASSERT(ctrl, nmapped == npes);
if (nsaved <= 0) {
for (i=0; i<npes; i++)
map[i] = i;
}
free(orgwgt);
}
IMfree(&order, LTERM);
IFSET(ctrl->dbglvl, DBG_INFO, rprintf(ctrl, "Savings from remapping: %d\n", nsaved));
/* Tell everybody about the map array */
MPI_Bcast(map, npes, IDX_DATATYPE, 0, ctrl->comm);
}

View File

@ -1,106 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* rename.h
*
* This file contains renaming #defines to remove any conflicts that the
* library may have with the users functions.
*
* George
*/
/* coarsen.c */
#define LocalMatch_HEM ___LocalMatch_HEM
#define Local_CreateCoarseGraph ___Local_CreateCoarseGraph
/* comm.c */
#define CommInterfaceData ___CommInterfaceData
#define CommChangedInterfaceData ___CommChangedInterfaceData
#define GlobalSEMax ___GlobalSEMax
#define GlobalSEMaxDouble ___GlobalSEMaxDouble
#define GlobalSEMin ___GlobalSEMin
#define GlobalSESum ___GlobalSESum
#define GlobalSESumReal ___GlobalSESumReal
/* debug.c */
#define PrintVector2 ___PrintVector2
/* diffuse.c */
#define ParMETIS_RepartLDiffusion ___ParMETIS_RepartLDiffusion
/* drivers.c */
#define AdaptiveUndirected_Partition ___AdaptiveUndirected_Partition
/* edge_refine.c */
#define ProjectPartition ___ProjectPartition
#define ComputePartitionParams ___ComputePartitionParams
#define KWayRefineClean ___KWayRefineClean
#define KWayAdaptiveRefineClean ___KWayAdaptiveRefineClean
/* grsetup.c */
#define SetUpGraph ___SetUpGraph
#define SetUpCtrl ___SetUpCtrl
#define ChangeNumbering ___ChangeNumbering
#define ComputeMoveStatistics ___ComputeMoveStatistics
/* iidxsort.c */
#define iidxsort ___iidxsort
/* ikeysort.c */
#define ikeysort ___ikeysort
/* memory.c */
#define PreAllocateMemory ___PreAllocateMemory
#define FreeWSpace ___FreeWSpace
#define FreeCtrl ___FreeCtrl
#define CreateGraph ___CreateGraph
#define InitGraph ___InitGraph
#define FreeGraph ___FreeGraph
#define FreeGraphContent ___FreeGraphContent
#define FreeInitialGraphAndRemap ___FreeInitialGraphAndRemap
/* remap.c */
#define ReMapGraph ___ReMapGraph
#define ComputeTotalVReMap1 ___ComputeTotalVReMap1
/* setup.c */
#define SetUp ___SetUp
/* timer.c */
#define InitTimers ___InitTimers
#define PrintTimingInfo ___PrintTimingInfo
#define PrintTimer ___PrintTimer
/* util.c */
#define errexit ___errexit
#define myprintf ___myprintf
#define rprintf ___rprintf
#ifndef DMALLOC
#define imalloc ___imalloc
#define idxmalloc ___idxmalloc
#define fmalloc ___fmalloc
#define realmalloc ___realmalloc
#define ismalloc ___ismalloc
#define idxsmalloc ___idxsmalloc
#define realsmalloc ___realsmalloc
#endif
#define iset ___iset
#define idxset ___idxset
#define realset ___realset
#define idxamax ___idxamax
#define idxamin ___idxamin
#define charsum ___charsum
#define isum ___isum
#define idxsum ___idxsum
#define snorm2 ___snorm2
#define sdot ___sdot
#define saxpy ___saxpy
#define ikeyvalsort_org ___ikeyvalsort_org
#define IncKeyValueCmp ___IncKeyValueCmp
#define dkeyvalsort ___dkeyvalsort
#define DecKeyValueCmp ___DecKeyValueCmp
#define BSearch ___BSearch
#define RandomPermute ___RandomPermute
#define FastRandomPermute ___FastRandomPermute
#define ispow2 ___ispow2
#define log2 ___log2

View File

@ -1,213 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* setup.c
*
* This file contains functions that setup the various communication
* data structures for parallel KWAY
*
* George Irene
*/
#include "parmetis.h"
#define DEBUG_SETUPINFO_
/*************************************************************************
* This function tests the repeated shmem_put
**************************************************************************/
void SetUp(CtrlType *ctrl, GraphType *graph, WorkSpaceType *wspace)
{
int i, j, k, islocal, penum, gnvtxs, nvtxs, nlocal, firstvtx, lastvtx, nsend, nrecv, nnbrs, nadj;
int npes=ctrl->npes, mype=ctrl->mype;
idxtype *vtxdist, *xadj, *adjncy;
idxtype *peind, *recvptr, *recvind, *sendptr, *sendind;
idxtype *receive, *pemap, *imap, *lperm;
idxtype *pexadj, *peadjncy, *peadjloc, *startsind;
KeyValueType *recvrequests, *sendrequests, *adjpairs;
IFSET(ctrl->dbglvl, DBG_TIME, MPI_Barrier(ctrl->comm));
IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->SetupTmr));
gnvtxs = graph->gnvtxs;
nvtxs = graph->nvtxs;
vtxdist = graph->vtxdist;
xadj = graph->xadj;
adjncy = graph->adjncy;
firstvtx = vtxdist[mype];
lastvtx = vtxdist[mype+1];
pemap = wspace->pv1;
idxset(npes, -1, pemap);
lperm = graph->lperm = idxmalloc(nvtxs, "SetUp: graph->lperm");
for (i=0; i<nvtxs; i++)
lperm[i] = i;
/*************************************************************
* Determine what you need to receive
*************************************************************/
receive = wspace->indices; /* Use the large global received array for now */
adjpairs = wspace->pairs;
for (nlocal = nadj = i = 0; i<nvtxs; i++) {
islocal = 1;
for (j=xadj[i]; j<xadj[i+1]; j++) {
k = adjncy[j];
if (k >= firstvtx && k < lastvtx) {
adjncy[j] = k-firstvtx;
continue; /* local vertex */
}
adjpairs[nadj].key = k;
adjpairs[nadj++].val = j;
islocal = 0;
}
if (islocal) {
lperm[i] = lperm[nlocal];
lperm[nlocal++] = i;
}
}
/* Take care the received part now */
ikeysort(nadj, adjpairs);
adjpairs[nadj].key = gnvtxs+1; /* Boundary condition */
for (nrecv=i=0; i<nadj; i++) {
adjncy[adjpairs[i].val] = nvtxs+nrecv;
if (adjpairs[i].key != adjpairs[i+1].key)
receive[nrecv++] = adjpairs[i].key;
}
/* Allocate space for the setup info attached to this level of the graph */
peind = graph->peind = idxmalloc(npes, "SetUp: peind");
recvptr = graph->recvptr = idxmalloc(npes+1, "SetUp: recvptr");
recvind = graph->recvind = idxmalloc(nrecv, "SetUp: recvind");
/* Take care of the received portion */
idxcopy(nrecv, receive, recvind); /* Copy the vertices to be received into recvind */
i = nnbrs = recvptr[0] = 0;
for (penum=0; penum<npes; penum++) {
for (j=i; j<nrecv; j++) {
if (recvind[j] >= vtxdist[penum+1])
break;
}
if (j > i) {
peind[nnbrs] = penum;
recvptr[++nnbrs] = j;
i = j;
}
}
/*************************************************************
* Determine what you need to send
*************************************************************/
/* Tell the other processors what they need to send you */
recvrequests = wspace->pepairs1;
sendrequests = wspace->pepairs2;
for (i=0; i<npes; i++)
recvrequests[i].key = 0;
for (i=0; i<nnbrs; i++) {
recvrequests[peind[i]].key = recvptr[i+1]-recvptr[i];
recvrequests[peind[i]].val = nvtxs+recvptr[i];
}
MPI_Alltoall((void *)recvrequests, 2, IDX_DATATYPE, (void *)sendrequests, 2, IDX_DATATYPE, ctrl->comm);
sendptr = graph->sendptr = idxmalloc(npes+1, "SetUp: sendptr");
startsind = wspace->pv2;
for (j=i=0; i<npes; i++) {
if (sendrequests[i].key > 0) {
sendptr[j] = sendrequests[i].key;
startsind[j] = sendrequests[i].val;
j++;
}
}
ASSERT(ctrl, nnbrs == j);
MAKECSR(i, j, sendptr);
nsend = sendptr[nnbrs];
sendind = graph->sendind = idxmalloc(nsend, "SetUp: sendind");
/* Issue the receives for sendind */
for (i=0; i<nnbrs; i++) {
MPI_Irecv((void *)(sendind+sendptr[i]), sendptr[i+1]-sendptr[i], IDX_DATATYPE,
peind[i], 1, ctrl->comm, ctrl->rreq+i);
}
/* Issue the sends. My recvind[penum] becomes penum's sendind[mype] */
for (i=0; i<nnbrs; i++) {
MPI_Isend((void *)(recvind+recvptr[i]), recvptr[i+1]-recvptr[i], IDX_DATATYPE,
peind[i], 1, ctrl->comm, ctrl->sreq+i);
}
MPI_Waitall(nnbrs, ctrl->rreq, ctrl->statuses);
MPI_Waitall(nnbrs, ctrl->sreq, ctrl->statuses);
/* Create the peadjncy data structure for sparse boundary exchanges */
pexadj = graph->pexadj = idxsmalloc(nvtxs+1, 0, "SetUp: pexadj");
peadjncy = graph->peadjncy = idxmalloc(nsend, "SetUp: peadjncy");
peadjloc = graph->peadjloc = idxmalloc(nsend, "SetUp: peadjloc");
for (i=0; i<nsend; i++) {
ASSERTP(ctrl, sendind[i] >= firstvtx && sendind[i] < lastvtx, (ctrl, "%d %d %d\n", sendind[i], firstvtx, lastvtx));
pexadj[sendind[i]-firstvtx]++;
}
MAKECSR(i, nvtxs, pexadj);
for (i=0; i<nnbrs; i++) {
for (j=sendptr[i]; j<sendptr[i+1]; j++) {
k = pexadj[sendind[j]-firstvtx]++;
peadjncy[k] = i; /* peind[i] is the actual PE number */
peadjloc[k] = startsind[i]++;
}
}
ASSERT(ctrl, pexadj[nvtxs] == nsend);
for (i=nvtxs; i>0; i--)
pexadj[i] = pexadj[i-1];
pexadj[0] = 0;
graph->nnbrs = nnbrs;
graph->nrecv = nrecv;
graph->nsend = nsend;
graph->nlocal = nlocal;
/* Create the inverse map from ladjncy to adjncy */
imap = graph->imap = idxmalloc(nvtxs+nrecv, "SetUp: imap");
for (i=0; i<nvtxs; i++)
imap[i] = firstvtx+i;
for (i=0; i<nrecv; i++)
imap[nvtxs+i] = recvind[i];
/* Check if wspace->nlarge is large enough for nrecv and nsend */
if (wspace->nlarge < nrecv+nsend) {
free(wspace->indices);
free(wspace->pairs);
wspace->nlarge = nrecv+nsend;
wspace->indices = idxmalloc(wspace->nlarge, "SetUp: wspace->indices");
wspace->pairs = (KeyValueType *)IMmalloc(sizeof(KeyValueType)*wspace->nlarge, "SetUp: wspace->pairs");
}
IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->SetupTmr));
#ifdef DEBUG_SETUPINFO
rprintf(ctrl, "[%5d %5d] \tl:[%5d %5d] \ts:[%5d, %5d] \tr:[%5d, %5d]\n",
GlobalSEMin(ctrl, nvtxs), GlobalSEMax(ctrl, nvtxs),
GlobalSEMin(ctrl, nlocal), GlobalSEMax(ctrl, nlocal),
GlobalSEMin(ctrl, nsend), GlobalSEMax(ctrl, nsend),
GlobalSEMin(ctrl, nrecv), GlobalSEMax(ctrl, nrecv));
PrintSetUpInfo(ctrl, graph);
#endif
}

View File

@ -1,222 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* struct.h
*
* This file contains data structures for ILU routines.
*
* George Irene
*/
/* Undefine the following #define in order to use short int as the idxtype */
#define IDXTYPE_INT
/* Undefine the following #define in order to use float as the realtype */
/*#define TYPE_REAL*/
/* Indexes are as long as integers for now */
#ifdef IDXTYPE_INT
typedef int idxtype;
#define IDX_DATATYPE MPI_INT
#else
typedef short idxtype;
#define IDX_DATATYPE MPI_SHORT
#endif
/* floats for now */
#ifdef TYPE_REAL
typedef float realtype;
#define REAL_DATATYPE MPI_FLOAT
#else
typedef double realtype;
#define REAL_DATATYPE MPI_DOUBLE
#endif
/*************************************************************************
* The following data structure stores key-value pair
**************************************************************************/
struct KeyValueType {
idxtype key;
idxtype val;
};
typedef struct KeyValueType KeyValueType;
/*************************************************************************
* The following data structure is used to store the buckets for the
* refinment algorithms
**************************************************************************/
struct PQueueType {
int nnodes;
int maxnnodes;
idxtype *perm, *iperm, *values;
/* iperm[i] stores where the ith entry is located
perm[i] stores the entry that is located in the ith position */
};
typedef struct PQueueType PQueueType;
/*************************************************************************
* The following data structure stores an edge
**************************************************************************/
struct edgedef {
idxtype edge;
realtype ewgt;
};
typedef struct edgedef EdgeType;
/*************************************************************************
* This data structure holds various working space data
**************************************************************************/
struct workspacedef {
idxtype *core; /* Where pairs, indices, and degrees are coming from */
int maxcore;
int nlarge; /* The size of 'Large' */
KeyValueType *pairs; /* Large pair array used during setup */
idxtype *indices; /* Large array of indxtype used for various purposes */
/* Auxiliary parameters */
idxtype *pv1, *pv2, *pv3, *pv4; /* Vectors of npes+1 size used in various places */
KeyValueType *pepairs1, *pepairs2;
EdgeType *degrees;
};
typedef struct workspacedef WorkSpaceType;
/*************************************************************************
* The following data structure holds information on degrees for k-way
* partition
**************************************************************************/
struct rinfodef {
realtype id, ed; /* ID/ED of edges */
int ndegrees; /* The number of different ext-degrees */
EdgeType *degrees; /* List of edges */
};
typedef struct rinfodef RInfoType;
/*************************************************************************
* The following data structure holds information on degrees for k-way
* partition
**************************************************************************/
struct nrinfodef {
int edegrees[2];
};
typedef struct nrinfodef NRInfoType;
/*************************************************************************
* This data structure holds the input graph
**************************************************************************/
struct graphdef {
int gnvtxs, nvtxs, nedges, maxvwgt;
idxtype *xadj; /* Pointers to the locally stored vertices */
idxtype *vwgt; /* Vertex weights */
idxtype *vsize; /* Vertex size */
idxtype *adjncy; /* Array that stores the adjacency lists of nvtxs */
realtype *adjwgt; /* Array that stores the weights of the adjacency lists */
idxtype *vtxdist; /* Distribution of vertices */
idxtype *match;
idxtype *cmap;
idxtype *label;
/* Communication/Setup parameters */
int nnbrs, nrecv, nsend; /* The number of neighboring processors */
idxtype *peind; /* Array of size nnbrs storing the neighboring PEs */
idxtype *sendptr, *sendind; /* CSR format of the vertices that are sent */
idxtype *recvptr, *recvind; /* CSR format of the vertices that are received */
idxtype *imap; /* The inverse map of local to global indices */
idxtype *pexadj, *peadjncy,
*peadjloc; /* CSR format of the PEs each vertex is adjancent to */
int nlocal; /* Number of interior vertices */
idxtype *lperm; /* lperm[0:nlocal] points to interior vertices, the rest are interface */
/* Communication parameters for projecting the partition.
* These are computed during CreateCoarseGraph and used during projection
* Note that during projection, the meaning of received and sent is reversed! */
idxtype *rlens, *slens; /* Arrays of size nnbrs of how many vertices you are sending and receiving */
KeyValueType *rcand;
/* Partition parameters */
idxtype *where;
idxtype *lpwgts, *gpwgts;
RInfoType *rinfo;
/* Node refinement information */
NRInfoType *nrinfo;
int nsep; /* The number of vertices in the separator */
idxtype *sepind; /* The indices of the vertices in the separator */
realtype lmincut, mincut;
int level;
int match_type;
int edgewgt_type;
struct graphdef *coarser, *finer;
};
typedef struct graphdef GraphType;
/*************************************************************************
* The following data type implements a timer
**************************************************************************/
typedef double timer;
/*************************************************************************
* The following structure stores information used by parallel kmetis
**************************************************************************/
struct controldef {
int mype, npes; /* Info about the parallel system */
int CoarsenTo; /* The # of vertices in the coarsest graph */
int dbglvl; /* Controls the debuging output of the program */
int nparts; /* The number of partitions */
int foldf; /* What is the folding factor */
int ipart; /* The type of initial partitioning */
int xyztype; /* The type of coordinate indexing */
MPI_Comm gcomm;
MPI_Comm comm; /* MPI Communicator */
MPI_Request sreq[MAX_PES],
rreq[MAX_PES]; /* MPI send and receive requests */
MPI_Status statuses[MAX_PES];
MPI_Status status;
/* Various Timers */
timer TotalTmr, InitPartTmr, MatchTmr, ContractTmr, CoarsenTmr, RefTmr,
SetupTmr, ColorTmr, ProjectTmr, KWayInitTmr, KWayTmr, MoveTmr,
RemapTmr, AuxTmr1, AuxTmr2, AuxTmr3, AuxTmr4, AuxTmr5, AuxTmr6;
};
typedef struct controldef CtrlType;
/*************************************************************************
* The following data structure stores a sparse matrix in CSR format
* The diagonal entry is in the first position of each row.
**************************************************************************/
struct matrixdef {
int nrows; /* Number of rows in the matrix */
idxtype *rowptr;
idxtype *colind;
float *values;
idxtype *transfer;
};
typedef struct matrixdef MatrixType;

View File

@ -1,85 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* timer.c
*
* This file contain various timing routines
*
* George
*/
#include "parmetis.h"
/*************************************************************************
* This function initializes the various timers
**************************************************************************/
void InitTimers(CtrlType *ctrl)
{
cleartimer(ctrl->TotalTmr);
cleartimer(ctrl->InitPartTmr);
cleartimer(ctrl->MatchTmr);
cleartimer(ctrl->ContractTmr);
cleartimer(ctrl->CoarsenTmr);
cleartimer(ctrl->RefTmr);
cleartimer(ctrl->SetupTmr);
cleartimer(ctrl->ProjectTmr);
cleartimer(ctrl->KWayInitTmr);
cleartimer(ctrl->KWayTmr);
cleartimer(ctrl->MoveTmr);
cleartimer(ctrl->RemapTmr);
cleartimer(ctrl->AuxTmr1);
cleartimer(ctrl->AuxTmr2);
cleartimer(ctrl->AuxTmr3);
cleartimer(ctrl->AuxTmr4);
cleartimer(ctrl->AuxTmr5);
cleartimer(ctrl->AuxTmr6);
}
/*************************************************************************
* This function prints timing information about KMETIS
**************************************************************************/
void PrintTimingInfo(CtrlType *ctrl)
{
/* PrintTimer(ctrl, ctrl->CoarsenTmr, " Coarsening"); */
PrintTimer(ctrl, ctrl->SetupTmr, " Setup");
PrintTimer(ctrl, ctrl->MatchTmr, " Matching");
PrintTimer(ctrl, ctrl->ContractTmr, "Contraction");
PrintTimer(ctrl, ctrl->InitPartTmr, " InitPart");
/* PrintTimer(ctrl, ctrl->RefTmr, " Refinement"); */
PrintTimer(ctrl, ctrl->ProjectTmr, " Project");
PrintTimer(ctrl, ctrl->KWayInitTmr, " Initialize");
PrintTimer(ctrl, ctrl->KWayTmr, " K-way");
PrintTimer(ctrl, ctrl->MoveTmr, " Move");
PrintTimer(ctrl, ctrl->RemapTmr, " Remap");
PrintTimer(ctrl, ctrl->TotalTmr, " Total");
/*
PrintTimer(ctrl, ctrl->AuxTmr1, " Aux1");
PrintTimer(ctrl, ctrl->AuxTmr2, " Aux2");
PrintTimer(ctrl, ctrl->AuxTmr3, " Aux3");
PrintTimer(ctrl, ctrl->AuxTmr4, " Aux4");
PrintTimer(ctrl, ctrl->AuxTmr5, " Aux5");
*/
PrintTimer(ctrl, ctrl->AuxTmr6, " Aux6");
}
/*************************************************************************
* This function prints timer stat
**************************************************************************/
void PrintTimer(CtrlType *ctrl, timer tmr, char *msg)
{
double sum, max, tsec;
tsec = gettimer(tmr);
MPI_Reduce((void *)&tsec, (void *)&sum, 1, MPI_DOUBLE, MPI_SUM, 0, ctrl->comm);
tsec = gettimer(tmr);
MPI_Reduce((void *)&tsec, (void *)&max, 1, MPI_DOUBLE, MPI_MAX, 0, ctrl->comm);
if (ctrl->mype == 0 && sum != 0.0)
printf("%s: Max: %7.3lf, Sum: %7.3lf, Balance: %7.3lf\n",
msg, max, sum, max*ctrl->npes/sum);
}

View File

@ -1,458 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* util.c
*
* This function contains various utility routines
*
* George Irene
*/
#include "parmetis.h"
/*************************************************************************
* This function prints an error message and exits
**************************************************************************/
void errexit(char *f_str,...)
{
va_list argp;
char out1[256], out2[256];
va_start(argp, f_str);
vsprintf(out1, f_str, argp);
va_end(argp);
sprintf(out2, "Error! %s", out1);
fprintf(stdout, out2);
fflush(stdout);
abort();
}
/*************************************************************************
* This function prints an error message and exits
**************************************************************************/
void myprintf(CtrlType *ctrl, char *f_str,...)
{
va_list argp;
char out1[256], out2[256];
va_start(argp, f_str);
vsprintf(out1, f_str, argp);
va_end(argp);
sprintf(out2, "[%2d] %s", ctrl->mype, out1);
fprintf(stdout, out2);
fflush(stdout);
}
/*************************************************************************
* This function prints an error message and exits
**************************************************************************/
void rprintf(CtrlType *ctrl, char *f_str,...)
{
va_list argp;
if (ctrl->mype == 0) {
va_start(argp, f_str);
vfprintf(stdout, f_str, argp);
va_end(argp);
}
fflush(stdout);
MPI_Barrier(ctrl->comm);
}
#ifndef DMALLOC
/*************************************************************************
* The following function allocates an array of integers
**************************************************************************/
int *imalloc(int n, char *msg)
{
if (n == 0)
return NULL;
return (int *)IMmalloc(sizeof(int)*n, msg);
}
/*************************************************************************
* The following function allocates an array of integers
**************************************************************************/
idxtype *idxmalloc(int n, char *msg)
{
if (n == 0)
return NULL;
return (idxtype *)IMmalloc(sizeof(idxtype)*n, msg);
}
/*************************************************************************
* The following function allocates an array of float
**************************************************************************/
float *fmalloc(int n, char *msg)
{
if (n == 0)
return NULL;
return (float *)IMmalloc(sizeof(float)*n, msg);
}
/*************************************************************************
* The following function allocates an array of real
**************************************************************************/
realtype *realmalloc(int n, char *msg)
{
if (n == 0)
return NULL;
return (realtype *)IMmalloc(sizeof(realtype)*n, msg);
}
/*************************************************************************
* The follwoing function allocates an array of integers
**************************************************************************/
int *ismalloc(int n, int ival, char *msg)
{
if (n == 0)
return NULL;
return iset(n, ival, (int *)IMmalloc(sizeof(int)*n, msg));
}
/*************************************************************************
* The follwoing function allocates an array of integers
**************************************************************************/
idxtype *idxsmalloc(int n, idxtype ival, char *msg)
{
if (n == 0)
return NULL;
return idxset(n, ival, (idxtype *)IMmalloc(sizeof(idxtype)*n, msg));
}
/*************************************************************************
* The follwoing function allocates an array of reals
**************************************************************************/
realtype *realsmalloc(int n, realtype rval, char *msg)
{
if (n == 0)
return NULL;
return realset(n, rval, (realtype *)IMmalloc(sizeof(realtype)*n, msg));
}
#endif
/*************************************************************************
* These functions set the values of a vector
**************************************************************************/
int *iset(int n, int val, int *x)
{
int i;
for (i=0; i<n; i++)
x[i] = val;
return x;
}
/*************************************************************************
* These functions set the values of a vector
**************************************************************************/
idxtype *idxset(int n, idxtype val, idxtype *x)
{
int i;
for (i=0; i<n; i++)
x[i] = val;
return x;
}
/*************************************************************************
* These functions set the values of a vector
**************************************************************************/
realtype *realset(int n, realtype val, realtype *x)
{
int i;
for (i=0; i<n; i++)
x[i] = val;
return x;
}
/*************************************************************************
* These functions return the index of the maximum element in a vector
**************************************************************************/
int idxamax(int n, idxtype *x)
{
int i, max=0;
for (i=1; i<n; i++)
max = (x[i] > x[max] ? i : max);
return max;
}
/*************************************************************************
* These functions return the index of the minimum element in a vector
**************************************************************************/
int idxamin(int n, idxtype *x)
{
int i, min=0;
for (i=1; i<n; i++)
min = (x[i] < x[min] ? i : min);
return min;
}
/*************************************************************************
* This function sums the entries in an array
**************************************************************************/
int charsum(int n, char *x)
{
int i, sum = 0;
for (i=0; i<n; i++)
sum += x[i];
return sum;
}
/*************************************************************************
* This function sums the entries in an array
**************************************************************************/
int isum(int n, int *x)
{
int i, sum = 0;
for (i=0; i<n; i++)
sum += x[i];
return sum;
}
/*************************************************************************
* This function sums the entries in an array
**************************************************************************/
int idxsum(int n, idxtype *x)
{
int i, sum = 0;
for (i=0; i<n; i++)
sum += x[i];
return sum;
}
/*************************************************************************
* This function computes a 2-norm
**************************************************************************/
float snorm2(int n, float *v)
{
int i;
float partial = 0;
for (i = 0; i<n; i++)
partial += v[i] * v[i];
return sqrt(partial);
}
/*************************************************************************
* This function computes a 2-norm
**************************************************************************/
float sdot(int n, float *x, float *y)
{
int i;
float partial = 0;
for (i = 0; i<n; i++)
partial += x[i] * y[i];
return partial;
}
/*************************************************************************
* This function computes a 2-norm
**************************************************************************/
void saxpy(int n, float alpha, float *x, float *y)
{
int i;
for (i=0; i<n; i++)
y[i] += alpha*x[i];
}
/*************************************************************************
* This function sorts an array of type KeyValueType in increasing order
**************************************************************************/
void ikeyvalsort_org(int n, KeyValueType *nodes)
{
qsort((void *)nodes, (size_t)n, (size_t)sizeof(KeyValueType), IncKeyValueCmp);
}
/*************************************************************************
* This function compares 2 KeyValueType variables for sorting in inc order
**************************************************************************/
int IncKeyValueCmp(const void *v1, const void *v2)
{
KeyValueType *n1, *n2;
n1 = (KeyValueType *)v1;
n2 = (KeyValueType *)v2;
return (n1->key != n2->key ? n1->key - n2->key : n1->val - n2->val);
}
/*************************************************************************
* This function sorts an array of type KeyValueType in increasing order
**************************************************************************/
void dkeyvalsort(int n, KeyValueType *nodes)
{
qsort((void *)nodes, (size_t)n, (size_t)sizeof(KeyValueType), DecKeyValueCmp);
}
/*************************************************************************
* This function compares 2 KeyValueType variables for sorting in inc order
**************************************************************************/
int DecKeyValueCmp(const void *v1, const void *v2)
{
KeyValueType *n1, *n2;
n1 = (KeyValueType *)v1;
n2 = (KeyValueType *)v2;
return n2->key - n1->key;
}
/*************************************************************************
* This function does a binary search on an array for a key and returns
* the index
**************************************************************************/
int BSearch(int n, idxtype *array, int key)
{
int a=0, b=n, c;
while (b-a > 8) {
c = (a+b)>>1;
if (array[c] > key)
b = c;
else
a = c;
}
for (c=a; c<b; c++) {
if (array[c] == key)
return c;
}
errexit("Key %d not found!\n", key);
}
/*************************************************************************
* This file randomly permutes the contents of an array.
* flag == 0, don't initialize perm
* flag == 1, set p[i] = i
**************************************************************************/
void RandomPermute(int n, idxtype *p, int flag)
{
int i, u, v;
idxtype tmp;
if (flag == 1) {
for (i=0; i<n; i++)
p[i] = i;
}
for (i=0; i<n; i++) {
v = RandomInRange(n);
u = RandomInRange(n);
SWAP(p[v], p[u], tmp);
}
}
/*************************************************************************
* This file randomly permutes the contents of an array.
* flag == 0, don't initialize perm
* flag == 1, set p[i] = i
**************************************************************************/
void FastRandomPermute(int n, idxtype *p, int flag)
{
int i, u, v;
idxtype tmp;
if (flag == 1) {
for (i=0; i<n; i++)
p[i] = i;
}
for (i=0; i<n; i+=8) {
v = RandomInRange(n-4);
u = RandomInRange(n-4);
SWAP(p[v], p[u], tmp);
SWAP(p[v+1], p[u+1], tmp);
SWAP(p[v+2], p[u+2], tmp);
SWAP(p[v+3], p[u+3], tmp);
}
}
/*************************************************************************
* This function returns true if the a is a power of 2
**************************************************************************/
int ispow2(int a)
{
for (; a%2 != 1; a = a>>1);
return (a > 1 ? 0 : 1);
}
/*************************************************************************
* This function returns the log2(x)
**************************************************************************/
int log2(int a)
{
int i;
for (i=1; a > 1; i++, a = a>>1);
return i-1;
}

View File

@ -1,35 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* var.c
*
* This file contains routines related to armetis
*
* Irene
*/
#include "parmetis.h"
/*************************************************************************
* This function changes the weights of interface edges
**************************************************************************/
void ChangeWeights(int nvtxs, idxtype *vtxdist, idxtype *xadj, idxtype *adjncy,
realtype *adjwgt, MPI_Comm comm)
{
int i, j, k, mype;
int firstvtx, lastvtx;
MPI_Comm_rank(comm, &mype);
firstvtx = vtxdist[mype];
lastvtx = vtxdist[mype+1];
for (i=0; i<nvtxs; i++) {
for (j=xadj[i]; j<xadj[i+1]; j++) {
k = adjncy[j];
if (k<firstvtx || k>=lastvtx)
adjwgt[j] *= 10; /* PLAY HERE !! */
}
}
}

View File

@ -1,16 +0,0 @@
include ../Makefile.in
default:
(cd IMParMetis-2.0 ; $(make) )
(cd ParLib ; $(make) )
(cd Programs ; $(make) )
clean:
(cd IMParMetis-2.0 ; $(make) clean )
(cd ParLib ; $(make) clean )
(cd Programs ; $(make) clean )
realclean:
(cd IMParMetis-2.0 ; $(make) realclean )
(cd ParLib ; $(make) realclean )
(cd Programs ; $(make) realclean )

View File

@ -1,11 +0,0 @@
comm.c
debug.c
grsetup.c
ikeysort.c
memory.c
move.c
parmgridgen.c
setup.c
util.c
LIB = $(FOAM_LIBBIN)/libParMGridGen

View File

@ -1,9 +0,0 @@
TYPE_REAL=
#if defined(SP)
TYPE_REAL=-DTYPE_REAL
#endif
include $(RULES)/mplib$(WM_MPLIB)
EXE_INC = -I../../MGridGen/IMlib $(PFLAGS) $(PINC) $(TYPE_REAL)
LIB_LIBS = -lIMlib -lParMETISLib $(PLIBS)

View File

@ -1,43 +0,0 @@
include ../../Makefile.in
DEBUGFLAGS =
ifeq ($(ddmalloc),yes)
INCDIR := $(INCDIR) -I$(DMALLOCDIR)/include
DEBUGFLAGS := $(DEBUGFLAGS) -DDMALLOC -DDEBUG
OPTFLAGS = -g
endif
ifeq ($(dmalloc),yes)
INCDIR := $(INCDIR) -I$(DMALLOCDIR)/include
DEBUGFLAGS := $(DEBUGFLAGS) -DDMALLOC
endif
ifeq ($(debug),yes)
DEBUGFLAGS := $(DEBUGFLAGS) -DDEBUG
OPTFLAGS = -g
endif
INCLUDES = -I./ -I$(IMLIBDIR) $(INCDIR)
CFLAGS = $(COPTIONS) $(OPTFLAGS) $(DEBUGFLAGS) $(INCLUDES)
OBJS = comm.o util.o memory.o debug.o setup.o parmgridgen.o grsetup.o move.o \
ikeysort.o
IPARMETISOBJS = fused.o comm.o util.o memory.o debug.o setup.o diffuse.o grsetup.o timer.o \
coarsen.o edge_refine.o drivers.o remap.o iidxsort.o ikeysort.o var.o
IMPARMETISOBJS = $(addprefix ../IMParMetis-2.0/ParMETISLib/, $(IPARMETISOBJS))
.c.o:
$(PARCC) $(CFLAGS) -c $*.c
../../libparmgrid.a: $(OBJS) $(IMPARMETISOBJS)
$(AR) $@ $(OBJS) $(IMPARMETISOBJS)
$(RANLIB) $@
clean:
rm -f *.o
realclean:
rm -f *.o ; rm -f ../../libparmgrid.a

View File

@ -1,181 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* comm.c
*
* This function provides various high level communication functions
*
* George Irene
*/
#include "parmgridgen.h"
/*************************************************************************
* This function performs the gather/scatter for the boundary vertices
**************************************************************************/
void MGridCommInterfaceData(MGridCtrlType *ctrl, MGridGraphType *graph, idxtype *data,
idxtype *sendvector, idxtype *recvvector)
{
int i, k, nnbrs, firstvtx;
idxtype *peind, *sendptr, *sendind, *recvptr;
firstvtx = graph->vtxdist[ctrl->mype];
nnbrs = graph->nnbrs;
peind = graph->peind;
sendptr = graph->sendptr;
sendind = graph->sendind;
recvptr = graph->recvptr;
/* Issue the receives first */
for (i=0; i<nnbrs; i++) {
MPI_Irecv((void *)(recvvector+recvptr[i]), recvptr[i+1]-recvptr[i], IDX_DATATYPE,
peind[i], 1, ctrl->comm, ctrl->rreq+i);
}
/* Issue the sends next */
k = sendptr[nnbrs];
for (i=0; i<k; i++)
sendvector[i] = data[sendind[i]-firstvtx];
for (i=0; i<nnbrs; i++) {
MPI_Isend((void *)(sendvector+sendptr[i]), sendptr[i+1]-sendptr[i], IDX_DATATYPE,
peind[i], 1, ctrl->comm, ctrl->sreq+i);
}
/* OK, now get into the loop waiting for the operations to finish */
MPI_Waitall(nnbrs, ctrl->rreq, ctrl->statuses);
MPI_Waitall(nnbrs, ctrl->sreq, ctrl->statuses);
}
/*************************************************************************
* This function performs the gather/scatter for the boundary vertices
**************************************************************************/
void MGridCommChangedInterfaceData(MGridCtrlType *ctrl, MGridGraphType *graph,
int nchanged, idxtype *changed, idxtype *data,
KeyValueType *sendpairs, KeyValueType *recvpairs, idxtype *psendptr)
{
int i, j, k, n, penum, nnbrs;
idxtype *peind, *sendptr, *recvptr, *pexadj, *peadjncy, *peadjloc;
KeyValueType *pairs;
nnbrs = graph->nnbrs;
peind = graph->peind;
sendptr = graph->sendptr;
recvptr = graph->recvptr;
pexadj = graph->pexadj;
peadjncy = graph->peadjncy;
peadjloc = graph->peadjloc;
/* Issue the receives first */
for (i=0; i<nnbrs; i++) {
MPI_Irecv((void *)(recvpairs+recvptr[i]), 2*(recvptr[i+1]-recvptr[i]), IDX_DATATYPE,
peind[i], 1, ctrl->comm, ctrl->rreq+i);
}
if (nchanged != 0) {
idxcopy(ctrl->npes, sendptr, psendptr);
/* Copy the changed values into the sendvector */
for (i=0; i<nchanged; i++) {
j = changed[i];
for (k=pexadj[j]; k<pexadj[j+1]; k++) {
penum = peadjncy[k];
sendpairs[psendptr[penum]].key = peadjloc[k];
sendpairs[psendptr[penum]].val = data[j];
psendptr[penum]++;
}
}
for (i=0; i<nnbrs; i++) {
MPI_Isend((void *)(sendpairs+sendptr[i]), 2*(psendptr[i]-sendptr[i]), IDX_DATATYPE,
peind[i], 1, ctrl->comm, ctrl->sreq+i);
}
}
else {
for (i=0; i<nnbrs; i++)
MPI_Isend((void *)(sendpairs), 0, IDX_DATATYPE, peind[i], 1, ctrl->comm, ctrl->sreq+i);
}
/* OK, now get into the loop waiting for the operations to finish */
for (i=0; i<nnbrs; i++) {
MPI_Wait(ctrl->rreq+i, &(ctrl->status));
MPI_Get_count(&ctrl->status, IDX_DATATYPE, &n);
if (n != 0) {
n = n/2;
pairs = recvpairs+graph->recvptr[i];
for (k=0; k<n; k++)
data[pairs[k].key] = pairs[k].val;
}
}
MPI_Waitall(nnbrs, ctrl->sreq, ctrl->statuses);
}
/*************************************************************************
* This function computes the max of a single element
**************************************************************************/
int MGridGlobalSEMax(MGridCtrlType *ctrl, int value)
{
int max;
MPI_Allreduce((void *)&value, (void *)&max, 1, MPI_INT, MPI_MAX, ctrl->comm);
return max;
}
/*************************************************************************
* This function computes the max of a single element
**************************************************************************/
double MGridGlobalSEMaxDouble(MGridCtrlType *ctrl, double value)
{
double max;
MPI_Allreduce((void *)&value, (void *)&max, 1, MPI_DOUBLE, MPI_MAX, ctrl->comm);
return max;
}
/*************************************************************************
* This function computes the max of a single element
**************************************************************************/
int MGridGlobalSEMin(MGridCtrlType *ctrl, int value)
{
int min;
MPI_Allreduce((void *)&value, (void *)&min, 1, MPI_INT, MPI_MIN, ctrl->comm);
return min;
}
/*************************************************************************
* This function computes the max of a single element
**************************************************************************/
int MGridGlobalSESum(MGridCtrlType *ctrl, int value)
{
int sum;
MPI_Allreduce((void *)&value, (void *)&sum, 1, MPI_INT, MPI_SUM, ctrl->comm);
return sum;
}
/*************************************************************************
* This function computes the max of a single element
**************************************************************************/
realtype MGridGlobalSESumReal(MGridCtrlType *ctrl, realtype value)
{
realtype sum;
MPI_Allreduce((void *)&value, (void *)&sum, 1, REAL_DATATYPE, MPI_SUM, ctrl->comm);
return sum;
}

View File

@ -1,118 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* debug.c
*
* This file contains various functions that are used to display debuging
* information
*
* George Irene
*/
#include "parmgridgen.h"
/*************************************************************************
* This function prints the local portion of the graph stored at each
* processor
**************************************************************************/
void PrintGraph(MGridCtrlType *ctrl, MGridGraphType *graph)
{
int i, j, penum;
int firstvtx;
MPI_Barrier(ctrl->comm);
firstvtx = graph->vtxdist[ctrl->mype];
for (penum=0; penum<ctrl->npes; penum++) {
if (ctrl->mype == penum) {
printf("\t%d", penum);
for (i=0; i<graph->nvtxs; i++) {
if (i==0)
printf("\t%2d %2d\t", firstvtx+i, graph->vwgt[i]);
else
printf("\t\t%2d %2d\t", firstvtx+i, graph->vwgt[i]);
for (j=graph->xadj[i]; j<graph->xadj[i+1]; j++)
printf("[%d %f] ", graph->adjncy[j], graph->adjwgt[j]);
printf("\n");
}
fflush(stdout);
}
MPI_Barrier(ctrl->comm);
}
}
/*************************************************************************
* This function prints the local portion of the graph stored at each
* processor along with degree information during refinement
**************************************************************************/
void PrintGraph2(MGridCtrlType *ctrl, MGridGraphType *graph)
{
int i, j, penum;
int firstvtx;
MPI_Barrier(ctrl->comm);
firstvtx = graph->vtxdist[ctrl->mype];
for (penum=0; penum<ctrl->npes; penum++) {
if (ctrl->mype == penum) {
printf("\t%d", penum);
for (i=0; i<graph->nvtxs; i++) {
if (i==0)
printf("\t%2d %2d [%d %f %f]\t", firstvtx+i, graph->vwgt[i], graph->where[i], graph->rinfo[i].id, graph->rinfo[i].ed);
else
printf("\t\t%2d %2d [%d %f %f]\t", firstvtx+i, graph->vwgt[i], graph->where[i], graph->rinfo[i].id, graph->rinfo[i].ed);
for (j=graph->xadj[i]; j<graph->xadj[i+1]; j++)
printf("[%d %f] ", graph->adjncy[j], graph->adjwgt[j]);
printf("\n");
}
fflush(stdout);
}
MPI_Barrier(ctrl->comm);
}
}
/*************************************************************************
* This function writes a graph in the format used by serial METIS
**************************************************************************/
void WriteMetisGraph(int nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, realtype *adjwgt)
{
int i, j;
FILE *fp;
fp = fopen("test.graph", "w");
fprintf(fp, "%d %d 11", nvtxs, xadj[nvtxs]/2);
for (i=0; i<nvtxs; i++) {
fprintf(fp, "\n%d ", vwgt[i]);
for (j=xadj[i]; j<xadj[i+1]; j++)
fprintf(fp, " %d %f", adjncy[j]+1, adjwgt[j]);
}
fclose(fp);
}
void WriteMetisGraph2(int nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, realtype *adjwgt, MPI_Comm comm)
{
int i, j;
int mype, npes;
char filename[20];
FILE *fp;
MPI_Comm_size(comm, &npes);
MPI_Comm_rank(comm, &mype);
sprintf(filename,"test.graph%d.%d",npes,mype);
fp = fopen(filename, "w");
fprintf(fp, "%d %d", nvtxs, xadj[nvtxs]/2);
for (i=0; i<nvtxs; i++) {
fprintf(fp, "\n%d ", vwgt[i]);
for (j=xadj[i]; j<xadj[i+1]; j++)
fprintf(fp, " %d %f", adjncy[j]+1, adjwgt[j]);
}
fclose(fp);
}

View File

@ -1,73 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* defs.h
*
* This file contains constant definitions
*
* George Irene
*/
#define MAXLINE 1280000
/* CType Schemes */
#define MATCH_RM 1
#define MATCH_HEM 2
#define MATCH_HEM_SLOW 3
#define MATCH_HEM_TRUE 4
/* RType Schemes */
#define REFINE_AR 1
#define REFINE_WAR 2
#define REFINE_SCUT 3
#define REFINE_MINMAXAVAR 4
#define REFINE_MINMAXAR 5
#define REFINE_MULTIOBJECTIVE 6
#define REFINE_MULTIOBJECTIVE2 7
#define NGD_PASSES 20
/* Meaning of various options[] parameters 3-6 */
#define OPTION_DBGLVL 2
#define OPTION_CTYPE 0
#define OPTION_RTYPE 1
#define OPTION_DIM 3
#define XYZ_XCOORD 1
#define XYZ_SPFILL 2
/* Type of initial vertex separator algorithms */
#define ISEP_EDGE 1
#define ISEP_NODE 2
#define UNMATCHED -1
#define MAYBE_MATCHED -2
#define TOO_HEAVY -3
#define MAX_PES 8192
#define MAX_INT (1<<30)
#define HTABLE_EMPTY -1
#define NGR_PASSES 4 /* Number of greedy refinement passes */
#define NLGR_PASSES 5 /* Number of GR refinement during IPartition */
#define IGNORE_FRACTION 0.9 /* What fraction of vertices will not be colored */
#define KEEP_BIT (idxtype)536870912 /* 1<<29 */
#define UNBALANCE_FRACTION 1.05
#define ORDER_UNBALANCE_FRACTION 1.05
#define MAXVWGT_FACTOR 1.4
#define MATCH_LOCAL 1
#define MATCH_GLOBAL 2
#define EDGE_WEIGHT 1
#define NOEDGE_WEIGHT 2
/* Debug Levels */
#define DBG_TRACK 128 /* Track flow of program Irene Debugging */
#define DBG_STEPS 256 /* Track convergence through iterations */

View File

@ -1,192 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* grsetup.c
*
* This file contain various graph setting up routines
*
* George Irene
*/
#include "parmgridgen.h"
/*************************************************************************
* This function setsup the GraphType structure
**************************************************************************/
MGridGraphType *SetUpMGridGraph(MGridCtrlType *ctrl, idxtype *vtxdist, idxtype *xadj, realtype *vvol,
realtype *vsurf, idxtype *adjncy, realtype *adjwgt)
{
int i, j;
MGridGraphType *graph;
graph = CreateMGridGraph();
graph->gnvtxs = vtxdist[ctrl->npes];
graph->nvtxs = vtxdist[ctrl->mype+1]-vtxdist[ctrl->mype];
graph->nedges = xadj[graph->nvtxs];
graph->vtxdist = vtxdist;
graph->xadj = xadj;
graph->vvol = vvol;
graph->vsurf = vsurf;
graph->adjncy = adjncy;
graph->adjwgt = adjwgt;
graph->vwgt = idxsmalloc(graph->nvtxs, 1, "SetUpMGridGraph: vwgt");
graph->adjwgtsum = realsmalloc(graph->nvtxs, 0.0, "adjwgtsum");
for (i=0; i<graph->nvtxs; i++)
for (j=xadj[i]; j<xadj[i+1]; j++)
graph->adjwgtsum[i] += adjwgt[j];
/* tvwgt = MGridGlobalSESum(ctrl, MGrididxsum(graph->nvtxs, graph->vwgt)); */
return graph;
}
/*************************************************************************
* This function setsup the CtrlType structure
**************************************************************************/
void SetUpMGridCtrl(MGridCtrlType *ctrl, int minsize, int maxsize, int *options, MPI_Comm comm)
{
MPI_Comm_dup(comm, &(ctrl->gcomm));
MPI_Comm_rank(ctrl->gcomm, &ctrl->mype);
MPI_Comm_size(ctrl->gcomm, &ctrl->npes);
ctrl->minsize = minsize;
ctrl->maxsize = maxsize;
ctrl->CType = options[OPTION_CTYPE];
ctrl->RType = options[OPTION_RTYPE];
ctrl->dbglvl = options[OPTION_DBGLVL];
ctrl->comm = ctrl->gcomm;
srand(ctrl->mype);
srand48(ctrl->mype);
}
/*************************************************************************
* This function changes the numbering from 1 to 0 or 0 to 1
**************************************************************************/
void ChangeNumbering(idxtype *vtxdist, idxtype *xadj, idxtype *adjncy, idxtype *part, int npes, int mype, int from)
{
int i, nvtxs, nedges;
if (from == 1) { /* Change it from 1 to 0 */
for (i=0; i<npes+1; i++)
vtxdist[i]--;
nvtxs = vtxdist[mype+1]-vtxdist[mype];
for (i=0; i<nvtxs+1; i++)
xadj[i]--;
nedges = xadj[nvtxs];
for (i=0; i<nedges; i++)
adjncy[i]--;
}
else { /* Change it from 0 to 1 */
nvtxs = vtxdist[mype+1]-vtxdist[mype];
nedges = xadj[nvtxs];
for (i=0; i<npes+1; i++)
vtxdist[i]++;
for (i=0; i<nvtxs+1; i++)
xadj[i]++;
for (i=0; i<nedges; i++)
adjncy[i]++;
for (i=0; i<nvtxs; i++)
part[i]++;
}
}
/*************************************************************************
* This function removes outside edges and makes graph purely local
**************************************************************************/
void RemoveEdges(idxtype *vtxdist, idxtype *xadj, idxtype *adjncy,
realtype *adjwgt, idxtype *newxadj, idxtype *newadjncy,
realtype *newadjwgt, MPI_Comm comm)
{
int i, j, k, l, mype;
int firstvtx, lastvtx, nvtxs;
MPI_Comm_rank(comm, &mype);
firstvtx = vtxdist[mype];
lastvtx = vtxdist[mype+1];
nvtxs = lastvtx - firstvtx;
for (newxadj[0]=0, l=0, i=0; i<nvtxs; i++) {
for (j=xadj[i]; j<xadj[i+1]; j++) {
k = adjncy[j];
if (k>=firstvtx && k<lastvtx) {
newadjncy[l] = k-firstvtx;
newadjwgt[l++] = adjwgt[j];
}
}
newxadj[i+1]=l;
}
}
/*************************************************************************
* This function corrects surface edges (vsurf)
**************************************************************************/
void CorrectSurfaceEdges(idxtype *vtxdist, idxtype *xadj, idxtype *adjncy,
realtype *adjwgt, realtype *vsurf, MPI_Comm comm)
{
int i, j, k, mype;
int firstvtx, lastvtx, nvtxs;
MPI_Comm_rank(comm, &mype);
firstvtx = vtxdist[mype];
lastvtx = vtxdist[mype+1];
nvtxs = lastvtx - firstvtx;
for (i=0; i<nvtxs; i++) {
for (j=xadj[i]; j<xadj[i+1]; j++) {
k = adjncy[j];
if (k<firstvtx || k>=lastvtx)
vsurf[i] += adjwgt[j];
}
}
}
/*************************************************************************
* This function removes outside edges and corrects surface edges (vsurf)
**************************************************************************/
void RemoveCorrectSurfaceEdges(idxtype *vtxdist, idxtype *xadj, idxtype *adjncy,
realtype *adjwgt, idxtype *newxadj, idxtype *newadjncy,
realtype *newadjwgt, realtype *newvsurf, MPI_Comm comm)
{
int i, j, k, l, mype;
int firstvtx, lastvtx, nvtxs;
MPI_Comm_rank(comm, &mype);
firstvtx = vtxdist[mype];
lastvtx = vtxdist[mype+1];
nvtxs = lastvtx - firstvtx;
for (newxadj[0]=0, l=0, i=0; i<nvtxs; i++) {
for (j=xadj[i]; j<xadj[i+1]; j++) {
k = adjncy[j];
if (k>=firstvtx && k<lastvtx) {
newadjncy[l] = k-firstvtx;
newadjwgt[l++] = adjwgt[j];
}
else
newvsurf[i] += adjwgt[j];
}
newxadj[i+1]=l;
}
}

View File

@ -1,151 +0,0 @@
#include "parmgridgen.h"
/* Byte-wise swap two items of size SIZE. */
#define QSSWAP(a, b, stmp) do { stmp = (a); (a) = (b); (b) = stmp; } while (0)
/* Discontinue quicksort algorithm when partition gets below this size.
This particular magic number was chosen to work best on a Sun 4/260. */
#define MAX_THRESH 20
/* Stack node declarations used to store unfulfilled partition obligations. */
typedef struct {
KeyValueType *lo;
KeyValueType *hi;
} stack_node;
/* The next 4 #defines implement a very fast in-line stack abstraction. */
#define STACK_SIZE (8 * sizeof(unsigned long int))
#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
#define STACK_NOT_EMPTY (stack < top)
void ikeysort(int total_elems, KeyValueType *pbase)
{
KeyValueType pivot, stmp;
if (total_elems == 0)
/* Avoid lossage with unsigned arithmetic below. */
return;
if (total_elems > MAX_THRESH) {
KeyValueType *lo = pbase;
KeyValueType *hi = &lo[total_elems - 1];
stack_node stack[STACK_SIZE]; /* Largest size needed for 32-bit int!!! */
stack_node *top = stack + 1;
while (STACK_NOT_EMPTY) {
KeyValueType *left_ptr;
KeyValueType *right_ptr;
KeyValueType *mid = lo + ((hi - lo) >> 1);
if (mid->key < lo->key)
QSSWAP(*mid, *lo, stmp);
if (hi->key < mid->key)
QSSWAP(*mid, *hi, stmp);
else
goto jump_over;
if (mid->key < lo->key)
QSSWAP(*mid, *lo, stmp);
jump_over:;
pivot = *mid;
left_ptr = lo + 1;
right_ptr = hi - 1;
/* Here's the famous ``collapse the walls'' section of quicksort.
Gotta like those tight inner loops! They are the main reason
that this algorithm runs much faster than others. */
do {
while (left_ptr->key < pivot.key)
left_ptr++;
while (pivot.key < right_ptr->key)
right_ptr--;
if (left_ptr < right_ptr) {
QSSWAP (*left_ptr, *right_ptr, stmp);
left_ptr++;
right_ptr--;
}
else if (left_ptr == right_ptr) {
left_ptr++;
right_ptr--;
break;
}
} while (left_ptr <= right_ptr);
/* Set up pointers for next iteration. First determine whether
left and right partitions are below the threshold size. If so,
ignore one or both. Otherwise, push the larger partition's
bounds on the stack and continue sorting the smaller one. */
if ((size_t) (right_ptr - lo) <= MAX_THRESH) {
if ((size_t) (hi - left_ptr) <= MAX_THRESH)
/* Ignore both small partitions. */
POP (lo, hi);
else
/* Ignore small left partition. */
lo = left_ptr;
}
else if ((size_t) (hi - left_ptr) <= MAX_THRESH)
/* Ignore small right partition. */
hi = right_ptr;
else if ((right_ptr - lo) > (hi - left_ptr)) {
/* Push larger left partition indices. */
PUSH (lo, right_ptr);
lo = left_ptr;
}
else {
/* Push larger right partition indices. */
PUSH (left_ptr, hi);
hi = right_ptr;
}
}
}
/* Once the BASE_PTR array is partially sorted by quicksort the rest
is completely sorted using insertion sort, since this is efficient
for partitions below MAX_THRESH size. BASE_PTR points to the beginning
of the array to sort, and END_PTR points at the very last element in
the array (*not* one beyond it!). */
{
KeyValueType *end_ptr = &pbase[total_elems - 1];
KeyValueType *tmp_ptr = pbase;
KeyValueType *thresh = (end_ptr < pbase + MAX_THRESH ? end_ptr : pbase + MAX_THRESH);
register KeyValueType *run_ptr;
/* Find smallest element in first threshold and place it at the
array's beginning. This is the smallest array element,
and the operation speeds up insertion sort's inner loop. */
for (run_ptr = tmp_ptr + 1; run_ptr <= thresh; run_ptr++)
if (run_ptr->key < tmp_ptr->key)
tmp_ptr = run_ptr;
if (tmp_ptr != pbase)
QSSWAP(*tmp_ptr, *pbase, stmp);
/* Insertion sort, running from left-hand-side up to right-hand-side. */
run_ptr = pbase + 1;
while (++run_ptr <= end_ptr) {
tmp_ptr = run_ptr - 1;
while (run_ptr->key < tmp_ptr->key)
tmp_ptr--;
tmp_ptr++;
if (tmp_ptr != run_ptr) {
KeyValueType elmnt = *run_ptr;
KeyValueType *mptr;
for (mptr=run_ptr; mptr>tmp_ptr; mptr--)
*mptr = *(mptr-1);
*mptr = elmnt;
}
}
}
}

View File

@ -1,106 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* macros.h
*
* This file contains macros used in multilevel
*
* George Irene
*/
/*************************************************************************
* This macro is used to normalize the weights of two nodes
**************************************************************************/
#define ARATIO1(dim, surf, vol) ((dim == 2) ? (pow((surf), 2)/(vol)) : (pow((surf), 1.5)/(vol)))
#define ARATIO(dim, surf, vol) ((dim == 2) ? ((surf)*(surf)/(vol)) : (sqrt((surf)*(surf)*(surf))/(vol)))
#define ARATIO2(dim, surf, vol) ((dim == 2) ? ((surf)*(surf)*(surf)*(surf)/(vol)*(vol)) : ((surf)*(surf)*(surf)/((vol)*(vol))))
/*************************************************************************
* The following macro returns a random number in the specified range
**************************************************************************/
#define RandomInRange(u) ((int)(drand48()*((double)(u))))
#define amax(a, b) ((a) >= (b) ? (a) : (b))
#define amin(a, b) ((a) >= (b) ? (b) : (a))
#define AND(a, b) ((a) < 0 ? ((-(a))&(b)) : ((a)&(b)))
#define OR(a, b) ((a) < 0 ? -((-(a))|(b)) : ((a)|(b)))
#define XOR(a, b) ((a) < 0 ? -((-(a))^(b)) : ((a)^(b)))
#define SWAP(a, b, tmp) \
do {(tmp) = (a); (a) = (b); (b) = (tmp);} while(0)
#define INC_DEC(a, b, val) \
do {(a) += (val); (b) -= (val);} while(0)
#define HASHFCT(key, size) ((key)%(size))
/*************************************************************************
* Timer macros
**************************************************************************/
#undef cleartimer
#undef starttimer
#undef stoptimer
#undef gettimer
#define cleartimer(tmr) (tmr = 0.0)
#define starttimer(tmr) (tmr -= MPI_Wtime())
#define stoptimer(tmr) (tmr += MPI_Wtime())
#define gettimer(tmr) (tmr)
/*************************************************************************
* This macro is used to handle dbglvl
**************************************************************************/
#define IFSET(a, flag, cmd) if ((a)&(flag)) (cmd);
#undef ASSERT
#undef ASSERTP
#ifdef DEBUG
# define ASSERT(ctrl, expr) \
if (!(expr)) { \
MGridmyprintf(ctrl, "***ASSERTION failed on line %d of file %s: " #expr "\n", \
__LINE__, __FILE__); \
abort(); \
}
#else
# define ASSERT(ctrl, expr) ;
#endif
#ifdef DEBUG
# define ASSERTP(ctrl, expr,msg) \
if (!(expr)) { \
MGridmyprintf(ctrl, "***ASSERTION failed on line %d of file %s:" #expr "\n", \
__LINE__, __FILE__); \
MGridmyprintf msg ; \
abort(); \
}
#else
# define ASSERTP(ctrl, expr,msg) ;
#endif
#ifdef DEBUGS
# define ASSERTS(expr) \
if (!(expr)) { \
printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \
__LINE__, __FILE__); \
abort(); \
}
#else
# define ASSERTS(expr) ;
#endif
#ifdef DEBUGS
# define ASSERTSP(expr, msg) \
if (!(expr)) { \
printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \
__LINE__, __FILE__); \
printf msg ; \
abort(); \
}
#else
# define ASSERTSP(expr, msg) ;
#endif

View File

@ -1,205 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* memory.c
*
* This file contains routines that deal with memory allocation
*
* George Irene
*/
#include "parmgridgen.h"
/*************************************************************************
* This function allocate various pools of memory
**************************************************************************/
void PreAllocateMGridMemory(MGridCtrlType *ctrl, MGridGraphType *graph, MGridWorkSpaceType *wspace)
{
wspace->nlarge = 2*graph->nedges;
/* pairs : 2*nedges. KeyValueType: 2*idxtype. So 4*nedges(idxtype) */
/* indices: 2*nedges. So 2*nedges(idxtype) */
/* degrees: 1*nedges. EdgeType: idxtype+realtype.So 1*nedges(idxtype)+1*nedges(realtype) */
wspace->maxcore = graph->nedges*(2*sizeof(KeyValueType) + 2*sizeof(idxtype) + sizeof(EdgeType));
wspace->core = IMmalloc(wspace->maxcore, "PreAllocateMemory: wspace->core");
wspace->pairs = (KeyValueType *)wspace->core;
wspace->indices = (idxtype *)(wspace->pairs + wspace->nlarge);
wspace->degrees = (EdgeType *)(wspace->indices + wspace->nlarge);
wspace->pv1 = idxmalloc(ctrl->npes+1, "PreAllocateMemory: wspace->pv1");
wspace->pv2 = idxmalloc(ctrl->npes+1, "PreAllocateMemory: wspace->pv2");
wspace->pv4 = idxmalloc(ctrl->npes+1, "PreAllocateMemory: wspace->pv4");
wspace->pepairs1 = (KeyValueType *)IMmalloc(sizeof(KeyValueType)*(ctrl->npes+1), "PreAllocateMemory: wspace->pepairs1");
wspace->pepairs2 = (KeyValueType *)IMmalloc(sizeof(KeyValueType)*(ctrl->npes+1), "PreAllocateMemory: wspace->pepairs2");
}
/*************************************************************************
* This function de-allocate various pools of memory
**************************************************************************/
void FreeMGridWSpace(MGridWorkSpaceType *wspace)
{
IMfree(&wspace->core,
&wspace->pv1,
&wspace->pv2,
&wspace->pv4,
&wspace->pepairs1,
&wspace->pepairs2,
LTERM);
}
/*************************************************************************
* This function de-allocates memory allocated for the control structures
**************************************************************************/
void FreeMGridCtrl(MGridCtrlType *ctrl)
{
MPI_Comm_free(&(ctrl->gcomm));
}
/*************************************************************************
* This function creates a MGridGraphType data structure and initializes
* the various fields
**************************************************************************/
MGridGraphType *CreateMGridGraph(void)
{
MGridGraphType *graph;
graph = (MGridGraphType *)IMmalloc(sizeof(MGridGraphType), "CreateMGridGraph: graph");
InitMGridGraph(graph);
return graph;
}
/*************************************************************************
* This function creates a CoarseGraphType data structure and initializes
* the various fields
**************************************************************************/
void InitMGridGraph(MGridGraphType *graph)
{
graph->gnvtxs = graph->nvtxs = graph->nedges = -1;
graph->nnbrs = graph->nrecv = graph->nsend = graph->nlocal = -1;
graph->xadj = graph->vwgt = graph->vsize = graph->adjncy = NULL;
graph->vvol = graph->vsurf = NULL;
graph->lpvol = graph->gpvol = graph->lpsurf = graph->gpsurf = NULL;
graph->adjwgt = graph->adjwgtsum = NULL;
graph->lminratio = graph->gminratio = -1.0;
graph->vtxdist = NULL;
graph->match = graph->cmap = NULL;
graph->peind = NULL;
graph->sendptr = graph->sendind = graph->recvptr = graph->recvind = NULL;
graph->imap = NULL;
graph->pexadj = graph->peadjncy = graph->peadjloc = NULL;
graph->lperm = NULL;
graph->slens = graph->rlens = NULL;
graph->rcand = NULL;
graph->glblvtxid = graph->fusedinfo = graph->where = graph->lpwgts = graph->gpwgts = NULL;
graph->rinfo = NULL;
graph->nrinfo = NULL;
}
/*************************************************************************
* This function deallocates any memory stored in a graph
**************************************************************************/
void FreeMGridGraph(MGridGraphType *graph)
{
IMfree(&graph->xadj,
&graph->vwgt,
&graph->vvol,
&graph->vsurf,
&graph->adjwgtsum,
&graph->lpvol,
&graph->gpvol,
&graph->lpsurf,
&graph->gpsurf,
&graph->vsize,
&graph->adjncy,
&graph->adjwgt,
&graph->vtxdist,
&graph->match,
&graph->cmap,
&graph->lperm,
&graph->glblvtxid,
&graph->fusedinfo,
&graph->where,
&graph->rinfo,
&graph->nrinfo,
&graph->lpwgts,
&graph->gpwgts,
&graph->peind,
&graph->sendptr,
&graph->sendind,
&graph->recvptr,
&graph->recvind,
&graph->imap,
&graph->rlens,
&graph->slens,
&graph->rcand,
&graph->pexadj,
&graph->peadjncy,
&graph->peadjloc,
LTERM);
IMfree(&graph, LTERM);
}
/*************************************************************************
* This function deallocates any memory stored in a graph
**************************************************************************/
void FreeMGridGraphContent(MGridGraphType *graph)
{
IMfree(&graph->xadj,
&graph->vwgt,
&graph->vvol,
&graph->vsurf,
&graph->adjwgtsum,
&graph->lpvol,
&graph->gpvol,
&graph->lpsurf,
&graph->gpsurf,
&graph->vsize,
&graph->adjncy,
&graph->adjwgt,
&graph->vtxdist,
&graph->match,
&graph->cmap,
&graph->lperm,
&graph->glblvtxid,
&graph->fusedinfo,
&graph->where,
&graph->rinfo,
&graph->nrinfo,
&graph->lpwgts,
&graph->gpwgts,
&graph->peind,
&graph->sendptr,
&graph->sendind,
&graph->recvptr,
&graph->recvind,
&graph->imap,
&graph->rlens,
&graph->slens,
&graph->rcand,
&graph->pexadj,
&graph->peadjncy,
&graph->peadjloc,
LTERM);
}

View File

@ -1,246 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* move.c
*
* This file contains functions that move the graph given a partition
*
* George Irene
*/
#include "parmgridgen.h"
/*************************************************************************
* This function moves the graph, and returns a new graph.
* This routine can be called with or without performing refinement.
* In the latter case it allocates and computes lpwgts itself.
**************************************************************************/
MGridGraphType *MoveMGridGraph(MGridCtrlType *ctrl, MGridGraphType *graph, MGridWorkSpaceType *wspace)
{
int i, ii, j, jj, nvtxs, nparts, maxrealcore;
idxtype *xadj, *vwgt, *adjncy, *mvtxdist, *p_d;
idxtype *where, *newlabel, *lpwgts, *gpwgts, *fusedinfo, *glblvtxid;
idxtype *sidxgraph, *ridxgraph;
realtype *adjwgt, *vvol, *vsurf;
realtype *srealgraph, *rrealgraph, *realcore;
KeyValueType *sinfo, *rinfo;
MGridGraphType *mgraph;
nparts = ctrl->nparts;
ASSERT(ctrl, nparts == ctrl->npes);
nvtxs = graph->nvtxs;
xadj = graph->xadj;
vwgt = graph->vwgt;
vvol = graph->vvol;
vsurf = graph->vsurf;
adjncy = graph->adjncy;
adjwgt = graph->adjwgt;
where = graph->where;
fusedinfo = graph->fusedinfo;
glblvtxid = graph->glblvtxid;
mvtxdist = idxmalloc(nparts+1, "MoveMGridGraph: mvtxdist");
/* Let's do a prefix scan to determine the labeling of the nodes given */
lpwgts = wspace->pv1;
gpwgts = wspace->pv2;
sinfo = wspace->pepairs1;
rinfo = wspace->pepairs2;
for (i=0; i<nparts; i++)
sinfo[i].key = sinfo[i].val = 0;
/* Here we care about the count and not total weight (diff since graph may be weighted) */
for (i=0; i<nvtxs; i++) {
ASSERTP(ctrl, where[i] >= 0 && where[i] < ctrl->npes, (ctrl, "%d %d %d\n", i, where[i], ctrl->npes) );
sinfo[where[i]].key++;
sinfo[where[i]].val += xadj[i+1]-xadj[i];
}
for (i=0; i<nparts; i++)
lpwgts[i] = sinfo[i].key;
MPI_Scan((void *)lpwgts, (void *)gpwgts, nparts, IDX_DATATYPE, MPI_SUM, ctrl->comm);
MPI_Allreduce((void *)lpwgts, (void *)mvtxdist, nparts, IDX_DATATYPE, MPI_SUM, ctrl->comm);
MAKECSR(i, nparts, mvtxdist);
/* gpwgts[i] will store the label of the first vertex for each domain in each processor */
for (i=0; i<nparts; i++)
gpwgts[i] = mvtxdist[i] + gpwgts[i] - lpwgts[i]; /* We were interested in an exclusive Scan */
newlabel = idxmalloc(nvtxs+graph->nrecv, "MoveMGridGraph: newlabel");
for (i=0; i<nvtxs; i++)
newlabel[i] = gpwgts[where[i]]++;
/* OK, now send the newlabel info to processors storing adjacent interface nodes */
MGridCommInterfaceData(ctrl, graph, newlabel, wspace->indices, newlabel+nvtxs);
/* Now lets tell everybody what and from where he will get it. Assume nparts == npes */
MPI_Alltoall((void *)sinfo, 2, IDX_DATATYPE, (void *)rinfo, 2, IDX_DATATYPE, ctrl->comm);
/* Use lpwgts and gpwgts as pointers to where data will be received and sent */
lpwgts[0] = 0; /* Send part */
gpwgts[0] = 0; /* Received part */
for (i=0; i<nparts; i++) {
lpwgts[i+1] = lpwgts[i] + 3*sinfo[i].key + sinfo[i].val;
gpwgts[i+1] = gpwgts[i] + 3*rinfo[i].key + rinfo[i].val;
}
if (lpwgts[nparts]+gpwgts[nparts] > wspace->maxcore) {
/* Adjust core memory, incase the graph was originally very memory unbalanced */
free(wspace->core);
wspace->maxcore = lpwgts[nparts]+4*gpwgts[nparts]; /* In spirit of the 8*nedges */
wspace->core = idxmalloc(wspace->maxcore, "MoveMGridGraph: wspace->core");
}
maxrealcore = (1 + sizeof(realtype)/sizeof(idxtype))*graph->nedges;
if (lpwgts[nparts]+gpwgts[nparts] > maxrealcore) {
maxrealcore = lpwgts[nparts]+4*gpwgts[nparts]; /* In spirit of the 8*nedges */
realcore = realmalloc(maxrealcore, "MoveMGridGraph: realcore");
}
else
realcore = realmalloc(maxrealcore, "PreAllocateMemory: realcore");
sidxgraph = wspace->core;
ridxgraph = wspace->core + lpwgts[nparts];
srealgraph = realcore;
rrealgraph = realcore + lpwgts[nparts];
/* Issue the receives first */
for (i=0; i<nparts; i++) {
if (rinfo[i].key > 0)
MPI_Irecv((void *)(ridxgraph+gpwgts[i]), gpwgts[i+1]-gpwgts[i], IDX_DATATYPE, i, 1, ctrl->comm, ctrl->rreq+i);
else
ASSERT(ctrl, gpwgts[i+1]-gpwgts[i] == 0);
}
/* Assemble the graph to be sent and send it */
for (i=0; i<nvtxs; i++) {
ii = lpwgts[where[i]];
sidxgraph[ii] = xadj[i+1]-xadj[i];
srealgraph[ii++] = vvol[i];
sidxgraph[ii] = vwgt[i];
srealgraph[ii++] = vsurf[i];
sidxgraph[ii] = fusedinfo[i];
/* srealgraph[ii++] = -1; */
p_d = (idxtype *) &srealgraph[ii++]; /* srealgraph[ii++] = glblvtxid[i] is NOT safe ! */
*p_d = glblvtxid[i];
for (j=xadj[i]; j<xadj[i+1]; j++) {
sidxgraph[ii] = newlabel[adjncy[j]];
srealgraph[ii++] = adjwgt[j];
}
lpwgts[where[i]] = ii;
}
for (i=nparts; i>0; i--)
lpwgts[i] = lpwgts[i-1];
lpwgts[0] = 0;
for (i=0; i<nparts; i++) {
if (sinfo[i].key > 0)
MPI_Isend((void *)(sidxgraph+lpwgts[i]), lpwgts[i+1]-lpwgts[i], IDX_DATATYPE, i, 1, ctrl->comm, ctrl->sreq+i);
else
ASSERT(ctrl, lpwgts[i+1]-lpwgts[i] == 0);
}
/*
#ifdef DMALLOC
ASSERT(ctrl, dmalloc_verify(NULL) == DMALLOC_VERIFY_NOERROR);
#endif
*/
/* Wait for the send/recv to finish */
for (i=0; i<nparts; i++) {
if (sinfo[i].key > 0)
MPI_Wait(ctrl->sreq+i, &ctrl->status);
}
for (i=0; i<nparts; i++) {
if (rinfo[i].key > 0)
MPI_Wait(ctrl->rreq+i, &ctrl->status);
}
/* Issue the receives first */
for (i=0; i<nparts; i++) {
if (rinfo[i].key > 0)
MPI_Irecv((void *)(rrealgraph+gpwgts[i]), gpwgts[i+1]-gpwgts[i], REAL_DATATYPE, i, 1, ctrl->comm, ctrl->rreq+i);
else
ASSERT(ctrl, gpwgts[i+1]-gpwgts[i] == 0);
}
for (i=0; i<nparts; i++) {
if (sinfo[i].key > 0)
MPI_Isend((void *)(srealgraph+lpwgts[i]), lpwgts[i+1]-lpwgts[i], REAL_DATATYPE, i, 1, ctrl->comm, ctrl->sreq+i);
else
ASSERT(ctrl, lpwgts[i+1]-lpwgts[i] == 0);
}
/*
#ifdef DMALLOC
ASSERT(ctrl, dmalloc_verify(NULL) == DMALLOC_VERIFY_NOERROR);
#endif
*/
/* Wait for the send/recv to finish */
for (i=0; i<nparts; i++) {
if (sinfo[i].key > 0)
MPI_Wait(ctrl->sreq+i, &ctrl->status);
}
for (i=0; i<nparts; i++) {
if (rinfo[i].key > 0)
MPI_Wait(ctrl->rreq+i, &ctrl->status);
}
/* OK, now go and put the graph into GraphType Format */
mgraph = CreateMGridGraph();
mgraph->gnvtxs = graph->gnvtxs;
mgraph->nvtxs = mgraph->nedges = 0;
for (i=0; i<nparts; i++) {
mgraph->nvtxs += rinfo[i].key;
mgraph->nedges += rinfo[i].val;
}
nvtxs = mgraph->nvtxs;
xadj = mgraph->xadj = idxmalloc(nvtxs+1, "MoveGraph: mgraph->xadj");
vwgt = mgraph->vwgt = idxmalloc(nvtxs, "MoveGraph: mgraph->vwgt");
vvol = mgraph->vvol = realmalloc(nvtxs, "MoveGraph: mgraph->vvol");
vsurf = mgraph->vsurf = realmalloc(nvtxs, "MoveGraph: mgraph->vsurf");
mgraph->adjwgtsum = realmalloc(nvtxs, "MoveGraph: mgraph->adjwgtsum");
adjncy = mgraph->adjncy = idxmalloc(mgraph->nedges, "MoveGraph: mgraph->adjncy");
adjwgt = mgraph->adjwgt = realmalloc(mgraph->nedges, "MoveGraph: mgraph->adjwgt");
fusedinfo = mgraph->fusedinfo = idxmalloc(nvtxs, "MoveGraph: mgraph->fusedinfo");
glblvtxid = mgraph->glblvtxid = idxmalloc(nvtxs, "MoveGraph: mgraph->glblvtxid");
mgraph->vtxdist = mvtxdist;
for (jj=ii=i=0; i<nvtxs; i++) {
xadj[i] = ridxgraph[ii];
vvol[i] = rrealgraph[ii++];
vwgt[i] = ridxgraph[ii];
vsurf[i] = rrealgraph[ii++];
fusedinfo[i] = ridxgraph[ii];
p_d = (idxtype *) &rrealgraph[ii++];
glblvtxid[i] = *p_d;
for (j=0; j<xadj[i]; j++) {
adjncy[jj] = ridxgraph[ii];
adjwgt[jj++] = rrealgraph[ii++];
}
}
MAKECSR(i, nvtxs, xadj);
for (i=0; i<mgraph->nvtxs; i++) {
mgraph->adjwgtsum[i] = 0.0;
for (j=xadj[i]; j<xadj[i+1]; j++)
mgraph->adjwgtsum[i] += adjwgt[j];
}
ASSERTP(ctrl, jj == mgraph->nedges, (ctrl, "%d %d\n", jj, mgraph->nedges));
ASSERTP(ctrl, ii == gpwgts[nparts], (ctrl, "%d %d %d %d %d\n", ii, gpwgts[nparts], jj, mgraph->nedges, nvtxs));
IMfree(&newlabel, &realcore, LTERM);
/* CheckMGraph(ctrl, mgraph); */
return mgraph;
}

View File

@ -1,620 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* parmgridgen.c
*
* This is the entry point of ParMETIS_AspectRatio
*
* George Irene
*/
#include "parmgridgen.h"
/***********************************************************************************
* This function is the entry point of the parallel coarse grid construction.
* This function assumes nothing about the graph distribution.
* It is the general case.
************************************************************************************/
void ParMGridGen(idxtype *vtxdist, idxtype *xadj, realtype *vvol, realtype *vsurf,
idxtype *adjncy, realtype *adjwgt, int *nparts, int minsize,
int maxsize, int *options, idxtype *part, MPI_Comm *comm)
{
int i,j;
int npes, mype;
int nmoves, nsteps, firstfvtx;
int orgnvtxs, nvtxs, nedges;
int moptions[10];
idxtype **p_glblvtxid, *glblvtxid, *fvtxdist, *perm;
idxtype *myvtxdist, *myxadj, *myadjncy, *mypart, *where;
idxtype **p_xadj, **p_adjncy, **p_part;
idxtype *orxadj, *oradjncy;
realtype *myvvol, *myvsurf, *myadjwgt;
realtype **p_vvol, **p_vsurf, **p_adjwgt;
realtype *oradjwgt, *orvsurf;
MGridCtrlType ctrl;
MGridGraphType *graph, *mgraph;
MGridWorkSpaceType wspace;
double tmr1;
MPI_Comm_size(*comm, &npes);
MPI_Comm_rank(*comm, &mype);
IFSET(options[OPTION_DBGLVL], DBG_STEPS, printf("---------------- CYCLE 0 ----------------\n"));
orgnvtxs = nvtxs = vtxdist[mype+1]-vtxdist[mype];
nedges = xadj[nvtxs];
/* Create my own copy of the graph, so that the original can be returned intact */
myvtxdist= idxmalloc(npes+1, "ParMGridGen: myvtxdist");
myxadj = idxmalloc(nvtxs+1, "ParMGridGen: myxadj");
myvvol = realmalloc(nvtxs, "ParMGridGen: myvvol");
myvsurf = realmalloc(nvtxs, "ParMGridGen: myvsurf");
myadjncy = idxmalloc(nedges, "ParMGridGen: myadjncy");
myadjwgt = realmalloc(nedges, "ParMGridGen: myadjwgt");
mypart = idxmalloc(nvtxs, "ParMGridGen: mypart");
idxcopy(npes+1, vtxdist, myvtxdist);
idxcopy(nvtxs+1, xadj, myxadj);
realcopy(nvtxs, vvol, myvvol);
realcopy(nvtxs, vsurf, myvsurf);
idxcopy(nedges, adjncy, myadjncy);
realcopy(nedges, adjwgt, myadjwgt);
p_xadj = &myxadj;
p_vvol = &myvvol;
p_vsurf = &myvsurf;
p_adjncy = &myadjncy;
p_adjwgt = &myadjwgt;
p_part = &mypart;
/*
if (*numflag == 1)
ChangeNumbering(myvtxdist, myxadj, myadjncy, mypart, npes, mype, 1);
*/
/* Keep a copy of the initial graph. */
/* I will need those twice in the next step when it will have been ruined */
orxadj = idxmalloc(nvtxs+1, "ParMGridGen: orxadj");
oradjncy = idxmalloc(nedges, "ParMGridGen: oradjncy");
oradjwgt = realmalloc(nedges, "ParMGridGen: oradjwgt");
orvsurf = realmalloc(nvtxs, "ParMGridGen: orvsurf");
idxcopy(nvtxs+1, myxadj, orxadj);
idxcopy(nedges, myadjncy, oradjncy);
realcopy(nedges, myadjwgt, oradjwgt);
realcopy(nvtxs, myvsurf, orvsurf);
glblvtxid = idxmalloc(nvtxs, "ParMGridGen: glblvtxid");
for (j=0, i=myvtxdist[mype]; i<myvtxdist[mype+1]; i++)
glblvtxid[j++]=i;
p_glblvtxid = &glblvtxid;
/* Create purely local graph by removing edges and correcting vsurf */
RemoveCorrectSurfaceEdges(myvtxdist, myxadj, myadjncy, myadjwgt, orxadj,
oradjncy, oradjwgt, orvsurf, *comm);
/* Call MGridGen to do the partitioning */
moptions[OPTION_CTYPE]=options[OPTION_CTYPE];
moptions[OPTION_RTYPE]=options[OPTION_RTYPE];
if ( options[OPTION_DBGLVL] == DBG_STEPS )
moptions[OPTION_DBGLVL]=DBG_TRACK;
else if ( options[OPTION_DBGLVL] == DBG_TRACK )
moptions[OPTION_DBGLVL]=0;
else
moptions[OPTION_DBGLVL]=options[OPTION_DBGLVL];
moptions[OPTION_DIM]=options[OPTION_DIM];
/*
cleartimer(tmr1);
starttimer(tmr1);
*/
MGridGen(nvtxs, orxadj, myvvol, orvsurf, oradjncy, oradjwgt, minsize, maxsize,
moptions, &nmoves, nparts, mypart);
/*
stoptimer(tmr1);
printf("MGridGen Time: %lf\n", gettimer(tmr1));
*/
IMfree(&orxadj, &oradjncy, &oradjwgt, &orvsurf, LTERM);
IFSET(options[OPTION_DBGLVL], DBG_STEPS, printf("%d END OF CYCLE 0 : MGridGen nparts=%d\n",mype, *nparts));
/* Move graph around and refine for #nsteps steps */
/*
cleartimer(tmr1);
starttimer(tmr1);
*/
nsteps = 3;
MoveRefine(myvtxdist, p_xadj, p_vvol, p_vsurf, p_adjncy, p_adjwgt, p_glblvtxid,
nparts, minsize, maxsize, &nmoves, &nsteps, options, p_part, comm);
/*
stoptimer(tmr1);
printf("MGridGenRefine Time: %lf\n", gettimer(tmr1));
*/
glblvtxid = *p_glblvtxid;
mypart = *p_part;
/* Communicate number of parts found */
nvtxs = myvtxdist[mype+1]-myvtxdist[mype];
fvtxdist = idxmalloc(npes+1, "ParMGridGen: fvtxdist");
MPI_Allgather((void *)nparts, 1, MPI_INT, (void *)fvtxdist, 1, MPI_INT, *comm);
MAKECSR(i, npes, fvtxdist);
firstfvtx = fvtxdist[mype];
IMfree(&fvtxdist, LTERM);
/* Convert the part array into global numbering */
for (i=0; i<nvtxs; i++)
mypart[i] +=firstfvtx;
IFSET(options[OPTION_DBGLVL], DBG_TRACK,
PrintAspectRatioStats(myvtxdist, *p_xadj, *p_vvol, *p_vsurf, *p_adjncy,
*p_adjwgt, nparts, minsize, maxsize, options, *p_part, *comm));
/* Communicate fused element information to correspond to the original graph */
where = idxsmalloc(nvtxs, -1, "ParMGridGen: sendind");
for (i=0; i<npes; i++)
for (j=0; j<nvtxs; j++)
if (glblvtxid[j] >= vtxdist[i] && glblvtxid[j] < vtxdist[i+1])
where[j] = i;
SetUpMGridCtrl(&ctrl, minsize, maxsize, options, *comm);
ctrl.nparts = npes;
for (i=0; i<nvtxs; i++)
ASSERTP(&ctrl, where[i] >= 0 && where[i] < npes, (&ctrl, "%d %d %d\n", i, where[i], npes) );
graph = SetUpMGridGraph(&ctrl, myvtxdist, *p_xadj, *p_vvol, *p_vsurf, *p_adjncy, *p_adjwgt);
graph->where = where;
graph->fusedinfo = mypart;
graph->glblvtxid = glblvtxid;
PreAllocateMGridMemory(&ctrl, graph, &wspace);
MGridSetUp(&ctrl, graph, &wspace);
mgraph = MoveMGridGraph(&ctrl, graph, &wspace);
nvtxs = mgraph->nvtxs;
IMfree(&graph->lperm, &graph->peind, &graph->recvptr, &graph->recvind, &graph->sendptr,
&graph->sendind, &graph->pexadj, &graph->peadjncy, &graph->peadjloc, &graph->imap,
&graph->vwgt, &graph->adjwgtsum, &graph->where, &graph, LTERM);
FreeMGridWSpace(&wspace);
/* Sort so as to go back to original order of input */
ASSERT(&ctrl, nvtxs == orgnvtxs);
perm = idxmalloc(nvtxs, "ParMGridGen: perm");
for (i=0; i<nvtxs; i++)
perm[mgraph->glblvtxid[i] - vtxdist[mype]] = i;
for (i=0; i<nvtxs; i++)
part[i] = mgraph->fusedinfo[perm[i]];
IMfree(&mgraph->vtxdist, &mgraph->xadj, &mgraph->vwgt, &mgraph->vvol, &mgraph->vsurf,
&mgraph->adjwgtsum, &mgraph->adjncy, &mgraph->adjwgt, &mgraph->fusedinfo,
&mgraph->glblvtxid, &mgraph,
p_xadj, p_vvol, p_vsurf, p_adjncy, p_adjwgt, p_part, p_glblvtxid,
&perm, &myvtxdist, LTERM);
}
/***************************************************************************/
void MoveRefine(idxtype *vtxdist, idxtype **p_xadj, realtype **p_vvol,
realtype **p_vsurf, idxtype **p_adjncy, realtype **p_adjwgt,
idxtype **p_glblvtxid, int *nparts, int minsize, int maxsize,
int *nmoves, int *nsteps, int *options, idxtype **p_part,
MPI_Comm *comm)
{
int i, step, count, wgtflag, numflag;
int firstfvtx, nvtxs, nedges;
int npes, mype;
int moptions[10];
idxtype *mpart, *fusedinfo, *fvtxdist, *glblvtxid;
idxtype *xadj, *adjncy, *vwgt, *part;
idxtype *orxadj, *oradjncy, *oradjncy2;
realtype *vvol, *adjwgt, *vsurf;
realtype *oradjwgt, *orvsurf;
realtype lmeasure1, lmeasure2, gmeasure1, gmeasure2;
MGridCtrlType ctrl;
MGridWorkSpaceType wspace;
MGridGraphType *graph = 0, *mgraph = 0;
double tmr1;
MPI_Comm_size(*comm, &npes);
MPI_Comm_rank(*comm, &mype);
xadj = *p_xadj;
vvol = *p_vvol;
vsurf = *p_vsurf;
adjncy = *p_adjncy;
adjwgt = *p_adjwgt;
part = *p_part;
glblvtxid = *p_glblvtxid;
/* Keep initial graph */
nvtxs = vtxdist[mype+1]-vtxdist[mype];
nedges = xadj[nvtxs];
oradjncy2 = idxmalloc(nedges, "CorrectSurfaceEdges: oradjncy2");
idxcopy(nedges, adjncy, oradjncy2);
vwgt = idxsmalloc(nvtxs, 1, "MoveRefine: vwgt");
for (step=0; step<*nsteps; step++) {
IFSET(options[OPTION_DBGLVL], DBG_STEPS, printf("---------------- CYCLE %d ----------------\n",step+1));
/* Communicate number of parts found in the previous call of MGridgen */
fvtxdist = idxmalloc(npes+1, "ParMETIS_AspectRatio: fvtxdist");
MPI_Allgather((void *)nparts, 1, MPI_INT, (void *)fvtxdist, 1, MPI_INT, *comm);
MAKECSR(i, npes, fvtxdist);
firstfvtx = fvtxdist[mype];
/* Convert the part array into global numbering */
for (i=0; i<nvtxs; i++)
part[i] +=firstfvtx;
fusedinfo = idxmalloc(nvtxs, "MoveRefine: fusedinfo");
idxcopy(nvtxs, part, fusedinfo);
/***** Create Fused Element Graph and get new partition *****/
/* on exit : adjncy array is transformed to local numbering */
moptions[0]=1;
wgtflag = 1;
numflag = 0;
/*
cleartimer(tmr1);
starttimer(tmr1);
*/
ParMETIS_FusedElementGraph(vtxdist, xadj, vvol, vsurf, adjncy, vwgt, adjwgt,
&wgtflag, &numflag, nparts, options, part, comm);
/*
stoptimer(tmr1);
printf("ParMETIS_FusedElementGraph Time = %lf\n", gettimer(tmr1)/nsteps);
*/
/*
count = 0;
printf("=========================\n");
for (i=0; i<nvtxs; i++)
if ( mype != part[i])
count++;
lmeasure1 = ((double)(count))/(*nparts);
lmeasure2 = ((double)(count))/nvtxs;
printf("count=%d nvtxs=%d nparts=%d count/npart=%f count/nvtxs=%f\n",count,nvtxs, *nparts, lmeasure1, lmeasure2);
printf("=========================\n");
*/
/* Move graph around based on the results of the fused graph partition */
/*
cleartimer(tmr1);
starttimer(tmr1);
*/
SetUpMGridCtrl(&ctrl, minsize, maxsize, options, *comm);
/*
stoptimer(tmr1);
printf("SetUpMGridCtrl Time = %lf\n",gettimer(tmr1)/nsteps);
*/
ctrl.nparts=npes;
IMfree(&graph, &mgraph, LTERM);
/*
cleartimer(tmr1);
starttimer(tmr1);
*/
graph = SetUpMGridGraph(&ctrl, vtxdist, xadj, vvol, vsurf, oradjncy2, adjwgt);
/*
stoptimer(tmr1);
printf("SetUpMGridGraph Time = %lf\n",gettimer(tmr1)/nsteps);
*/
graph->where = part;
graph->fusedinfo = fusedinfo;
graph->glblvtxid = glblvtxid;
PreAllocateMGridMemory(&ctrl, graph, &wspace);
MGridSetUp(&ctrl, graph, &wspace);
/*
cleartimer(tmr1);
starttimer(tmr1);
*/
mgraph = MoveMGridGraph(&ctrl, graph, &wspace);
/*
stoptimer(tmr1);
printf("MoveMGridGraph Time = %lf\n",gettimer(tmr1)/nsteps);
*/
IMfree(&xadj, &vvol, &vsurf, &adjwgt, &adjncy, &oradjncy2, &part, &vwgt,
&fvtxdist, &fusedinfo, &glblvtxid, &graph->vwgt, &graph->adjwgtsum,
&graph->lperm, &graph->peind, &graph->recvptr, &graph->recvind,
&graph->sendind, &graph->sendptr, &graph->pexadj, &graph->peadjncy,
&graph->peadjloc, &graph->imap, LTERM);
nvtxs = mgraph->nvtxs;
nedges = mgraph->xadj[nvtxs];
orxadj = idxmalloc(nvtxs+1, "CorrectSurfaceEdges: orxadj");
oradjncy = idxmalloc(nedges, "CorrectSurfaceEdges: oradjncy");
oradjncy2 = idxmalloc(nedges, "CorrectSurfaceEdges: oradjncy");
oradjwgt = realmalloc(nedges, "CorrectSurfaceEdges: oradjwgt");
orvsurf = realmalloc(nvtxs, "CorrectSurfaceEdges: orvsurf");
idxcopy(nvtxs+1, mgraph->xadj, orxadj);
idxcopy(nedges, mgraph->adjncy, oradjncy);
idxcopy(nedges, mgraph->adjncy, oradjncy2);
realcopy(nedges, mgraph->adjwgt, oradjwgt);
realcopy(nvtxs, mgraph->vsurf, orvsurf);
mpart = idxmalloc(nvtxs, "MoveRefine: mpart");
/* Create purely local graph by removing edges and correcting vsurf */
/*
cleartimer(tmr1);
starttimer(tmr1);
*/
RemoveCorrectSurfaceEdges(mgraph->vtxdist, orxadj, oradjncy, oradjwgt,
mgraph->xadj, mgraph->adjncy, mgraph->adjwgt, mgraph->vsurf, *comm);
/*
stoptimer(tmr1);
printf("RemoveCorrectSurfaceEdges Time = %lf\n",gettimer(tmr1)/nsteps);
*/
/* One more step of refinement */
moptions[OPTION_CTYPE]=options[OPTION_CTYPE];
moptions[OPTION_RTYPE]=options[OPTION_RTYPE];
if ( options[OPTION_DBGLVL] == DBG_STEPS )
moptions[OPTION_DBGLVL]=DBG_TRACK;
else if ( options[OPTION_DBGLVL] == DBG_TRACK )
moptions[OPTION_DBGLVL]=0;
else
moptions[OPTION_DBGLVL]=options[OPTION_DBGLVL];
moptions[OPTION_DIM]=options[OPTION_DIM];
/*
cleartimer(tmr1);
starttimer(tmr1);
*/
MGridGenRefine(nvtxs, mgraph->xadj, mgraph->vvol, mgraph->vsurf, mgraph->adjncy,
mgraph->fusedinfo, mgraph->adjwgt, minsize, maxsize, moptions,
nmoves, nparts, mpart);
/*
stoptimer(tmr1);
printf("MGridGenRefineSerial Time = %lf\n",gettimer(tmr1)/nsteps);
*/
nedges = mgraph->xadj[nvtxs];
idxcopy(npes+1, mgraph->vtxdist, vtxdist);
xadj = orxadj;
adjncy = oradjncy;
vvol = mgraph->vvol;
vsurf = orvsurf;
vwgt = mgraph->vwgt;
adjwgt = oradjwgt;
part = mpart;
glblvtxid = mgraph->glblvtxid;
/*
gmeasure1 = MGridGlobalSESumReal(&ctrl, lmeasure1)/npes;
gmeasure2 = MGridGlobalSESumReal(&ctrl, lmeasure2)/npes;
printf("count measure1=%f measure2=%f\n",gmeasure1, gmeasure2);
*/
IMfree(&mgraph->vtxdist, &mgraph->xadj, &mgraph->adjncy, &mgraph->vsurf,
&mgraph->adjwgt, &mgraph->adjwgtsum, &mgraph->fusedinfo, LTERM);
FreeMGridWSpace(&wspace);
FreeMGridCtrl(&ctrl);
/*
if (gmeasure1 < LALALAALA)
break;
*/
}
*p_xadj = xadj;
*p_vvol = vvol;
*p_vsurf = vsurf;
*p_adjncy = adjncy;
*p_adjwgt = adjwgt;
*p_part = part;
*p_glblvtxid = glblvtxid;
IMfree(&vwgt, &oradjncy2, &graph, &mgraph, LTERM);
}
/******************************************************************************
* This function takes a graph and its partition vector and then
* computes and prints statistics info regarding the partition found
*******************************************************************************/
void PrintAspectRatioStats(idxtype *vtxdist, idxtype *xadj, realtype *vvol, realtype *vsurf,
idxtype *adjncy, realtype *adjwgt, int *nparts, int minsize, int maxsize,
int *options, idxtype *part, MPI_Comm comm)
{
int i, j, k, nvtxs, nedges, dim;
int firstpart;
idxtype *myvtxdist, *myxadj, *myadjncy;
idxtype *lpwgts, *counts;
idxtype *where, *swhere, *rwhere;
RInfoType *rinfo, *myrinfo;
EdgeType *edegrees;
MGridCtrlType ctrl;
MGridWorkSpaceType wspace;
MGridGraphType *graph;
int me, other;
int npes, mype;
realtype *myvvol, *myvsurf, *myadjwgt;
realtype *lpvol, *lpsurf;
realtype lmin, lmax, lsum, lwsum, ratio, lsurf;
realtype gmin, gmax, gsum, gwsum, gsurf;
MPI_Comm_size(comm, &npes);
MPI_Comm_rank(comm, &mype);
dim = options[OPTION_DIM];
/*IFSET(options[OPTION_DBGLVL], DBG_IRENE, printf("%d PrintAspectRatioStats\n",mype)); */
nvtxs = vtxdist[mype+1]-vtxdist[mype];
nedges = xadj[nvtxs];
/* Create my own copy of the graph, so that the original can be returned intact */
myvtxdist= idxmalloc(npes+1, "PrintAspectRatioStats: myvtxdist");
myxadj = idxmalloc(nvtxs+1, "PrintAspectRatioStats: myxadj");
myvvol = realmalloc(nvtxs, "PrintAspectRatioStats: myvvol");
myvsurf = realmalloc(nvtxs, "PrintAspectRatioStats: myvsurf");
myadjncy = idxmalloc(nedges, "PrintAspectRatioStats: myadjncy");
myadjwgt = realmalloc(nedges, "PrintAspectRatioStats: myadjwgt");
idxcopy(npes+1, vtxdist, myvtxdist);
idxcopy(nvtxs+1, xadj, myxadj);
realcopy(nvtxs, vvol, myvvol);
realcopy(nvtxs, vsurf, myvsurf);
idxcopy(nedges, adjncy, myadjncy);
realcopy(nedges, adjwgt, myadjwgt);
SetUpMGridCtrl(&ctrl, minsize, maxsize, options, comm);
ctrl.nparts=*nparts;
graph = SetUpMGridGraph(&ctrl, myvtxdist, myxadj, myvvol, myvsurf, myadjncy, myadjwgt);
PreAllocateMGridMemory(&ctrl, graph, &wspace);
MGridSetUp(&ctrl, graph, &wspace);
graph->where = idxmalloc(nvtxs+graph->nrecv, "PrintAspectRatioStats: graph->where");
i = idxamin(nvtxs, part);
firstpart = part[i];
for (i=0; i<nvtxs; i++)
graph->where[i] = part[i] - firstpart;
counts = idxsmalloc(maxsize+1, 0, "PrintAspectRatioStats: counts");
where = graph->where;
rinfo = graph->rinfo = (RInfoType *)IMmalloc(sizeof(RInfoType)*nvtxs, "PrintAspectRatioStats:rinfo");
lpwgts = graph->lpwgts = idxsmalloc(ctrl.nparts, 0, "PrintAspectRatioStats: lpwgts");
graph->gpwgts = idxmalloc(ctrl.nparts, "PrintAspectRatioStats: gpwgts");
lpvol = graph->lpvol = realsmalloc(ctrl.nparts, 0.0, "PrintAspectRatioStats: lpvol");
graph->gpvol = realmalloc(ctrl.nparts, "PrintAspectRatioStats: gpvol");
lpsurf = graph->lpsurf = realsmalloc(ctrl.nparts, 0.0, "PrintAspectRatioStats: lpsurf");
graph->gpsurf = realmalloc(ctrl.nparts, "PrintAspectRatioStats: gpsurf");
/*------------------------------------------------------------
/ Send/Receive the where information of interface vertices
/------------------------------------------------------------*/
swhere = wspace.indices;
rwhere = where + nvtxs;
MGridCommInterfaceData(&ctrl, graph, where, swhere, rwhere);
ASSERT(&ctrl, wspace.nlarge >= myxadj[nvtxs]);
/*------------------------------------------------------------
/ Compute now the id/ed degrees
/------------------------------------------------------------*/
graph->lmincut = 0;
for (i=0; i<nvtxs; i++) {
me = where[i];
myrinfo = rinfo+i;
lpwgts[me] += graph->vwgt[i];
lpvol[me] += graph->vvol[i];
lpsurf[me] += graph->vsurf[i];
myrinfo->degrees = wspace.degrees + myxadj[i];
myrinfo->ndegrees = 0;
myrinfo->id = myrinfo->ed = 0.0;
for (j=myxadj[i]; j<myxadj[i+1]; j++) {
if (me == where[myadjncy[j]])
/* myrinfo->id += myadjwgt[j]; */
myrinfo->id = myrinfo->id + 1.0;
else {
/* myrinfo->ed += myadjwgt[j]; */
myrinfo->ed = myrinfo->ed + 1.0;
lpsurf[me] += myadjwgt[j];
}
}
if (myrinfo->ed > 0.0) { /* Time to do some serious work */
graph->lmincut += myrinfo->ed;
edegrees = myrinfo->degrees;
for (j=myxadj[i]; j<myxadj[i+1]; j++) {
other = where[myadjncy[j]];
if (me != other) {
for (k=0; k<myrinfo->ndegrees; k++) {
if (edegrees[k].edge == other) {
edegrees[k].ewgt += myadjwgt[j];
break;
}
}
if (k == myrinfo->ndegrees) {
edegrees[k].edge = other;
edegrees[k].ewgt = myadjwgt[j];
myrinfo->ndegrees++;
}
ASSERT(&ctrl, myrinfo->ndegrees <= myxadj[i+1]-myxadj[i]);
}
}
}
}
graph->lmincut = graph->lmincut/2;
lmin = lmax = lsum = ARATIO(dim, lpsurf[0], lpvol[0]);
lwsum = 1.0*lpwgts[0]*ARATIO(dim, lpsurf[0], lpvol[0]);
lsurf = lpsurf[0];
counts[lpwgts[0]]++;
graph->lminratio = ARATIO(dim, lpsurf[0], lpvol[0]);
for (i=1; i<ctrl.nparts; i++) {
ratio = ARATIO(dim, lpsurf[i], lpvol[i]);
graph->lminratio += ARATIO(dim, lpsurf[i], lpvol[i]);
lsum += ratio;
lwsum += 1.0*lpwgts[i]*ratio;
lsurf += lpsurf[i];
if (lmin > ratio)
lmin = ratio;
if (lmax < ratio)
lmax = ratio;
counts[lpwgts[i]]++;
}
printf("\n-------------------------- LOCAL --------------------------\n");
printf("Npoints: %d, Coarsening Factor: %f\n", ctrl.nparts, 1.0*graph->nvtxs/(1.0*ctrl.nparts));
printf("Aspect Ratios: Min : %e, Max : %e\n", lmin, lmax);
printf("Aspect Ratios: Sum : %e, Wsum: %e\n", lsum, lwsum);
printf("Aspect Ratios: Surf: %e, Avg : %e\n", lsurf, lsum/(1.0*ctrl.nparts));
printf("Graph lmincut : %e\n", graph->lmincut);
printf("Cell size: min=%d, max=%d\n", ctrl.minsize, ctrl.maxsize);
for (i=1; i<=maxsize; i++)
if (counts[i] != 0)
printf("[%2d %4d] ", i, counts[i]);
printf("\n");
/* Finally, sum-up the partition params */
MPI_Allreduce((void *)&lmin, (void *)&gmin, 1, REAL_DATATYPE, MPI_MIN, comm);
MPI_Allreduce((void *)&lmax, (void *)&gmax, 1, REAL_DATATYPE, MPI_MAX, comm);
MPI_Allreduce((void *)&lsum, (void *)&gsum, 1, REAL_DATATYPE, MPI_SUM, comm);
MPI_Allreduce((void *)&lwsum, (void *)&gwsum, 1, REAL_DATATYPE, MPI_SUM, comm);
MPI_Allreduce((void *)&lsurf, (void *)&gsurf, 1, REAL_DATATYPE, MPI_SUM, comm);
graph->mincut = MGridGlobalSESumReal(&ctrl, graph->lmincut);
i = MGridGlobalSESum(&ctrl, ctrl.nparts);
printf("-------------------------- GLOBAL --------------------------\n");
printf("Npoints: %d, Coarsening Factor: %f\n", i, 1.0*graph->gnvtxs/(1.0*i));
printf("Aspect Ratios: Min : %e, Max : %e\n", gmin, gmax);
printf("Aspect Ratios: Sum : %e, Wsum: %e\n", gsum, gwsum);
printf("Aspect Ratios: Surf: %e, Avg : %e\n", gsurf, gsum/(1.0*i));
printf("Graph mincut : %e\n", graph->mincut);
printf("\n------------------------------ END ------------------------------\n");
FreeMGridWSpace(&wspace);
IMfree(&graph->vtxdist, &graph->xadj, &graph->adjncy, &graph->adjwgt, &graph->vvol,
&graph->vsurf, &graph->vwgt, &graph->adjwgtsum, &graph->lpvol, &graph->gpvol,
&graph->lpsurf, &graph->gpsurf, &graph->lperm, &graph->where, &graph->rinfo,
&graph->lpwgts, &graph->gpwgts, &graph->peind, &graph->sendptr,
&graph->sendind, &graph->recvptr, &graph->recvind, &graph->imap,
&graph->pexadj, &graph->peadjncy, &graph->peadjloc, &counts, &graph, LTERM);
}

View File

@ -1,34 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* parmgridgen.h
*
* This file includes all necessary header files
*
* George Irene
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include <math.h>
#include <stdarg.h>
#include <time.h>
#include <mpi.h>
#ifdef DMALLOC
#include <dmalloc.h>
#else
#include <malloc.h>
#endif
#include "IMlib.h"
#include "rename.h"
#include "defs.h"
#include "struct.h"
#include "defs.h"
#include "macros.h"
#include "proto.h"

View File

@ -1,92 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* proto.h
*
* This file contains header files
*
* George Irene
*/
/* parmgridgen.c */
void ParMGridGen(idxtype *, idxtype *, realtype *, realtype *,
idxtype *, realtype *, int *, int, int, int *, idxtype *,
MPI_Comm *);
void MoveRefine(idxtype *, idxtype **, realtype **, realtype **,
idxtype **, realtype **, idxtype **, int *, int, int, int *,
int *, int *, idxtype **, MPI_Comm *);
void PrintAspectRatioStats(idxtype *, idxtype *, realtype *, realtype *,
idxtype *, realtype *, int *, int, int, int *, idxtype *, MPI_Comm);
/* comm.c */
void MGridCommInterfaceData(MGridCtrlType *, MGridGraphType *, idxtype *,
idxtype *, idxtype *);
void MGridCommChangedInterfaceData(MGridCtrlType *, MGridGraphType *, int,
idxtype *, idxtype *, KeyValueType *, KeyValueType *, idxtype *);
int MGridGlobalSEMax(MGridCtrlType *, int);
double MGridGlobalSEMaxDouble(MGridCtrlType *, double);
int MGridGlobalSEMin(MGridCtrlType *, int);
int MGridGlobalSESum(MGridCtrlType *, int);
realtype MGridGlobalSESumReal(MGridCtrlType *, realtype);
/* debug.c */
void PrintGraph(MGridCtrlType *, MGridGraphType *);
void PrintGraph2(MGridCtrlType *, MGridGraphType *);
void WriteMetisGraph(int, idxtype *, idxtype *, idxtype *, realtype *);
void WriteMetisGraph2(int, idxtype *, idxtype *, idxtype *, realtype *, MPI_Comm);
/* grsetup.c */
MGridGraphType *SetUpMGridGraph(MGridCtrlType *, idxtype *, idxtype *,
realtype *, realtype *, idxtype *, realtype *);
void SetUpMGridCtrl(MGridCtrlType *ctrl, int, int, int *, MPI_Comm);
void ChangeNumbering(idxtype *, idxtype *, idxtype *, idxtype *, int, int, int);
void RemoveEdges(idxtype *, idxtype *, idxtype *, realtype *, idxtype *,
idxtype *, realtype *, MPI_Comm);
void CorrectSurfaceEdges(idxtype *, idxtype *, idxtype *, realtype *,
realtype *, MPI_Comm);
void RemoveCorrectSurfaceEdges(idxtype *, idxtype *, idxtype *, realtype *,
idxtype *, idxtype *, realtype *, realtype *, MPI_Comm);
/* ikeysort.c */
void ikeysort(int, KeyValueType *);
/* memory.c */
void PreAllocateMGridMemory(MGridCtrlType *, MGridGraphType *, MGridWorkSpaceType *);
void FreeMGridWSpace(MGridWorkSpaceType *);
void FreeMGridCtrl(MGridCtrlType *);
MGridGraphType *CreateMGridGraph(void);
void InitMGridGraph(MGridGraphType *);
void FreeMGridGraph(MGridGraphType *);
void FreeMGridGraphContent(MGridGraphType *);
/* move.c */
MGridGraphType *MoveMGridGraph(MGridCtrlType *, MGridGraphType *,
MGridWorkSpaceType *);
/* setup.c */
void MGridSetUp(MGridCtrlType *, MGridGraphType *, MGridWorkSpaceType *);
/* util.c */
void MGriderrexit(char *,...);
void MGridmyprintf(MGridCtrlType *, char *f_str,...);
void MGridrprintf(MGridCtrlType *, char *f_str,...);
/* parmgridgen.c */
void TestParMGridGen(char *, int *, int, int, MPI_Comm);
/* tio.c */
void MGridReadTestGraph(MGridGraphType *, char *, MPI_Comm);
double *ReadTestCoordinates(MGridGraphType *, char *, int, MPI_Comm);
void ReadMGridGraph(char *, int *, idxtype **, idxtype **, realtype **, realtype **, realtype **);
void WriteParallelPartition(char *, idxtype *, idxtype *, int, int, int);

View File

@ -1,52 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* rename.h
*
* This file contains renaming #defines to remove any conflicts that the
* library may have with the users functions.
*
* George Irene
*/
/* comm.c */
#define MGridCommInterfaceData MGridCommInterfaceData___
#define MGridCommChangedInterfaceData MGridCommChangedInterfaceData___
#define MGridGlobalSEMax MGridGlobalSEMax___
#define MGridGlobalSEMaxDouble MGridGlobalSEMaxDouble___
#define MGridGlobalSEMin MGridGlobalSEMin___
#define MGridGlobalSESum MGridGlobalSESum___
#define MGridGlobalSESumReal MGridGlobalSESumReal___
/* debug.c */
#define PrintGraph PrintGraph___
#define PrintGraph2 PrintGraph2___
/* grsetup.c */
#define SetUpMGridGraph SetUpMGridGraph___
#define SetUpMGridCtrl SetUpMGridCtrl___
#define ChangeNumbering ChangeNumbering___
/* ikeysort.c */
#define ikeysort ikeysort___
/* memory.c */
#define PreAllocateMGridMemory PreAllocateMGridMemory___
#define FreeMGridWSpace FreeMGridWSpace___
#define FreeMGridCtrl FreeMGridCtrl___
#define CreateMGridGraph CreateMGridGraph___
#define InitMGridGraph InitMGridGraph___
#define FreeMGridGraph FreeMGridGraph___
#define FreeMGridGraphContent FreeMGridGraphContent___
/* move.c */
#define MoveMGridGraph MoveMGridGraph___
/* setup.c */
#define MGridSetUp MGridSetUp___
/* util.c */
#define MGriderrexit MGriderrexit___
#define MGridmyprintf MGridmyprintf___
#define MGridrprintf MGridrprintf___

View File

@ -1,196 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* setup.c
*
* This file contains functions that setup the various communication
* data structures for parallel KWAY
*
* George Irene
*/
#include "parmgridgen.h"
/*************************************************************************
* This function tests the repeated shmem_put
**************************************************************************/
void MGridSetUp(MGridCtrlType *ctrl, MGridGraphType *graph, MGridWorkSpaceType *wspace)
{
int i, j, k, islocal, penum, gnvtxs, nvtxs, nlocal, firstvtx, lastvtx, nsend, nrecv, nnbrs, nadj;
int npes=ctrl->npes, mype=ctrl->mype;
idxtype *vtxdist, *xadj, *adjncy;
idxtype *peind, *recvptr, *recvind, *sendptr, *sendind;
idxtype *receive, *pemap, *imap, *lperm;
idxtype *pexadj, *peadjncy, *peadjloc, *startsind;
KeyValueType *recvrequests, *sendrequests, *adjpairs;
gnvtxs = graph->gnvtxs;
nvtxs = graph->nvtxs;
vtxdist = graph->vtxdist;
xadj = graph->xadj;
adjncy = graph->adjncy;
firstvtx = vtxdist[mype];
lastvtx = vtxdist[mype+1];
pemap = wspace->pv1;
idxset(npes, -1, pemap);
lperm = graph->lperm = idxmalloc(nvtxs, "SetUp: graph->lperm");
for (i=0; i<nvtxs; i++)
lperm[i] = i;
/*************************************************************
* Determine what you need to receive
*************************************************************/
receive = wspace->indices; /* Use the large global received array for now */
adjpairs = wspace->pairs;
for (nlocal = nadj = i = 0; i<nvtxs; i++) {
islocal = 1;
for (j=xadj[i]; j<xadj[i+1]; j++) {
k = adjncy[j];
if (k >= firstvtx && k < lastvtx) {
adjncy[j] = k-firstvtx;
continue; /* local vertex */
}
adjpairs[nadj].key = k;
adjpairs[nadj++].val = j;
islocal = 0;
}
if (islocal) {
lperm[i] = lperm[nlocal];
lperm[nlocal++] = i;
}
}
/* Take care the received part now */
ikeysort(nadj, adjpairs);
adjpairs[nadj].key = gnvtxs+1; /* Boundary condition */
for (nrecv=i=0; i<nadj; i++) {
adjncy[adjpairs[i].val] = nvtxs+nrecv;
if (adjpairs[i].key != adjpairs[i+1].key)
receive[nrecv++] = adjpairs[i].key;
}
/* Allocate space for the setup info attached to this level of the graph */
peind = graph->peind = idxmalloc(npes, "SetUp: peind");
recvptr = graph->recvptr = idxmalloc(npes+1, "SetUp: recvptr");
recvind = graph->recvind = idxmalloc(nrecv, "SetUp: recvind");
/* Take care of the received portion */
idxcopy(nrecv, receive, recvind); /* Copy the vertices to be received into recvind */
i = nnbrs = recvptr[0] = 0;
for (penum=0; penum<npes; penum++) {
for (j=i; j<nrecv; j++) {
if (recvind[j] >= vtxdist[penum+1])
break;
}
if (j > i) {
peind[nnbrs] = penum;
recvptr[++nnbrs] = j;
i = j;
}
}
/*************************************************************
* Determine what you need to send
*************************************************************/
/* Tell the other processors what they need to send you */
recvrequests = wspace->pepairs1;
sendrequests = wspace->pepairs2;
for (i=0; i<npes; i++)
recvrequests[i].key = 0;
for (i=0; i<nnbrs; i++) {
recvrequests[peind[i]].key = recvptr[i+1]-recvptr[i];
recvrequests[peind[i]].val = nvtxs+recvptr[i];
}
MPI_Alltoall((void *)recvrequests, 2, IDX_DATATYPE, (void *)sendrequests, 2, IDX_DATATYPE, ctrl->comm);
sendptr = graph->sendptr = idxmalloc(npes+1, "SetUp: sendptr");
startsind = wspace->pv2;
for (j=i=0; i<npes; i++) {
if (sendrequests[i].key > 0) {
sendptr[j] = sendrequests[i].key;
startsind[j] = sendrequests[i].val;
j++;
}
}
ASSERT(ctrl, nnbrs == j);
MAKECSR(i, j, sendptr);
nsend = sendptr[nnbrs];
sendind = graph->sendind = idxmalloc(nsend, "SetUp: sendind");
/* Issue the receives for sendind */
for (i=0; i<nnbrs; i++) {
MPI_Irecv((void *)(sendind+sendptr[i]), sendptr[i+1]-sendptr[i], IDX_DATATYPE,
peind[i], 1, ctrl->comm, ctrl->rreq+i);
}
/* Issue the sends. My recvind[penum] becomes penum's sendind[mype] */
for (i=0; i<nnbrs; i++) {
MPI_Isend((void *)(recvind+recvptr[i]), recvptr[i+1]-recvptr[i], IDX_DATATYPE,
peind[i], 1, ctrl->comm, ctrl->sreq+i);
}
MPI_Waitall(nnbrs, ctrl->rreq, ctrl->statuses);
MPI_Waitall(nnbrs, ctrl->sreq, ctrl->statuses);
/* Create the peadjncy data structure for sparse boundary exchanges */
pexadj = graph->pexadj = idxsmalloc(nvtxs+1, 0, "SetUp: pexadj");
peadjncy = graph->peadjncy = idxmalloc(nsend, "SetUp: peadjncy");
peadjloc = graph->peadjloc = idxmalloc(nsend, "SetUp: peadjloc");
for (i=0; i<nsend; i++) {
ASSERTP(ctrl, sendind[i] >= firstvtx && sendind[i] < lastvtx, (ctrl, "%d %d %d\n", sendind[i], firstvtx, lastvtx));
pexadj[sendind[i]-firstvtx]++;
}
MAKECSR(i, nvtxs, pexadj);
for (i=0; i<nnbrs; i++) {
for (j=sendptr[i]; j<sendptr[i+1]; j++) {
k = pexadj[sendind[j]-firstvtx]++;
peadjncy[k] = i; /* peind[i] is the actual PE number */
peadjloc[k] = startsind[i]++;
}
}
ASSERT(ctrl, pexadj[nvtxs] == nsend);
for (i=nvtxs; i>0; i--)
pexadj[i] = pexadj[i-1];
pexadj[0] = 0;
graph->nnbrs = nnbrs;
graph->nrecv = nrecv;
graph->nsend = nsend;
graph->nlocal = nlocal;
/* Create the inverse map from ladjncy to adjncy */
imap = graph->imap = idxmalloc(nvtxs+nrecv, "SetUp: imap");
for (i=0; i<nvtxs; i++)
imap[i] = firstvtx+i;
for (i=0; i<nrecv; i++)
imap[nvtxs+i] = recvind[i];
/* Check if wspace->nlarge is large enough for nrecv and nsend */
if (wspace->nlarge < nrecv+nsend) {
free(wspace->indices);
free(wspace->pairs);
wspace->nlarge = nrecv+nsend;
wspace->indices = idxmalloc(wspace->nlarge, "SetUp: wspace->indices");
wspace->pairs = (KeyValueType *)IMmalloc(sizeof(KeyValueType)*wspace->nlarge, "SetUp: wspace->pairs");
}
}

View File

@ -1,216 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* struct.h
*
* This file contains data structures.
*
* George Irene
*/
/* Indexes are as long as integers for now */
#ifdef IDXTYPE_INT
#define IDX_DATATYPE MPI_INT
#else
#define IDX_DATATYPE MPI_SHORT
#endif
/* floats for now */
#ifdef TYPE_REAL
#define REAL_DATATYPE MPI_FLOAT
#else
#define REAL_DATATYPE MPI_DOUBLE
#endif
/*************************************************************************
* The following data structure stores key-value pair
**************************************************************************/
struct KeyValueType {
idxtype key;
idxtype val;
};
typedef struct KeyValueType KeyValueType;
/*************************************************************************
* The following data structure is used to store the buckets for the
* refinment algorithms
**************************************************************************/
struct PQueueType {
int nnodes;
int maxnnodes;
idxtype *perm, *iperm, *values;
/* iperm[i] stores where the ith entry is located
perm[i] stores the entry that is located in the ith position */
};
typedef struct PQueueType PQueueType;
/*************************************************************************
* The following data structure stores an edge
**************************************************************************/
struct edgedef {
realtype ewgt;
idxtype edge;
};
typedef struct edgedef EdgeType;
/*************************************************************************
* This data structure holds various working space data
**************************************************************************/
struct workspacedef {
idxtype *core; /* Where pairs, indices, and degrees are coming from */
int maxcore;
int nlarge; /* The size of 'Large' */
KeyValueType *pairs; /* Large pair array used during setup */
idxtype *indices; /* Large array of indxtype used for various purposes */
/* Auxiliary parameters */
idxtype *pv1, *pv2, *pv4; /* Vectors of npes+1 size used in various places */
KeyValueType *pepairs1, *pepairs2;
EdgeType *degrees;
};
typedef struct workspacedef MGridWorkSpaceType;
/*************************************************************************
* The following data structure holds information on degrees for k-way
* partition
**************************************************************************/
struct rinfodef {
realtype id, ed; /* ID/ED of edges */
int ndegrees; /* The number of different ext-degrees */
EdgeType *degrees; /* List of edges */
};
typedef struct rinfodef RInfoType;
/*************************************************************************
* The following data structure holds information on degrees for k-way
* partition
**************************************************************************/
struct nrinfodef {
int edegrees[2];
};
typedef struct nrinfodef NRInfoType;
/*************************************************************************
* This data structure holds the input graph
**************************************************************************/
struct graphdef {
int gnvtxs, nvtxs, nedges;
idxtype *xadj; /* Pointers to the locally stored vertices */
idxtype *vwgt; /* Vertex weights */
realtype *vvol; /* The volume of the vertex */
realtype *vsurf; /* The surface of the vertex (applicable only to boundary elements) */
idxtype *vsize; /* Vertex size */
idxtype *adjncy; /* Array that stores the adjacency lists of nvtxs */
realtype *adjwgt; /* Array that stores the weights of the adjacency lists */
realtype *adjwgtsum; /* The sum of the adjacent weights (surace volume) */
idxtype *vtxdist; /* Distribution of vertices */
idxtype *match;
idxtype *cmap;
/* Communication/Setup parameters */
int nnbrs, nrecv, nsend; /* The number of neighboring processors */
idxtype *peind; /* Array of size nnbrs storing the neighboring PEs */
idxtype *sendptr, *sendind; /* CSR format of the vertices that are sent */
idxtype *recvptr, *recvind; /* CSR format of the vertices that are received */
idxtype *imap; /* The inverse map of local to global indices */
idxtype *pexadj, *peadjncy,
*peadjloc; /* CSR format of the PEs each vertex is adjancent to */
int nlocal; /* Number of interior vertices */
idxtype *lperm; /* lperm[0:nlocal] points to interior vertices, the rest are interface */
/* Communication parameters for projecting the partition.
* These are computed during CreateCoarseGraph and used during projection
* Note that during projection, the meaning of received and sent is reversed! */
idxtype *rlens, *slens; /* Arrays of size nnbrs of how many vertices you are sending and receiving */
KeyValueType *rcand;
/* Partition parameters */
idxtype *where; /* processor where vtx resides */
idxtype *fusedinfo; /* fused element vtx belongs to */
idxtype *glblvtxid;
idxtype *lpwgts, *gpwgts;
realtype *lpvol, *gpvol; /* The volume of the partitions */
realtype *lpsurf, *gpsurf; /* The surface area of the partitions */
realtype lminratio, gminratio; /* The value of the objective function */
RInfoType *rinfo;
/* Node refinement information */
NRInfoType *nrinfo;
realtype lmincut, mincut;
};
typedef struct graphdef MGridGraphType;
/*************************************************************************
* The following data type implements a timer
**************************************************************************/
typedef double timer;
/*************************************************************************
* The following structure stores information used by parallel kmetis
**************************************************************************/
struct controldef {
int mype, npes; /* Info about the parallel system */
int dbglvl; /* Controls the debuging output of the program */
int nparts; /* The number of partitions */
int CType; /* The type of coarsening */
int RType; /* The type of refinement */
int minsize; /* The bounds on the number of elements per parti
tion */
int maxsize;
MPI_Comm gcomm;
MPI_Comm comm; /* MPI Communicator */
MPI_Request sreq[MAX_PES],
rreq[MAX_PES]; /* MPI send and receive requests */
MPI_Status statuses[MAX_PES];
MPI_Status status;
/* Various Timers */
timer TotalTmr, InitPartTmr, MatchTmr, ContractTmr, CoarsenTmr, RefTmr,
SetupTmr, ColorTmr, ProjectTmr, KWayInitTmr, KWayTmr, MoveTmr,
RemapTmr, AuxTmr1, AuxTmr2, AuxTmr3, AuxTmr4, AuxTmr5, AuxTmr6;
};
typedef struct controldef MGridCtrlType;
/*************************************************************************
* The following data structure stores a sparse matrix in CSR format
* The diagonal entry is in the first position of each row.
**************************************************************************/
struct matrixdef {
int nrows; /* Number of rows in the matrix */
idxtype *rowptr;
idxtype *colind;
float *values;
idxtype *transfer;
};
typedef struct matrixdef MatrixType;

View File

@ -1,83 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* util.c
*
* This function contains various utility routines
*
* George Irene
*/
#include "parmgridgen.h"
/*************************************************************************
* This function prints an error message and exits
**************************************************************************/
void MGriderrexit(char *f_str,...)
{
va_list argp;
char out1[256], out2[256];
va_start(argp, f_str);
vsprintf(out1, f_str, argp);
va_end(argp);
sprintf(out2, "Error! %s", out1);
fprintf(stdout, out2);
fflush(stdout);
abort();
}
/*************************************************************************
* This function prints an error message and exits
**************************************************************************/
void MGridmyprintf(MGridCtrlType *ctrl, char *f_str,...)
{
va_list argp;
char out1[256], out2[256];
va_start(argp, f_str);
vsprintf(out1, f_str, argp);
va_end(argp);
sprintf(out2, "[%2d] %s", ctrl->mype, out1);
fprintf(stdout, out2);
fflush(stdout);
}
/*************************************************************************
* This function prints an error message and exits
**************************************************************************/
void MGridrprintf(MGridCtrlType *ctrl, char *f_str,...)
{
va_list argp;
if (ctrl->mype == 0) {
va_start(argp, f_str);
vfprintf(stdout, f_str, argp);
va_end(argp);
}
fflush(stdout);
MPI_Barrier(ctrl->comm);
}
#ifdef XXXX
/*************************************************************************
* This function returns the seconds
**************************************************************************/
float seconds(void)
{
return ((float) clock()/CLOCKS_PER_SEC);
}
#endif

View File

@ -1,46 +0,0 @@
include ../../Makefile.in
PARMGRIDLIB = ../../libparmgrid.a
ifeq ($(ddmalloc),yes)
DEBUGFLAGS := $(DEBUGFLAGS) -DDMALLOC -DDEBUG
INCDIR := $(INCDIR) -I$(DMALLOCDIR)/include
LIBDIR := $(LIBDIR) -L$(DMALLOCDIR)/lib
PARLIBS := $(PARLIBS) -ldmalloc
OPTFLAGS = -g
endif
ifeq ($(dmalloc),yes)
DEBUGFLAGS := $(DEBUGFLAGS) -DDMALLOC
INCDIR := $(INCDIR) -I$(DMALLOCDIR)/include
LIBDIR := $(LIBDIR) -L$(DMALLOCDIR)/lib
PARLIBS := $(PARLIBS) -ldmalloc
endif
ifeq ($(debug),yes)
DEBUGFLAGS := $(DEBUGFLAGS) -DDEBUG
OPTFLAGS = -g
endif
INCLUDES = -I../ParLib -I$(IMLIBDIR) $(INCDIR)
CFLAGS = $(COPTIONS) $(OPTFLAGS) $(DEBUGFLAGS) $(INCLUDES)
OBJS = main.o parmgridgen.o io.o
.c.o:
$(PARCC) $(CFLAGS) -c $*.c
default: $(BINDIR)/parmgridgen
$(BINDIR)/parmgridgen: $(OBJS) $(PARMGRIDLIB)
$(PARLD) -o $@ $(OBJS) $(LIBDIR) $(PARLIBS)
chmod 744 $@
clean:
rm -f *.o
realclean:
rm -f *.o ;\
rm -f $(BINDIR)/parmgridgen

View File

@ -1,289 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* tio.c
*
* This file contains routines related to I/O
*
* George Irene
*/
#include "parmgridgen.h"
/*************************************************************************
* This function reads the CSR matrix
**************************************************************************/
void MGridReadTestGraph(MGridGraphType *graph, char *filename, MPI_Comm comm)
{
int i, k, l, npes, mype;
int nvtxs, penum, snvtxs;
idxtype *gxadj, *gadjncy;
idxtype *vtxdist, *sxadj, *ssize;
realtype *gadjwgt, *gvsurf, *gvvol;
MPI_Status status;
MPI_Comm_size(comm, &npes);
MPI_Comm_rank(comm, &mype);
vtxdist = graph->vtxdist = idxsmalloc(npes+1, 0, "MGridReadTestGraph: vtxdist");
if (mype == 0) {
ssize = idxsmalloc(npes, 0, "MGridReadTestGraph: ssize");
ReadMGridGraph(filename, &nvtxs, &gxadj, &gadjncy, &gadjwgt, &gvvol, &gvsurf);
printf("Nvtxs: %d, Nedges: %d\n", nvtxs, gxadj[nvtxs]);
/* Construct vtxdist and send it to all the processors */
vtxdist[0] = 0;
for (i=0,k=nvtxs; i<npes; i++) {
l = k/(npes-i);
vtxdist[i+1] = vtxdist[i]+l;
k -= l;
}
}
MPI_Bcast((void *)vtxdist, npes+1, IDX_DATATYPE, 0, comm);
graph->gnvtxs = vtxdist[npes];
graph->nvtxs = vtxdist[mype+1]-vtxdist[mype];
graph->xadj = idxmalloc(graph->nvtxs+1, "MGridReadTestGraph: xadj");
if (mype == 0) {
for (penum=0; penum<npes; penum++) {
snvtxs = vtxdist[penum+1]-vtxdist[penum];
sxadj = idxmalloc(snvtxs+1, "MGridReadTestGraph: sxadj");
idxcopy(snvtxs+1, gxadj+vtxdist[penum], sxadj);
for (i=snvtxs; i>=0; i--)
sxadj[i] -= sxadj[0];
ssize[penum] = gxadj[vtxdist[penum+1]] - gxadj[vtxdist[penum]];
if (penum == mype)
idxcopy(snvtxs+1, sxadj, graph->xadj);
else
MPI_Send((void *)sxadj, snvtxs+1, IDX_DATATYPE, penum, 1, comm);
free(sxadj);
}
}
else
MPI_Recv((void *)graph->xadj, graph->nvtxs+1, IDX_DATATYPE, 0, 1, comm, &status);
graph->vvol = realmalloc(graph->nvtxs, "MGridReadTestGraph: vvol");
if (mype == 0) {
for (penum=0; penum<npes; penum++) {
snvtxs = vtxdist[penum+1]-vtxdist[penum];
if (penum == mype)
realcopy(snvtxs, gvvol+vtxdist[penum], graph->vvol);
else
MPI_Send((void *)(gvvol+vtxdist[penum]), snvtxs, REAL_DATATYPE, penum, 1, comm);
}
}
else
MPI_Recv((void *)graph->vvol, graph->nvtxs, REAL_DATATYPE, 0, 1, comm, &status);
graph->vsurf = realmalloc(graph->nvtxs, "MGridReadTestGraph: vsurf");
if (mype == 0) {
for (penum=0; penum<npes; penum++) {
snvtxs = vtxdist[penum+1]-vtxdist[penum];
if (penum == mype)
realcopy(snvtxs, gvsurf+vtxdist[penum], graph->vsurf);
else
MPI_Send((void *)(gvsurf+vtxdist[penum]), snvtxs, REAL_DATATYPE, penum, 1, comm);
}
}
else
MPI_Recv((void *)graph->vsurf, graph->nvtxs, REAL_DATATYPE, 0, 1, comm, &status);
graph->nedges = graph->xadj[graph->nvtxs];
graph->adjncy = idxmalloc(graph->nedges, "MGridReadTestGraph: graph->adjncy");
if (mype == 0) {
for (penum=0; penum<npes; penum++) {
if (penum == mype)
idxcopy(ssize[penum], gadjncy+gxadj[vtxdist[penum]], graph->adjncy);
else
MPI_Send((void *)(gadjncy+gxadj[vtxdist[penum]]), ssize[penum], IDX_DATATYPE, penum, 1, comm);
}
}
else
MPI_Recv((void *)graph->adjncy, graph->nedges, IDX_DATATYPE, 0, 1, comm, &status);
graph->vwgt = NULL;
graph->adjwgt = realmalloc(graph->nedges, "MGridReadTestGraph: graph->adjwgt");
if (mype == 0) {
for (penum=0; penum<npes; penum++) {
if (penum == mype)
realcopy(ssize[penum], gadjwgt+gxadj[vtxdist[penum]], graph->adjwgt);
else
MPI_Send((void *)(gadjwgt+gxadj[vtxdist[penum]]), ssize[penum], REAL_DATATYPE, penum, 1, comm);
}
free(ssize);
}
else
MPI_Recv((void *)graph->adjwgt, graph->nedges, REAL_DATATYPE, 0, 1, comm, &status);
if (mype == 0)
IMfree(&gxadj, &gvvol, &gvsurf, &gadjncy, &gadjwgt, LTERM);
}
/*************************************************************************
* This function reads the CSR matrix
**************************************************************************/
double *ReadTestCoordinates(MGridGraphType *graph, char *filename, int ndims, MPI_Comm comm)
{
int i, j, k, npes, mype;
int penum;
double *xyz, *txyz;
FILE *fpin;
idxtype *vtxdist;
MPI_Status status;
char xyzfile[256];
MPI_Comm_size(comm, &npes);
MPI_Comm_rank(comm, &mype);
vtxdist = graph->vtxdist;
xyz = fmalloc(graph->nvtxs*ndims, "io");
if (mype == 0) {
sprintf(xyzfile, "%s.xyz", filename);
if ((fpin = fopen(xyzfile, "r")) == NULL)
errexit("Failed to open file %s\n", xyzfile);
}
if (mype == 0) {
txyz = fmalloc(2*graph->nvtxs*ndims, "io");
for (penum=0; penum<npes; penum++) {
for (k=0, i=vtxdist[penum]; i<vtxdist[penum+1]; i++, k++) {
for (j=0; j<ndims; j++)
fscanf(fpin, "%e ", txyz+k*ndims+j);
}
if (penum == mype)
memcpy((void *)xyz, (void *)txyz, sizeof(float)*ndims*k);
else {
MPI_Send((void *)txyz, ndims*k, MPI_FLOAT, penum, 1, comm);
}
}
free(txyz);
fclose(fpin);
}
else
MPI_Recv((void *)xyz, ndims*graph->nvtxs, MPI_FLOAT, 0, 1, comm, &status);
return xyz;
}
/*************************************************************************
* This function reads the spd matrix
**************************************************************************/
void ReadMGridGraph(char *filename, int *r_nvtxs, idxtype **r_xadj, idxtype **r_adjncy, realtype **r_adjwgt, realtype **r_vvol, realtype **r_vsurf)
{
int i, k, nvtxs, nedges;
idxtype *xadj, *adjncy;
realtype *vvol, *vsurf, *adjwgt;
char line[MAXLINE+1], delim[] = " \t", *token;
FILE *fpin;
if ((fpin = fopen(filename, "r")) == NULL) {
printf("Failed to open file %s\n", filename);
exit(0);
}
do {
fgets(line, MAXLINE, fpin);
} while (line[0] == '%' && !feof(fpin));
if (feof(fpin)) {
nvtxs = 0;
return;
}
sscanf(line, "%d %d", &nvtxs, &nedges);
nedges *= 2;
xadj = idxsmalloc(nvtxs+1, 0, "ReadMGridGraph: xadj");
vvol = realmalloc(nvtxs, "ReadMGridGraph: vvol");
vsurf = realsmalloc(nvtxs, 0.0, "ReadMGridGraph: vsurf");
adjncy = idxmalloc(nedges+1, "ReadMGridGraph: adjncy");
adjwgt = realmalloc(nedges+1, "ReadMGridGraph: adjwgt");
/* Start reading the graph file */
for (xadj[0]=0, k=0, i=0; i<nvtxs; i++) {
do {
fgets(line, MAXLINE, fpin);
} while (line[0] == '%' && !feof(fpin));
if (strlen(line) == MAXLINE)
errexit("\nBuffer for fgets not big enough!\n");
/* Parse the string and get the arguments */
token = strtok(line, delim);
vvol[i] = atof(token);
while ((token = strtok(NULL, delim))) {
adjncy[k] = atoi(token) - 1;
if (adjncy[k] == i)
vsurf[i] = atof(strtok(NULL, delim));
else
adjwgt[k++] = atof(strtok(NULL, delim));
}
xadj[i+1] = k;
}
fclose(fpin);
if (k != nedges)
errexit("ReadMGridGraph: Something wrong with the edges from input file %d %d", nedges, k);
*r_nvtxs = nvtxs;
*r_xadj = xadj;
*r_adjncy = adjncy;
*r_adjwgt = adjwgt;
*r_vvol = vvol;
*r_vsurf = vsurf;
}
/*************************************************************************
* This function writes out the partition vector locallly
**************************************************************************/
void WriteParallelPartition(char *fname, idxtype *part, idxtype *vtxdist, int nparts,
int mype, int npes)
{
int i,n;
char filename[256];
FILE *fpout;
n = vtxdist[mype+1] - vtxdist[mype];
sprintf(filename,"%s.part%d-%d.%d",fname, npes, mype, nparts);
if ((fpout = fopen(filename, "w")) == NULL)
errexit("Problems in opening the partition file: %s", filename);
for (i=0; i<n; i++)
fprintf(fpout,"%d\n",part[i]);
fclose(fpout);
}

View File

@ -1,73 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* main.c
*
* This file contains code for testing the adaptive partitioning routines
*
* George Irene
*/
#include "parmgridgen.h"
/*************************************************************************
* Let the game begin
**************************************************************************/
int main(int argc, char *argv[])
{
int mype, npes;
MPI_Comm comm;
int minsize, maxsize;
int options[10];
char filename[15];
MPI_Init(&argc, &argv);
MPI_Comm_dup(MPI_COMM_WORLD, &comm);
MPI_Comm_size(comm, &npes);
MPI_Comm_rank(comm, &mype);
sprintf(filename,"OUTPUT%d.%d",npes,mype);
freopen(filename, "a", stdout);
if (argc != 8) {
if (mype == 0) {
printf("Usage: %s <GraphFile> <Dim> <CType> <RType> <minsize> <maxsize> <dbglvl>\n", argv[0]);
printf("Where:\n");
printf("\tDim: \t2 -> 2-D Mesh\n");
printf("\t \t3 -> 3-D Mesh\n");
printf("\tCType: \t1 -> Random\n");
printf("\t \t2 -> HEM\n");
printf("\t \t3 -> Slow HEM\n");
printf("\t \t4 -> Slow Heaviest\n");
printf("\tRType: \t1 -> Aspect Ratio refinement\n");
printf("\t \t2 -> Weighted Aspect Ratio refinement\n");
printf("\t \t3 -> Surface cut refinement\n");
printf("\t \t4 -> Minimum Aspect Ratio & Average refinement\n");
printf("\t \t5 -> Minimum Aspect Ratio refinement\n");
printf("\t \t6 -> 4+2 Minimum & Weighted Aspect Ratio refinement\n");
printf("\t \t7 -> 5+2 Minimum & Weighted Aspect Ratio refinement\n");
printf("\tminsize:\tA lower bound on the cell size (suggested)\n");
printf("\tmaxsize:\tAn upper bound on the cell size (strict)\n");
printf("--------------------------------------------------------------------\n");
printf("Recomended usage: %s <GraphFile> <Dim> 4 6 ? ? 128\n", argv[0]);
printf("--------------------------------------------------------------------\n");
}
MPI_Finalize();
exit(0);
}
options[OPTION_DIM] = atoi(argv[2]);
options[OPTION_CTYPE] = atoi(argv[3]);
options[OPTION_RTYPE] = atoi(argv[4]);
minsize = atoi(argv[5]);
maxsize = atoi(argv[6]);
options[OPTION_DBGLVL] = atoi(argv[7]);
TestParMGridGen(argv[1], options, minsize, maxsize, comm);
MPI_Comm_free(&comm);
MPI_Finalize();
return(0);
}

View File

@ -1,59 +0,0 @@
/*
* Copyright 2001, Regents of the University of Minnesota
*
* parmgridgen.c
*
* This file contains code for testing the adaptive partitioning routines
*
* George Irene
*/
#include "parmgridgen.h"
/***********************************************************************************
* This function is the testing routine for the adaptive multilevel partitioning code.
* It computes a partition from scratch, it then moves the graph and changes some
* of the vertex weights and then call the adaptive code.
************************************************************************************/
void TestParMGridGen(char *filename, int *options, int minsize, int maxsize, MPI_Comm comm)
{
int i, nparts, npes, mype;
MGridGraphType graph;
idxtype *part;
double tmr;
MPI_Comm_size(comm, &npes);
MPI_Comm_rank(comm, &mype);
MGridReadTestGraph(&graph, filename, comm);
part = idxmalloc(graph.nvtxs, "TestParMGridGen: part");
/*======================================================================
/ ParMETIS_AspectRatio
/=======================================================================*/
if (mype==0)
printf("------------------------ PARAMETERS --------------------------------------\n");
for (i=0; i<npes; i++)
if (mype == i)
printf("%s, Dim=%d [%2d %2d] CType=%d RType=%d Nvtxs=%d Nedges=%d\n", filename,
options[OPTION_DIM], minsize, maxsize, options[OPTION_CTYPE],
options[OPTION_RTYPE], graph.nvtxs, graph.nedges);
cleartimer(tmr);
MPI_Barrier(comm);
starttimer(tmr);
ParMGridGen(graph.vtxdist, graph.xadj, graph.vvol, graph.vsurf, graph.adjncy,
graph.adjwgt, &nparts, minsize, maxsize, options, part, &comm);
MPI_Barrier(comm);
stoptimer(tmr);
printf("Total Time = %lf\n", gettimer(tmr));
WriteParallelPartition(filename, part, graph.vtxdist, nparts, mype, npes);
IMfree(&graph.vtxdist, &graph.xadj, &graph.vvol, &graph.vsurf, &graph.vwgt,
&graph.adjncy, &graph.adjwgt, &part, LTERM);
}

View File

@ -1,13 +0,0 @@
This is PARMGRIDGEN version 1.0. You can find the manual describing the
various routines in the directory Doc. Also, the file called INSTALL
contains instructions on how to build and test PARMGRIDGEN.
Any bug fixes and upgrades of the PARMGRIDGEN package is available on WWW
at URL: http://www.cs.umn.edu/~moulitsa/software.html
Irene Moulitsas
moulitsa@cs.umn.edu
Tue Dec 4 18:24:47 CST 2001

View File

@ -1 +0,0 @@
PARMGRIDGEN 1.0 Tue Dec 4 18:24:47 CST 2001

Some files were not shown because too many files have changed in this diff Show More