Cloned SEACAS for EXODUS library with extra build files for internal package management.
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

/*
* 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);
}