/* * 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 "chaco.h" #include "defs.h" // for FALSE, TRUE #include "prototypes.h" #include "smalloc.h" // for sfree, smalloc_ret #include "structs.h" #include // for NULL, printf, fclose, fopen, etc #include // for free extern int submain(struct vtx_data **graph, int nvtxs, int nedges, int using_vwgts, int using_ewgts, int igeom, float **coords, char *outassignname, char *outfilename, int *assignment, double *goal, int architecture, int ndims_tot, int mesh_dims[3], int global_method, int local_method, int rqi_flag, int vmax, int ndims, double eigtol, long seed); int Using_Main = FALSE; /* Is main routine being called? */ int INTER_FACE(int nvtxs, /* number of vertices in full graph */ int *start, /* start of edge list for each vertex */ int *adjacency, /* edge list data */ int *vwgts, /* weights for all vertices */ float *ewgts, /* weights for all edges */ float *x, float *y, float *z, /* coordinates for inertial method */ char *outassignname, /* name of assignment output file */ char *outfilename, /* output file name */ int *assignment, /* set number of each vtx (length n) */ int architecture, /* 0 => hypercube, d => d-dimensional mesh */ int ndims_tot, /* total number of cube dimensions to divide */ int mesh_dims[3], /* dimensions of mesh of processors */ double *goal, /* desired set sizes for each set */ int global_method, /* global partitioning algorithm */ int local_method, /* local partitioning algorithm */ int rqi_flag, /* should I use RQI/Symmlq eigensolver? */ int vmax, /* how many vertices to coarsen down to? */ int ndims, /* number of eigenvectors (2^d sets) */ double eigtol, /* tolerance on eigenvectors */ long seed /* for random graph mutations */ ) { extern char *PARAMS_FILENAME; /* name of file with parameter updates */ extern int MAKE_VWGTS; /* make vertex weights equal to degrees? */ extern int MATCH_TYPE; /* matching routine to use */ extern int FREE_GRAPH; /* free graph data structure after reformat? */ extern int DEBUG_PARAMS; /* debug flag for reading parameters */ extern int DEBUG_TRACE; /* trace main execution path */ extern double start_time; /* time routine is entered */ extern double reformat_time; /* time spent reformatting graph */ FILE *params_file = NULL; /* file for reading new parameters */ struct vtx_data **graph; /* graph data structure */ double vwgt_sum; /* sum of vertex weights */ double time; /* timing variable */ float **coords; /* coordinates for vertices if used */ int *vptr; /* loops through vertex weights */ int flag; /* return code from balance */ int nedges; /* number of edges in graph */ int using_vwgts; /* are vertex weights being used? */ int using_ewgts; /* are edge weights being used? */ int nsets_tot = 0; /* total number of sets being created */ int igeom; /* geometric dimension for inertial method */ int default_goal; /* using default goals? */ int i; /* loop counter */ double seconds(void); if (DEBUG_TRACE > 0) { printf("\n"); } flag = 0; graph = NULL; coords = NULL; if (!Using_Main) { /* If not using main, need to read parameters file. */ start_time = seconds(); params_file = fopen(PARAMS_FILENAME, "r"); if (params_file == NULL && DEBUG_PARAMS > 1) { printf("Parameter file `%s' not found; using default parameters.\n", PARAMS_FILENAME); } read_params(params_file); } if (goal == NULL) { /* If not passed in, default goals have equal set sizes. */ default_goal = TRUE; if (architecture == 0) { nsets_tot = 1 << ndims_tot; } else if (architecture == 1) { nsets_tot = mesh_dims[0]; } else if (architecture == 2) { nsets_tot = mesh_dims[0] * mesh_dims[1]; } else if (architecture > 2) { nsets_tot = mesh_dims[0] * mesh_dims[1] * mesh_dims[2]; } if (MAKE_VWGTS && start != NULL) { vwgt_sum = start[nvtxs] - start[0] + nvtxs; } else if (vwgts == NULL) { vwgt_sum = nvtxs; } else { vwgt_sum = 0; vptr = vwgts; for (i = nvtxs; i; i--) { vwgt_sum += *(vptr++); } } if (nsets_tot > 0) { vwgt_sum /= nsets_tot; } goal = smalloc_ret(nsets_tot * sizeof(double)); if (goal == NULL) { strout("\nERROR: No room to make goals.\n"); flag = 1; goto skip; } for (i = 0; i < nsets_tot; i++) { goal[i] = vwgt_sum; } } else { default_goal = FALSE; } if (MAKE_VWGTS) { /* Generate vertex weights equal to degree of node. */ if (vwgts != NULL) { strout("WARNING: Vertex weights being overwritten by vertex degrees."); } vwgts = smalloc_ret(nvtxs * sizeof(int)); if (vwgts == NULL) { strout("\nERROR: No room to make vertex weights.\n"); flag = 1; goto skip; } if (start != NULL) { for (i = 0; i < nvtxs; i++) { vwgts[i] = 1 + start[i + 1] - start[i]; } } else { for (i = 0; i < nvtxs; i++) { vwgts[i] = 1; } } } using_vwgts = (vwgts != NULL); using_ewgts = (ewgts != NULL); if (start != NULL || vwgts != NULL) { /* Reformat into our data structure. */ time = seconds(); flag = reformat(start, adjacency, nvtxs, &nedges, vwgts, ewgts, &graph); if (flag) { strout("\nERROR: No room to reformat graph.\n"); goto skip; } reformat_time += seconds() - time; } else { nedges = 0; } if (FREE_GRAPH) { /* Free old graph data structures. */ sfree(start); start = NULL; sfree(adjacency); adjacency = NULL; sfree(vwgts); vwgts = NULL; sfree(ewgts); ewgts = NULL; } if (global_method == 3 || (MATCH_TYPE == 5 && (global_method == 1 || (global_method == 2 && rqi_flag)))) { if (x == NULL) { igeom = 0; } else { /* Set up coordinate data structure. */ coords = smalloc_ret(3 * sizeof(float *)); if (coords == NULL) { strout("\nERROR: No room to make coordinate array.\n"); flag = 1; goto skip; } /* Minus 1's are to allow remainder of program to index with 1. */ coords[0] = x - 1; igeom = 1; if (y != NULL) { coords[1] = y - 1; igeom = 2; if (z != NULL) { coords[2] = z - 1; igeom = 3; } } } } else { igeom = 0; } /* Subtract from assignment to allow code to index from 1. */ assignment = assignment - 1; flag = submain(graph, nvtxs, nedges, using_vwgts, using_ewgts, igeom, coords, outassignname, outfilename, assignment, goal, architecture, ndims_tot, mesh_dims, global_method, local_method, rqi_flag, vmax, ndims, eigtol, seed); skip: sfree(coords); if (default_goal) { sfree(goal); } if (graph != NULL) { free_graph(graph); } if (flag && FREE_GRAPH) { sfree(start); sfree(adjacency); sfree(vwgts); sfree(ewgts); } if (!Using_Main && params_file != NULL) { fclose(params_file); } return (flag); }