Пример #1
0
/***********************************************************************************
 * * This function is the entry point of the parallel k-way multilevel partitionioner.
 * * This function assumes nothing about the graph distribution.
 * * It is the general case.
 * ************************************************************************************/
void PARKMETIS(idxtype *vtxdist, idxtype *xadj, idxtype *vwgt, idxtype *adjncy, idxtype *adjwgt,
		               idxtype *part, int *options, MPI_Comm comm)
{
  int wgtflag, numflag, edgecut, newoptions[5];
  int npes;

  MPI_Comm_size(comm, &npes);

  newoptions[0] = 1;
  newoptions[OPTION_IPART] = options[2];
  newoptions[OPTION_FOLDF] = options[1];
  newoptions[OPTION_DBGLVL] = options[4];

		        numflag = options[3];
  wgtflag = (vwgt == NULL ? 0 : 2) + (adjwgt == NULL ? 0 : 1);

  ParMETIS_PartKway(vtxdist, xadj, adjncy, vwgt, adjwgt, &wgtflag, &numflag, &npes,
	newoptions, &edgecut, part, &comm);

  options[0] = edgecut;

}
Пример #2
0
// same as above, but assumes that the matrix A has symmetric sparsity pattern. Only recommended for use
// on a matrix that has been formed directly from a finite volume mesh.
void mtx_CRS_dist_domdec_sym( Tmtx_CRS_dist_ptr A, Tdistribution_ptr dist, int *p )
{
	int i, n_nodes, dom, count, n_dom, pos, edgecut, numflag=0, wgtflag=0, this_dom, n_neigh=0;
	int *vstarts=NULL, *indx=NULL, *starts=NULL, *counts=NULL, *part=NULL, *ppart=NULL, *_cindx=NULL, *_rindx=NULL;
	int ParMETIS_options[4] = {0, 0, 0, 0};
	TMPI_dat_ptr This=NULL;
	
	This = &A->This;
	
	// initialise variables
	n_nodes  =  A->mtx.nrows;
	n_dom    =  This->n_proc;
	this_dom =  This->this_proc;
	
	// initialise the distribution
	distribution_init( dist, n_dom, n_nodes, 1 );
	
	// setup pointers
	indx   = dist->indx;
	starts = dist->starts;
	counts = dist->counts;
	part   = dist->part;
	ppart  = dist->ppart;

	// make the CRS profile of the matrix into an adjacency graph
	_cindx = malloc( (A->mtx.nnz)*sizeof(int) );
	_rindx = malloc( (n_nodes+1)*sizeof(int) );
	index_make_adjacency( n_nodes, A->vtxdist[this_dom], A->mtx.cindx, A->mtx.rindx, _cindx, _rindx );

	// use ParMETIS to perform domain decomp
	ParMETIS_PartKway( A->vtxdist, _rindx, _cindx, NULL, NULL, &wgtflag, &numflag, &n_dom, 
					   ParMETIS_options, &edgecut, part, &This->comm);
		
	// keep copy of original part in ppart
	memcpy( ppart, part, sizeof(int)*n_nodes );
	
	// sort part, indx holds the permutation required for This
	for( i=0; i<n_nodes; i++ ) 
		indx[i]=i;
	heapsort_int_index( n_nodes, indx, part);
	
	// determine the number of nodes that we have for each processor
	pos = 0;
	for( dom=0; dom<n_dom; dom++ )
	{
		starts[dom] = pos;
		count=0;
		while( part[pos]==dom && pos<A->mtx.nrows ) 
		{
			pos++;
			count++;
		}
		counts[dom] = count;
		if( count )
			n_neigh++;
	}
	starts[dom] = pos;
	
	// find and store the neighbour information to dist
	free( dist->neighbours );
	dist->neighbours = (int *)malloc( sizeof(int)*n_neigh );
	dist->n_neigh = n_neigh;
	for( pos=0, dom=0; dom<n_dom; dom++ )
		if( counts[dom] )
			dist->neighbours[pos++] = dom;
	
	
	// sort the indices of each target domain's nodes
	for( dom=0; dom<n_dom; dom++ )
		if( counts[dom]>1 )
			heapsort_int( counts[dom], indx + starts[dom] );
	
	// all processes update their copy of the global partition vector in p
	vstarts = (int *)malloc( sizeof(int)*n_dom );
	for( i=0; i<n_dom; i++ )
		vstarts[i] = A->vtxdist[i+1] - A->vtxdist[i];
	
	MPI_Allgatherv( ppart, vstarts[this_dom], MPI_INT, p, vstarts, A->vtxdist, MPI_INT, This->comm );
	free( vstarts );
	free( _rindx );
	free( _cindx );
}