You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
227 lines
6.8 KiB
227 lines
6.8 KiB
/*
|
|
* Copyright(C) 1999-2020 National Technology & Engineering Solutions
|
|
* of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with
|
|
* NTESS, the U.S. Government retains certain rights in this software.
|
|
*
|
|
* See packages/seacas/LICENSE for details
|
|
*/
|
|
|
|
#include "smalloc.h" // for smalloc
|
|
#include "structs.h" // for vtx_data
|
|
#include <stdio.h> // for fprintf, printf, NULL, etc
|
|
|
|
/* Make a bipartite graph from vertex separator and neighbors. */
|
|
|
|
void make_bpgraph(struct vtx_data **graph, /* list of graph info for each vertex */
|
|
int * sets, /* local partitioning of vtxs */
|
|
int * bndy_list, /* list of vertices on boundary (0 ends) */
|
|
int sep_size, /* length of bndy_list */
|
|
int set_match, /* side to match against */
|
|
int ** ppointers, /* start/stop of adjacency lists */
|
|
int ** pindices, /* adjacency list for each vertex */
|
|
int ** pvweight, /* weight of each vertex */
|
|
int ** ploc2glob, /* maps bp number to full graph */
|
|
int * pnleft, /* number of nodes in left half */
|
|
int * pnright, /* number of nodes in right half */
|
|
int using_vwgts /* are vertices weighted? */
|
|
)
|
|
{
|
|
int *loc2glob = NULL; /* maps bp number to full graph */
|
|
int *pointers = NULL; /* start/stop of adjacency lists */
|
|
int *indices = NULL; /* adjacency list for each vertex */
|
|
int *vwgts = NULL; /* saves vwgts so they can be overwritten */
|
|
int nleft, nright; /* # vertices in halves of bipartite graph */
|
|
int nedges; /* number of edges in bipartite graph */
|
|
int vtx; /* vertex in graph */
|
|
int neighbor; /* neighbor of vertex */
|
|
int i, j, k; /* loop counters */
|
|
|
|
/* First count everything that needs to be counted. */
|
|
nleft = sep_size;
|
|
nright = 0;
|
|
nedges = 0;
|
|
for (i = 0; i < sep_size; i++) {
|
|
vtx = bndy_list[i];
|
|
for (j = 1; j < graph[vtx]->nedges; j++) {
|
|
neighbor = graph[vtx]->edges[j];
|
|
if (sets[neighbor] == set_match) {
|
|
++nedges;
|
|
if (graph[neighbor]->edges[0] > 0) { /* Not yet seen */
|
|
++nright;
|
|
/* Flag him as seen already. */
|
|
graph[neighbor]->edges[0] = -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pointers = smalloc((nleft + nright + 1) * sizeof(int));
|
|
indices = smalloc((2 * nedges + 1) * sizeof(int));
|
|
|
|
/* Now set up data structures to make construction easier */
|
|
loc2glob = smalloc((nleft + nright) * sizeof(int));
|
|
|
|
if (!using_vwgts) {
|
|
for (i = 0; i < nleft; i++) {
|
|
vtx = bndy_list[i];
|
|
loc2glob[i] = vtx;
|
|
graph[vtx]->edges[0] = i;
|
|
}
|
|
|
|
k = nleft;
|
|
for (i = 0; i < nleft; i++) {
|
|
vtx = bndy_list[i];
|
|
for (j = 1; j < graph[vtx]->nedges; j++) {
|
|
neighbor = graph[vtx]->edges[j];
|
|
if (sets[neighbor] == set_match) {
|
|
if (graph[neighbor]->edges[0] == -1) {
|
|
loc2glob[k] = neighbor;
|
|
/* Reflag him as seen already with glob2loc value. */
|
|
graph[neighbor]->edges[0] = k;
|
|
k++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
vwgts = smalloc((nleft + nright) * sizeof(int));
|
|
|
|
for (i = 0; i < nleft; i++) {
|
|
vtx = bndy_list[i];
|
|
loc2glob[i] = vtx;
|
|
vwgts[i] = graph[vtx]->vwgt;
|
|
/* Use edges[0] as a seen flag and as a glob2loc value. */
|
|
graph[vtx]->edges[0] = i;
|
|
}
|
|
|
|
k = nleft;
|
|
for (i = 0; i < nleft; i++) {
|
|
vtx = bndy_list[i];
|
|
for (j = 1; j < graph[vtx]->nedges; j++) {
|
|
neighbor = graph[vtx]->edges[j];
|
|
if (sets[neighbor] == set_match) {
|
|
if (graph[neighbor]->edges[0] == -1) { /* First occurrence. */
|
|
loc2glob[k] = neighbor;
|
|
vwgts[k] = graph[neighbor]->vwgt;
|
|
/* Use edges[0] as a seen flag and as a glob2loc value. */
|
|
graph[neighbor]->edges[0] = k;
|
|
k++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* I can now construct graph directly */
|
|
nedges = 0;
|
|
pointers[0] = 0;
|
|
for (i = 0; i < nleft; i++) {
|
|
vtx = loc2glob[i];
|
|
for (j = 1; j < graph[vtx]->nedges; j++) {
|
|
neighbor = graph[vtx]->edges[j];
|
|
if (sets[neighbor] == set_match) {
|
|
indices[nedges++] = graph[neighbor]->edges[0];
|
|
}
|
|
}
|
|
pointers[i + 1] = nedges;
|
|
}
|
|
|
|
for (i = nleft; i < nleft + nright; i++) {
|
|
vtx = loc2glob[i];
|
|
for (j = 1; j < graph[vtx]->nedges; j++) {
|
|
neighbor = graph[vtx]->edges[j];
|
|
if (sets[neighbor] == 2) {
|
|
indices[nedges++] = graph[neighbor]->edges[0];
|
|
}
|
|
}
|
|
pointers[i + 1] = nedges;
|
|
}
|
|
|
|
/* Now restore the edges[0] values. */
|
|
for (i = 0; i < nleft + nright; i++) {
|
|
graph[loc2glob[i]]->edges[0] = loc2glob[i];
|
|
}
|
|
|
|
/*
|
|
check_bpgraph(nleft, nright, pointers, indices);
|
|
*/
|
|
|
|
if (using_vwgts) {
|
|
*pvweight = vwgts;
|
|
}
|
|
else {
|
|
*pvweight = NULL;
|
|
}
|
|
|
|
*ploc2glob = loc2glob;
|
|
*ppointers = pointers;
|
|
*pindices = indices;
|
|
*pnleft = nleft;
|
|
*pnright = nright;
|
|
}
|
|
|
|
void check_bpgraph(int n_left, int n_right, int *pointers, int *indices)
|
|
{
|
|
int i, j, k, neighbor;
|
|
|
|
for (i = 0; i < n_left; i++) {
|
|
for (j = pointers[i]; j < pointers[i + 1]; j++) {
|
|
neighbor = indices[j];
|
|
if (neighbor < n_left || neighbor >= n_left + n_right) {
|
|
printf("Bad edge (%d, %d)\n", i, neighbor);
|
|
}
|
|
/* Check for counter-edge */
|
|
for (k = pointers[neighbor]; k < pointers[neighbor + 1]; k++) {
|
|
if (indices[k] == i) {
|
|
break;
|
|
}
|
|
}
|
|
if (k == pointers[neighbor + 1]) {
|
|
printf("Flip edge (%d, %d) not found\n", k, i);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = n_left; i < n_left + n_right; i++) {
|
|
for (j = pointers[i]; j < pointers[i + 1]; j++) {
|
|
neighbor = indices[j];
|
|
if (neighbor < 0 || neighbor >= n_left) {
|
|
printf("Bad edge (%d, %d)\n", i, neighbor);
|
|
}
|
|
/* Check for counter-edge */
|
|
for (k = pointers[neighbor]; k < pointers[neighbor + 1]; k++) {
|
|
if (indices[k] == i) {
|
|
break;
|
|
}
|
|
}
|
|
if (k == pointers[neighbor + 1]) {
|
|
printf("Flip edge (%d, %d) not found\n", k, i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void print_bpgraph(int nleft, int nright, int *pointers, int *indices, int *vwgts)
|
|
{
|
|
FILE *file;
|
|
int i, j, nedges, nvtxs;
|
|
|
|
nvtxs = nleft + nright;
|
|
nedges = (pointers[nvtxs] - pointers[0]) / 2;
|
|
|
|
file = fopen("BPGRAPH", "w");
|
|
|
|
fprintf(file, "%d %d\n", nvtxs, nedges);
|
|
|
|
for (i = 0; i < nvtxs; i++) {
|
|
if (vwgts != NULL) {
|
|
fprintf(file, "%d ", vwgts[i]);
|
|
}
|
|
for (j = pointers[i]; j < pointers[i + 1]; j++) {
|
|
fprintf(file, "%d ", indices[j]);
|
|
}
|
|
fprintf(file, "\n");
|
|
}
|
|
fclose(file);
|
|
}
|
|
|