mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
* bin/rmdepall: Correction to the removing of scanned files.
This commit is contained in:
@ -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>"
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -1,6 +0,0 @@
|
||||
TYPE_REAL=
|
||||
#if defined(SP)
|
||||
TYPE_REAL=-DTYPE_REAL
|
||||
#endif
|
||||
|
||||
EXE_INC = $(TYPE_REAL)
|
||||
@ -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
|
||||
@ -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);
|
||||
}
|
||||
@ -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
|
||||
|
||||
}
|
||||
@ -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
|
||||
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
aratio.c
|
||||
coarsen.c
|
||||
kwayfm.c
|
||||
match.c
|
||||
merge.c
|
||||
mgridgen.c
|
||||
refine.c
|
||||
setup.c
|
||||
|
||||
LIB = $(FOAM_LIBBIN)/libMGridGen
|
||||
@ -1,7 +0,0 @@
|
||||
TYPE_REAL=
|
||||
#if defined(SP)
|
||||
TYPE_REAL=-DTYPE_REAL
|
||||
#endif
|
||||
|
||||
EXE_INC = -I../IMlib $(TYPE_REAL)
|
||||
LIB_LIBS = -lIMlib
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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 */
|
||||
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
@ -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);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
}
|
||||
@ -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"
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
@ -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 )
|
||||
@ -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
|
||||
@ -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);
|
||||
}
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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 )
|
||||
@ -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
|
||||
@ -1,11 +0,0 @@
|
||||
include ../../Makefile.in
|
||||
|
||||
default:
|
||||
(cd ParMETISLib ; $(make) )
|
||||
|
||||
clean:
|
||||
(cd ParMETISLib ; $(make) clean )
|
||||
|
||||
realclean:
|
||||
(cd ParMETISLib ; $(make) realclean )
|
||||
|
||||
@ -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
|
||||
@ -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)
|
||||
@ -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
|
||||
@ -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 */
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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 */
|
||||
@ -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);
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -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);
|
||||
}
|
||||
@ -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"
|
||||
|
||||
@ -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);
|
||||
*/
|
||||
@ -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);
|
||||
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
}
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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 !! */
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -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 )
|
||||
@ -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
|
||||
@ -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)
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -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 */
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -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);
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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"
|
||||
@ -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);
|
||||
|
||||
@ -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___
|
||||
@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -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
|
||||
@ -1 +0,0 @@
|
||||
PARMGRIDGEN 1.0 Tue Dec 4 18:24:47 CST 2001
|
||||
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user