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.
130 lines
4.3 KiB
130 lines
4.3 KiB
/*
|
|
* Copyright(C) 1999-2020, 2023 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 "defs.h" // for FALSE, TRUE
|
|
#include "smalloc.h" // for sfree, smalloc
|
|
#include "structs.h" // for vtx_data
|
|
|
|
int flatten(struct vtx_data **graph, /* array of vtx data for graph */
|
|
int nvtxs, /* number of vertices in graph */
|
|
int nedges, /* number of edges in graph */
|
|
struct vtx_data ***pcgraph, /* coarsened version of graph */
|
|
int *pcnvtxs, /* number of vtxs in coarsened graph */
|
|
int *pcnedges, /* number of edges in coarsened graph */
|
|
int **pv2cv, /* pointer to v2cv */
|
|
int using_ewgts, /* are edge weights being used? */
|
|
int igeom, /* dimensions of geometric data */
|
|
float **coords, /* coordinates for vertices */
|
|
float **ccoords /* coordinates for coarsened vertices */
|
|
)
|
|
{
|
|
double Thresh; /* minimal acceptable size reduction */
|
|
int *v2cv; /* map from vtxs to coarse vtxs */
|
|
int cnvtxs; /* number of vertices in flattened graph */
|
|
|
|
Thresh = .9;
|
|
|
|
v2cv = smalloc((nvtxs + 1) * sizeof(int));
|
|
|
|
find_flat(graph, nvtxs, &cnvtxs, v2cv);
|
|
|
|
if (cnvtxs <= Thresh * nvtxs) { /* Sufficient shrinkage? */
|
|
makefgraph(graph, nvtxs, nedges, pcgraph, cnvtxs, pcnedges, v2cv, using_ewgts, igeom, coords,
|
|
ccoords);
|
|
|
|
*pcnvtxs = cnvtxs;
|
|
*pv2cv = v2cv;
|
|
return (TRUE);
|
|
}
|
|
|
|
/* Not worth bothering */
|
|
sfree(v2cv);
|
|
return (FALSE);
|
|
}
|
|
|
|
void find_flat(struct vtx_data **graph, /* data structure for storing graph */
|
|
int nvtxs, /* number of vertices in graph */
|
|
int *pcnvtxs, /* number of coarse vertices */
|
|
int *v2cv /* map from vtxs to coarse vtxs */
|
|
)
|
|
{
|
|
/* Look for cliques with the same neighbor set. These are matrix */
|
|
/* rows corresponding to multiple degrees of freedom on a node. */
|
|
/* They can be flattened out, generating a smaller graph. */
|
|
|
|
int *scatter; /* for checking neighbor list identity */
|
|
int *hash; /* hash value for each vertex */
|
|
int this_hash; /* particular hash value */
|
|
int neighbor; /* neighbor of a vertex */
|
|
int cnvtxs; /* number of distinct vertices */
|
|
int i, j; /* loop counters */
|
|
|
|
hash = smalloc((nvtxs + 1) * sizeof(int));
|
|
scatter = smalloc((nvtxs + 1) * sizeof(int));
|
|
|
|
/* compute hash values */
|
|
|
|
for (i = 1; i <= nvtxs; i++) {
|
|
this_hash = i;
|
|
for (j = 1; j < graph[i]->nedges; j++) {
|
|
this_hash += graph[i]->edges[j];
|
|
}
|
|
hash[i] = this_hash;
|
|
}
|
|
|
|
for (i = 1; i <= nvtxs; i++) {
|
|
v2cv[i] = 0;
|
|
scatter[i] = 0;
|
|
}
|
|
|
|
/* Find supernodes. */
|
|
cnvtxs = 0;
|
|
|
|
for (i = 1; i <= nvtxs; i++) {
|
|
if (v2cv[i] == 0) { /* Not yet flattened. */
|
|
v2cv[i] = ++cnvtxs;
|
|
for (j = 1; j < graph[i]->nedges; j++) {
|
|
neighbor = graph[i]->edges[j];
|
|
if (neighbor > i && hash[neighbor] == hash[i] && /* same hash value */
|
|
graph[i]->nedges == graph[neighbor]->nedges && /* same degree */
|
|
v2cv[neighbor] == 0 && /* neighbor not flattened */
|
|
SameStructure(i, neighbor, graph, scatter)) {
|
|
v2cv[neighbor] = cnvtxs;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
*pcnvtxs = cnvtxs;
|
|
|
|
sfree(scatter);
|
|
sfree(hash);
|
|
}
|
|
|
|
int SameStructure(int node1, int node2, /* two vertices which might have same nonzeros */
|
|
struct vtx_data **graph, /* data structure for storing graph */
|
|
int *scatter /* array for checking vertex labelling */
|
|
)
|
|
{
|
|
int same; /* are two vertices indistinguisable? */
|
|
int i; /* loop counter */
|
|
|
|
scatter[node1] = node1;
|
|
for (i = 1; i < graph[node1]->nedges; i++) {
|
|
scatter[graph[node1]->edges[i]] = node1;
|
|
}
|
|
|
|
for (i = 1; i < graph[node2]->nedges; i++) {
|
|
if (scatter[graph[node2]->edges[i]] != node1) {
|
|
break;
|
|
}
|
|
}
|
|
same = (i == graph[node2]->nedges && scatter[node2] == node1);
|
|
|
|
return (same);
|
|
}
|
|
|