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.

219 lines
7.6 KiB

2 years ago
/*
* Copyright(C) 1999-2020, 2022, 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 "params.h" // for MAXDIMS
#include "smalloc.h" // for sfree, smalloc
#include "structs.h" // for vtx_data
#include <stdio.h> // for NULL, fprintf, printf, etc
void sequence(struct vtx_data **graph, /* graph data structure */
int nvtxs, /* number of vertices in graph */
int nedges, /* number of edges in graph */
int using_ewgts, /* are edge weights being used? */
double *vwsqrt, /* sqrt of vertex weights (length nvtxs+1) */
int solver_flag, /* which eigensolver should I use? */
int rqi_flag, /* use multilevel eigensolver? */
int vmax, /* if so, how many vtxs to coarsen down to? */
double eigtol /* tolerance on eigenvectors */
)
{
extern char SEQ_FILENAME[]; /* name of sequence file */
extern int RQI_CONVERGENCE_MODE; /* residual or partition mode? */
extern int LANCZOS_CONVERGENCE_MODE; /* residual or partition mode? */
extern double sequence_time; /* time spent sequencing */
struct vtx_data **subgraph = NULL; /* subgraph data structure */
struct edgeslist *edge_list = NULL; /* edges added for connectivity */
double *yvecs[MAXDIMS + 1]; /* space for pointing to eigenvectors */
double evals[MAXDIMS + 1]; /* corresponding eigenvalues */
double *subvwsqrt = NULL; /* vwsqrt vector for subgraphs */
double *subvals = NULL; /* values for one connected component */
double goal[2]; /* needed for eigen convergence mode = 1 */
double total_vwgt; /* sum of all vertex weights */
float *term_wgts[2]; /* dummy vector for terminal weights */
int *setsize = NULL; /* size of each connected component */
int *glob2loc = NULL; /* maps graph vtxs to subgraph vtxs */
int *loc2glob = NULL; /* maps subgraph vtxs to graph vtxs */
int *subperm = NULL; /* partial permutation */
int *degree = NULL; /* degrees of vertices in subgraph */
double maxdeg; /* maximum weighted degree of a vertex */
int subnvtxs; /* number of vertices in subgraph */
int subnedges; /* number of edges in subgraph */
int maxsize; /* size of largest connected component */
int subvwgt_max; /* largest vertex weight in component */
int comp; /* loops over connected components */
int nused; /* number of vertices already handled */
int old_rqi_conv_mode; /* value of RQI_CONVERGENCE_MODE */
int old_lan_conv_mode; /* value of LANCZOS_CONVERGENCE_MODE */
int i; /* loop counters */
FILE *orderfile = NULL;
double time = seconds();
int using_vwgts = (vwsqrt != NULL);
/* Sort each connected component separately. */
int *compnum = smalloc((nvtxs + 1) * sizeof(int));
int *permutation = smalloc(nvtxs * sizeof(int));
double *values = smalloc((nvtxs + 1) * sizeof(double));
int *space = smalloc(nvtxs * sizeof(int));
int ncomps = find_edges(graph, nvtxs, compnum, space, &edge_list);
++ncomps;
free_edgeslist(edge_list);
yvecs[1] = smalloc((nvtxs + 1) * sizeof(double));
term_wgts[1] = NULL;
old_rqi_conv_mode = RQI_CONVERGENCE_MODE;
old_lan_conv_mode = LANCZOS_CONVERGENCE_MODE;
RQI_CONVERGENCE_MODE = 0;
LANCZOS_CONVERGENCE_MODE = 0;
maxsize = nvtxs;
if (ncomps > 1) {
/* Find size of largest set. */
setsize = smalloc(ncomps * sizeof(int));
for (comp = 0; comp < ncomps; comp++) {
setsize[comp] = 0;
}
for (i = 1; i <= nvtxs; i++) {
++setsize[compnum[i]];
}
maxsize = 0;
for (comp = 0; comp < ncomps; comp++) {
if (setsize[comp] > maxsize) {
maxsize = setsize[comp];
}
}
glob2loc = smalloc((nvtxs + 1) * sizeof(int));
loc2glob = smalloc((maxsize + 1) * sizeof(int));
subgraph = smalloc((maxsize + 1) * sizeof(struct vtx_data *));
degree = smalloc((maxsize + 1) * sizeof(int));
if (using_vwgts) {
subvwsqrt = smalloc((maxsize + 1) * sizeof(double));
}
}
nused = 0;
for (comp = 0; comp < ncomps; comp++) {
subperm = &(permutation[nused]);
subvals = &(values[nused]);
if (ncomps > 1) {
make_maps2(compnum, nvtxs, comp, glob2loc, loc2glob);
subnvtxs = setsize[comp];
make_subgraph(graph, subgraph, subnvtxs, &subnedges, compnum, comp, glob2loc, loc2glob,
degree, using_ewgts);
if (using_vwgts) {
make_subvector(vwsqrt, subvwsqrt, subnvtxs, loc2glob);
}
}
else {
subgraph = graph;
subnvtxs = nvtxs;
subnedges = nedges;
subvwsqrt = vwsqrt;
}
if (using_vwgts) {
subvwgt_max = 0;
total_vwgt = 0;
for (i = 1; i <= subnvtxs; i++) {
if (subgraph[i]->vwgt > subvwgt_max) {
subvwgt_max = subgraph[i]->vwgt;
}
total_vwgt += subgraph[i]->vwgt;
}
}
else {
subvwgt_max = 1;
total_vwgt = subnvtxs;
}
goal[0] = goal[1] = total_vwgt / 2;
if (subnvtxs == 1) {
yvecs[1][1] = 0;
}
else {
maxdeg = find_maxdeg(subgraph, subnvtxs, using_ewgts, (float *)NULL);
eigensolve(subgraph, subnvtxs, subnedges, maxdeg, subvwgt_max, subvwsqrt, using_vwgts,
using_ewgts, term_wgts, 0, (float **)NULL, yvecs, evals, 0, space, goal,
solver_flag, rqi_flag, vmax, 1, 3, eigtol);
/* Sort values in eigenvector */
if (using_vwgts) {
y2x(yvecs, 1, subnvtxs, subvwsqrt);
}
ch_mergesort(&(yvecs[1][1]), subnvtxs, subperm, space);
}
if (ncomps > 1) {
remake_graph(subgraph, subnvtxs, loc2glob, degree, using_ewgts);
for (i = 0; i < subnvtxs; i++) {
subvals[i] = yvecs[1][subperm[i] + 1];
subperm[i] = loc2glob[subperm[i] + 1];
}
}
else {
for (i = 0; i < nvtxs; i++) {
++subperm[i];
}
}
nused += subnvtxs;
}
/* Turn off timer. */
sequence_time += seconds() - time;
/* Print the ordering to a file. */
/* Note that permutation is 1<->n. */
orderfile = fopen(SEQ_FILENAME, "w");
if (ncomps == 1) {
for (i = 0; i < nvtxs; i++) {
fprintf(orderfile, "%-7d %9.6f\n", permutation[i], yvecs[1][permutation[i]]);
}
}
else {
for (i = 0; i < nvtxs; i++) {
fprintf(orderfile, "%-7d %9.6f\n", permutation[i], values[i]);
}
}
fclose(orderfile);
RQI_CONVERGENCE_MODE = old_rqi_conv_mode;
LANCZOS_CONVERGENCE_MODE = old_lan_conv_mode;
if (ncomps > 1) {
sfree(degree);
sfree(subgraph);
sfree(loc2glob);
sfree(glob2loc);
sfree(setsize);
if (using_vwgts) {
sfree(subvwsqrt);
}
}
sfree(yvecs[1]);
sfree(space);
sfree(values);
sfree(permutation);
sfree(compnum);
printf("%d connected components found\n", ncomps);
printf("Sequence printed to file `%s'\n", SEQ_FILENAME);
}