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.
 
 
 
 
 
 

143 lines
5.6 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 "params.h" // for MAXSETS
#include "structs.h" // for bilist
#include <stdio.h> // for NULL
/* Perform KL between two sets. */
int kl_refine(struct vtx_data **graph, /* graph data structure */
struct vtx_data **subgraph, /* space for subgraph to refine */
struct bilist *set_list, /* lists of vtxs in each set */
struct bilist *vtx_elems, /* start of storage for lists */
int *new_assign, /* set assignments for all vertices */
int set1, int set2, /* two sets being refined */
int *glob2loc, /* maps vertices to subgraph vertices */
int *loc2glob, /* maps subgraph vertices to vertices */
int *sub_assign, /* new assignment for subgraphs */
int *old_sub_assign, /* current assignment for subgraphs */
int *degrees, /* space for forming subgraphs */
int using_ewgts, /* are edge weights being used? */
int (*hops)[MAXSETS], /* KL set preferences */
double *goal, /* desired set sizes */
int *sizes, /* number of vertices in different sets */
float *term_wgts[], /* space for terminal propagation weights */
int architecture, /* 0 => hypercube, d => d-dimensional mesh */
int mesh_dims[3] /* if mesh, how big is it? */
)
{
extern int TERM_PROP; /* perform terminal propagation? */
extern double KL_IMBALANCE; /* fractional imbalance allowed in KL */
struct bilist *ptr; /* element in set_list */
double subgoal[2]; /* goal within two subgraphs */
double weights[2] = {0.0, 0.0}; /* weights for each set */
double maxdeg; /* largest degree of a vertex */
double ratio; /* set sizes / goals */
int *null_ptr; /* argument to klspiff */
int vwgt_max; /* largest vertex weight */
int max_dev; /* largest set deviation allowed in KL */
int subnvtxs; /* number of vtxs in subgraph */
int vwgt_sum1; /* sum of vertex wgts in first set */
int vwgt_sum2; /* sum of vertex wgts in second set */
int subnedges; /* number of edges in subgraph */
int setA, setB; /* two sets being refined */
int nsame; /* number of vertices not moved */
int vtx; /* vertex in subgraph */
int i; /* loop counter */
/* Compute all the quantities I'll need. */
null_ptr = NULL;
make_maps_ref(graph, set_list, vtx_elems, new_assign, sub_assign, set1, set2, glob2loc, loc2glob,
&subnvtxs, &vwgt_max, &vwgt_sum1, &vwgt_sum2);
for (i = 1; i <= subnvtxs; i++) {
old_sub_assign[i] = sub_assign[i];
}
/* Set up goals for this KL invocation. */
ratio = (vwgt_sum1 + vwgt_sum2) / (goal[set1] + goal[set2]);
subgoal[0] = ratio * goal[set1];
subgoal[1] = ratio * goal[set2];
if (TERM_PROP) {
make_terms_ref(graph, using_ewgts, subnvtxs, loc2glob, set1, set2, new_assign, architecture,
mesh_dims, term_wgts);
}
/* New_assign has overwritten set2 with set1. */
make_subgraph(graph, subgraph, subnvtxs, &subnedges, new_assign, set1, glob2loc, loc2glob,
degrees, using_ewgts);
maxdeg = find_maxdeg(subgraph, subnvtxs, using_ewgts, (float *)NULL);
count_weights(subgraph, subnvtxs, sub_assign, 2, weights, (vwgt_max != 1));
max_dev = vwgt_max;
ratio = (subgoal[0] + subgoal[1]) * KL_IMBALANCE / 2;
if (ratio > max_dev) {
max_dev = ratio;
}
klspiff(subgraph, subnvtxs, sub_assign, 2, hops, subgoal, term_wgts, max_dev, maxdeg, using_ewgts,
&null_ptr, weights);
/* Figure out which modification leaves most vertices intact. */
nsame = 0;
for (i = 1; i <= subnvtxs; i++) {
if (old_sub_assign[i] == sub_assign[i]) {
nsame++;
}
}
if (2 * nsame > subnvtxs) {
setA = set1;
setB = set2;
}
else {
setA = set2;
setB = set1;
}
/* Now update the assignments. */
sizes[setA] = sizes[setB] = 0;
for (i = 1; i <= subnvtxs; i++) {
vtx = loc2glob[i];
/* Update the set_lists. */
ptr = &(vtx_elems[vtx]);
if (ptr->next != NULL) {
ptr->next->prev = ptr->prev;
}
if (ptr->prev != NULL) {
ptr->prev->next = ptr->next;
}
if (sub_assign[i] == 0) {
new_assign[vtx] = setA;
++sizes[setA];
ptr->next = set_list[setA].next;
if (ptr->next != NULL) {
ptr->next->prev = ptr;
}
ptr->prev = &(set_list[setA]);
set_list[setA].next = ptr;
}
else {
new_assign[vtx] = setB;
++sizes[setB];
ptr->next = set_list[setB].next;
if (ptr->next != NULL) {
ptr->next->prev = ptr;
}
ptr->prev = &(set_list[setB]);
set_list[setB].next = ptr;
}
}
remake_graph(subgraph, subnvtxs, loc2glob, degrees, using_ewgts);
return (nsame != subnvtxs);
}