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.
490 lines
18 KiB
490 lines
18 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 "defs.h"
|
|
#include "params.h"
|
|
#include "structs.h"
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
|
|
static int check_params(int global_method, /* global partitioning algorithm */
|
|
int local_method, /* local partitioning algorithm */
|
|
int rqi_flag, /* use multilevel eigensolver? */
|
|
int ndims /* number of eigenvectors */);
|
|
|
|
static int check_assignment(int *assignment, /* set numbers if read-from-file */
|
|
int nvtxs, /* number of vertices */
|
|
int nsets_tot, /* total number of desired sets */
|
|
int ndims, /* partitioning level */
|
|
int local_method /* local partitioning algorithm */
|
|
);
|
|
|
|
/* Check graph and input options and parameters. */
|
|
int check_input(struct vtx_data **graph, /* linked lists of vertex data */
|
|
int nvtxs, /* number of vertices */
|
|
int nedges, /* number of edges */
|
|
int igeom, /* geometric dimension for inertial method */
|
|
float **coords, /* coordinates for inertial method */
|
|
char *graphname, /* graph input file name */
|
|
int *assignment, /* set numbers if read-from-file */
|
|
double *goal, /* desired sizes of different sets */
|
|
int architecture, /* 0=> hypercube, d=> d-dimensional mesh */
|
|
int ndims_tot, /* number of hypercube dimensions */
|
|
int mesh_dims[3], /* size of mesh in each dimension */
|
|
int global_method, /* global partitioning algorithm */
|
|
int local_method, /* local partitioning algorithm */
|
|
int rqi_flag, /* flag for RQI/symmlq eigensolver */
|
|
int *vmax, /* smallest acceptable coarsened nvtxs */
|
|
int ndims, /* partitioning level */
|
|
double eigtol /* tolerance for eigen-pairs */
|
|
)
|
|
{
|
|
extern FILE *Output_File; /* output file or null */
|
|
extern int DEBUG_TRACE; /* trace main execution path? */
|
|
extern int MATCH_TYPE; /* which type of contraction matching to use? */
|
|
double vwgt_sum, vwgt_sum2; /* sums of values in vwgts and goals */
|
|
int flag; /* does input data pass all the tests? */
|
|
int flag_graph; /* does graph check out OK? */
|
|
int flag_params; /* do params look OK? */
|
|
int flag_assign; /* does assignment look good? */
|
|
int nprocs = 0; /* number of processors partitioning for */
|
|
int i; /* loop counter */
|
|
|
|
if (DEBUG_TRACE > 0) {
|
|
printf("<Entering check_input>\n");
|
|
}
|
|
|
|
/* First check for consistency in the graph. */
|
|
if (graph != NULL) {
|
|
flag_graph = check_graph(graph, nvtxs, nedges);
|
|
if (flag_graph) {
|
|
if (graphname != NULL) {
|
|
printf("ERRORS in graph input file %s.\n", graphname);
|
|
}
|
|
if (Output_File != NULL) {
|
|
fprintf(Output_File, "ERRORS in graph input file %s.\n", graphname);
|
|
}
|
|
else {
|
|
printf("ERRORS in graph.\n");
|
|
}
|
|
if (Output_File != NULL) {
|
|
fprintf(Output_File, "ERRORS in graph.\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
else {
|
|
/* Only allowed if simple or inertial w/o KL and no weights. */
|
|
flag_graph = FALSE;
|
|
if (global_method == 1 || global_method == 2 || local_method == 1) {
|
|
printf("No graph input. Only allowed for inertial or simple methods without KL.\n");
|
|
flag_graph = TRUE;
|
|
}
|
|
}
|
|
|
|
/* Now check the input values. */
|
|
flag = FALSE;
|
|
flag_assign = FALSE;
|
|
|
|
if (architecture < 0 || architecture > 3) {
|
|
printf("Machine architecture parameter = %d, must be in [0,3].\n", architecture);
|
|
flag = TRUE;
|
|
}
|
|
|
|
else if (architecture == 0) {
|
|
if (ndims_tot < 0) {
|
|
printf("Dimension of hypercube = %d, must be at least 1.\n", ndims_tot);
|
|
flag = TRUE;
|
|
}
|
|
}
|
|
|
|
else if (architecture > 0) {
|
|
if (architecture == 1 && mesh_dims[0] <= 0) {
|
|
printf("Size of 1-D mesh improperly specified, %d.\n", mesh_dims[0]);
|
|
flag = TRUE;
|
|
}
|
|
if (architecture == 2 && (mesh_dims[0] <= 0 || mesh_dims[1] <= 0)) {
|
|
printf("Size of 2-D mesh improperly specified, %dx%d.\n", mesh_dims[0], mesh_dims[1]);
|
|
flag = TRUE;
|
|
}
|
|
if (architecture == 2 && (mesh_dims[0] <= 0 || mesh_dims[1] <= 0 || mesh_dims[2] <= 0)) {
|
|
printf("Size of 3-D mesh improperly specified, %dx%dx%d.\n", mesh_dims[0], mesh_dims[1],
|
|
mesh_dims[2]);
|
|
flag = TRUE;
|
|
}
|
|
}
|
|
|
|
if (ndims < 1 || ndims > MAXDIMS) {
|
|
printf("Partitioning at each step = %d, should be in [1,%d].\n", ndims, MAXDIMS);
|
|
flag = TRUE;
|
|
}
|
|
|
|
if (architecture == 0) {
|
|
if (!flag) {
|
|
nprocs = 1 << ndims_tot;
|
|
}
|
|
}
|
|
else if (architecture > 0) {
|
|
nprocs = mesh_dims[0] * mesh_dims[1] * mesh_dims[2];
|
|
}
|
|
if (1 << ndims > nprocs) {
|
|
printf("Partitioning step %d too large for %d processors.\n", ndims, nprocs);
|
|
flag = TRUE;
|
|
}
|
|
|
|
if (global_method < 1 || global_method > 7) {
|
|
printf("Global partitioning method = %d, must be in [1,7].\n", global_method);
|
|
flag = TRUE;
|
|
}
|
|
|
|
if (local_method < 1 || local_method > 2) {
|
|
printf("Local partitioning method = %d, must be in [1,2].\n", local_method);
|
|
flag = TRUE;
|
|
}
|
|
|
|
if (global_method == 1 || (global_method == 2 && rqi_flag)) {
|
|
i = 2 * (1 << ndims);
|
|
if (*vmax < i) {
|
|
printf("WARNING: Number of vertices in coarse graph (%d) being reset to %d.\n", *vmax, i);
|
|
if (Output_File != NULL) {
|
|
fprintf(Output_File,
|
|
"WARNING: Number of vertices in coarse graph (%d) being reset to %d.\n", *vmax, i);
|
|
}
|
|
*vmax = i;
|
|
}
|
|
}
|
|
|
|
if ((global_method == 1 || global_method == 2) && eigtol <= 0) {
|
|
printf("Eigen tolerance (%g) must be positive value\n", eigtol);
|
|
flag = TRUE;
|
|
}
|
|
|
|
if (global_method == 3 ||
|
|
(MATCH_TYPE == 5 && (global_method == 1 || (global_method == 2 && rqi_flag)))) {
|
|
if (igeom < 1 || igeom > 3) {
|
|
printf("Geometry must be 1-, 2- or 3-dimensional\n");
|
|
flag = TRUE;
|
|
}
|
|
if (igeom > 0 && coords == NULL) {
|
|
printf("No coordinates given\n");
|
|
flag = FALSE;
|
|
}
|
|
else if (igeom > 0 && coords[0] == NULL) {
|
|
printf("No X-coordinates given\n");
|
|
flag = TRUE;
|
|
}
|
|
else if (igeom > 1 && coords[1] == NULL) {
|
|
printf("No Y-coordinates given\n");
|
|
flag = TRUE;
|
|
}
|
|
else if (igeom > 2 && coords[2] == NULL) {
|
|
printf("No Z-coordinates given\n");
|
|
flag = TRUE;
|
|
}
|
|
}
|
|
|
|
if (global_method == 7 && local_method == 1) {
|
|
if (nprocs > 1 << ndims) {
|
|
printf("Can only use local method on single level of read-in assignment,\n");
|
|
printf(" but ndims = %d, while number of processors = %d.\n", ndims, nprocs);
|
|
flag = TRUE;
|
|
}
|
|
}
|
|
|
|
/* Now check for consistency in the goal array. */
|
|
if (graph != NULL) {
|
|
vwgt_sum = 0;
|
|
for (i = 1; i <= nvtxs; i++) {
|
|
vwgt_sum += graph[i]->vwgt;
|
|
}
|
|
}
|
|
else {
|
|
vwgt_sum = nvtxs;
|
|
}
|
|
|
|
vwgt_sum2 = 0;
|
|
for (i = 0; i < nprocs; i++) {
|
|
if (goal[i] < 0) {
|
|
printf("goal[%d] is %g, but should be nonnegative.\n", i, goal[i]);
|
|
flag = TRUE;
|
|
}
|
|
vwgt_sum2 += goal[i];
|
|
}
|
|
|
|
if (fabs(vwgt_sum - vwgt_sum2) > 1e-5 * (vwgt_sum + vwgt_sum2)) {
|
|
printf("Sum of values in goal (%g) not equal to sum of vertex weights (%g).\n", vwgt_sum2,
|
|
vwgt_sum);
|
|
flag = TRUE;
|
|
}
|
|
|
|
/* Check assignment file if read in. */
|
|
if (global_method == 7 && !flag) {
|
|
flag_assign = check_assignment(assignment, nvtxs, nprocs, ndims, local_method);
|
|
}
|
|
|
|
/* Add some checks for model parameters */
|
|
|
|
/* Finally, check the parameters. */
|
|
flag_params = check_params(global_method, local_method, rqi_flag, ndims);
|
|
|
|
flag = flag || flag_graph || flag_assign || flag_params;
|
|
|
|
return (flag);
|
|
}
|
|
|
|
static int check_params(int global_method, /* global partitioning algorithm */
|
|
int local_method, /* local partitioning algorithm */
|
|
int rqi_flag, /* use multilevel eigensolver? */
|
|
int ndims /* number of eigenvectors */
|
|
)
|
|
{
|
|
extern FILE *Output_File; /* Output file or null */
|
|
extern int ECHO; /* print input/param options? to file? (-2..2) */
|
|
extern int EXPERT; /* is user an expert? */
|
|
extern int OUTPUT_METRICS; /* controls formatting of output */
|
|
extern int OUTPUT_TIME; /* at what level to display timing */
|
|
|
|
extern int LANCZOS_TYPE; /* type of Lanczos to use */
|
|
extern double EIGEN_TOLERANCE; /* eigen-tolerance convergence criteria */
|
|
extern int LANCZOS_SO_INTERVAL; /* interval between orthog checks in SO */
|
|
extern double BISECTION_SAFETY; /* divides Lanczos bisection tol */
|
|
extern int LANCZOS_CONVERGENCE_MODE; /* Lanczos convergence test type */
|
|
extern int RQI_CONVERGENCE_MODE; /* rqi convergence test type: */
|
|
extern double WARNING_ORTHTOL; /* warn if Ares/bjitol this big */
|
|
extern double WARNING_MISTOL; /* warn if Ares/bjitol this big */
|
|
extern int LANCZOS_SO_PRECISION; /* single or double precision? */
|
|
|
|
extern int PERTURB; /* randomly perturb matrix in spectral method? */
|
|
extern int NPERTURB; /* if so, how many edges to modify? */
|
|
extern double PERTURB_MAX; /* largest value for perturbation */
|
|
extern int MAPPING_TYPE; /* how to map from eigenvectors to partition */
|
|
extern int COARSE_NLEVEL_RQI; /* levels between RQI calls */
|
|
extern int OPT3D_NTRIES; /* # local opts to look for global min in opt3d */
|
|
|
|
extern int KL_METRIC; /* KL interset cost: 1=>cuts, 2=>hops */
|
|
extern int KL_BAD_MOVES; /* number of unhelpful moves in a row allowed */
|
|
extern int KL_NTRIES_BAD; /* # unhelpful passes before quitting KL */
|
|
extern double KL_IMBALANCE; /* allowed imbalance in KL */
|
|
|
|
extern double COARSEN_RATIO_MIN; /* required coarsening reduction */
|
|
extern int COARSE_NLEVEL_KL; /* # levels between KL calls in uncoarsening */
|
|
extern int MATCH_TYPE; /* which type of contraction matching to use? */
|
|
|
|
extern int SIMULATOR; /* simulate the communication? */
|
|
|
|
extern int TERM_PROP; /* perform terminal propagation? */
|
|
extern double CUT_TO_HOP_COST; /* ..if so, relative cut/hop importance */
|
|
int flag_params;
|
|
|
|
flag_params = FALSE;
|
|
if (ECHO < -2 || ECHO > 2) {
|
|
printf("ECHO (%d) should be in [-2,2].\n", ECHO);
|
|
flag_params = TRUE;
|
|
}
|
|
|
|
if (OUTPUT_METRICS < -2 || OUTPUT_METRICS > 2) {
|
|
printf("WARNING: OUTPUT_METRICS (%d) should be in [-2,2].\n", OUTPUT_METRICS);
|
|
if (Output_File != NULL) {
|
|
fprintf(Output_File, "WARNING: OUTPUT_METRICS (%d) should be in [-2,2].\n", OUTPUT_METRICS);
|
|
}
|
|
}
|
|
if (OUTPUT_TIME < 0 || OUTPUT_TIME > 2) {
|
|
printf("WARNING: OUTPUT_TIME (%d) should be in [0,2].\n", OUTPUT_TIME);
|
|
if (Output_File != NULL) {
|
|
fprintf(Output_File, "WARNING: OUTPUT_TIME (%d) should be in [0,2].\n", OUTPUT_TIME);
|
|
}
|
|
}
|
|
|
|
if (global_method == 1 || global_method == 2) {
|
|
if (EXPERT) {
|
|
if (LANCZOS_TYPE < 1 || LANCZOS_TYPE > 4) {
|
|
printf("LANCZOS_TYPE (%d) should be in [1,4].\n", LANCZOS_TYPE);
|
|
flag_params = TRUE;
|
|
}
|
|
}
|
|
else {
|
|
if (LANCZOS_TYPE < 1 || LANCZOS_TYPE > 3) {
|
|
printf("LANCZOS_TYPE (%d) should be in [1,3].\n", LANCZOS_TYPE);
|
|
flag_params = TRUE;
|
|
}
|
|
}
|
|
if (EIGEN_TOLERANCE <= 0) {
|
|
printf("EIGEN_TOLERANCE (%g) should be positive.\n", EIGEN_TOLERANCE);
|
|
flag_params = TRUE;
|
|
}
|
|
if (LANCZOS_SO_INTERVAL <= 0) {
|
|
printf("LANCZOS_SO_INTERVAL (%d) should be positive.\n", LANCZOS_SO_INTERVAL);
|
|
flag_params = TRUE;
|
|
}
|
|
if (LANCZOS_SO_INTERVAL == 1) {
|
|
printf("WARNING: More efficient if LANCZOS_SO_INTERVAL = 2, not 1.\n");
|
|
if (Output_File != NULL) {
|
|
fprintf(Output_File, "WARNING: More efficient if LANCZOS_SO_INTERVAL = 2, not 1.\n");
|
|
}
|
|
}
|
|
if (BISECTION_SAFETY <= 0) {
|
|
printf("BISECTION_SAFETY (%g) should be positive.\n", BISECTION_SAFETY);
|
|
flag_params = TRUE;
|
|
}
|
|
if (LANCZOS_CONVERGENCE_MODE < 0 || LANCZOS_CONVERGENCE_MODE > 1) {
|
|
printf("LANCZOS_CONVERGENCE_MODE (%d) should be in [0,1].\n", LANCZOS_CONVERGENCE_MODE);
|
|
flag_params = TRUE;
|
|
}
|
|
|
|
if (WARNING_ORTHTOL == 0) {
|
|
printf("WARNING: WARNING_ORTHTOL (%g) should be positive.\n", WARNING_ORTHTOL);
|
|
if (Output_File != NULL) {
|
|
fprintf(Output_File, "WARNING: WARNING_ORTHTOL (%g) should be positive.\n",
|
|
WARNING_ORTHTOL);
|
|
}
|
|
}
|
|
if (WARNING_MISTOL == 0) {
|
|
printf("WARNING: WARNING_MISTOL (%g) should be positive.\n", WARNING_MISTOL);
|
|
if (Output_File != NULL) {
|
|
fprintf(Output_File, "WARNING: WARNING_MISTOL (%g) should be positive.\n", WARNING_MISTOL);
|
|
}
|
|
}
|
|
|
|
if (LANCZOS_SO_PRECISION < 1 || LANCZOS_SO_PRECISION > 2) {
|
|
printf("LANCZOS_SO_PRECISION (%d) should be in [1,2].\n", LANCZOS_SO_PRECISION);
|
|
flag_params = TRUE;
|
|
}
|
|
|
|
if (PERTURB) {
|
|
if (NPERTURB < 0) {
|
|
printf("NPERTURB (%d) should be nonnegative.\n", NPERTURB);
|
|
flag_params = TRUE;
|
|
}
|
|
if (NPERTURB > 0 && PERTURB_MAX < 0) {
|
|
printf("PERTURB_MAX (%g) should be nonnegative.\n", PERTURB_MAX);
|
|
flag_params = TRUE;
|
|
}
|
|
}
|
|
|
|
if (MAPPING_TYPE < 0 || MAPPING_TYPE > 3) {
|
|
printf("MAPPING_TYPE (%d) should be in [0,3].\n", MAPPING_TYPE);
|
|
flag_params = TRUE;
|
|
}
|
|
|
|
if (ndims == 3 && OPT3D_NTRIES <= 0) {
|
|
printf("OPT3D_NTRIES (%d) should be positive.\n", OPT3D_NTRIES);
|
|
flag_params = TRUE;
|
|
}
|
|
|
|
if (global_method == 2 && rqi_flag) {
|
|
if (COARSE_NLEVEL_RQI <= 0) {
|
|
printf("COARSE_NLEVEL_RQI (%d) should be positive.\n", COARSE_NLEVEL_RQI);
|
|
flag_params = TRUE;
|
|
}
|
|
|
|
if (RQI_CONVERGENCE_MODE < 0 || RQI_CONVERGENCE_MODE > 1) {
|
|
printf("RQI_CONVERGENCE_MODE (%d) should be in [0,1].\n", RQI_CONVERGENCE_MODE);
|
|
flag_params = TRUE;
|
|
}
|
|
|
|
if (TERM_PROP) {
|
|
printf("WARNING: Using default Lanczos for extended eigenproblem, not RQI/Symmlq.\n");
|
|
}
|
|
}
|
|
|
|
if (global_method == 1) {
|
|
if (COARSE_NLEVEL_KL <= 0) {
|
|
printf("COARSE_NLEVEL_KL (%d) should be positive.\n", COARSE_NLEVEL_KL);
|
|
flag_params = TRUE;
|
|
}
|
|
}
|
|
|
|
if (global_method == 1 || (global_method == 2 && rqi_flag)) {
|
|
if (COARSEN_RATIO_MIN < .5) {
|
|
printf("COARSEN_RATIO_MIN (%g) should be at least 1/2.\n", COARSEN_RATIO_MIN);
|
|
flag_params = TRUE;
|
|
}
|
|
if (MATCH_TYPE < 1 || MATCH_TYPE > 9) {
|
|
printf("MATCH_TYPE (%d) should be in [1,9].\n", MATCH_TYPE);
|
|
flag_params = TRUE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
if (global_method == 1 && LIMIT_KL_EWGTS && EWGT_RATIO_MAX <= 0) {
|
|
printf("EWGT_RATIO_MAX (%g) should be at positive.\n",
|
|
EWGT_RATIO_MAX);
|
|
flag_params = TRUE;
|
|
}
|
|
*/
|
|
}
|
|
|
|
if (global_method == 1 || local_method == 1) {
|
|
if (KL_METRIC < 1 || KL_METRIC > 2) {
|
|
printf("KL_METRIC (%d) should be in [0,1].\n", KL_METRIC);
|
|
flag_params = TRUE;
|
|
}
|
|
if (KL_BAD_MOVES < 0) {
|
|
printf("KL_BAD_MOVES (%d) should be non-negative.\n", KL_BAD_MOVES);
|
|
flag_params = TRUE;
|
|
}
|
|
if (KL_NTRIES_BAD < 0) {
|
|
printf("KL_NTRIES_BAD (%d) should be non-negative.\n", KL_NTRIES_BAD);
|
|
flag_params = TRUE;
|
|
}
|
|
if (KL_IMBALANCE < 0.0 || KL_IMBALANCE > 1.0) {
|
|
printf("KL_IMBALANCE (%g) should be in [0,1].\n", KL_IMBALANCE);
|
|
flag_params = TRUE;
|
|
}
|
|
}
|
|
|
|
if (SIMULATOR < 0 || SIMULATOR > 3) {
|
|
printf("SIMULATOR (%d) should be in [0,3].\n", SIMULATOR);
|
|
flag_params = TRUE;
|
|
}
|
|
|
|
if (TERM_PROP) {
|
|
if (CUT_TO_HOP_COST <= 0) {
|
|
printf("CUT_TO_HOP_COST (%g) should be positive.\n", CUT_TO_HOP_COST);
|
|
flag_params = TRUE;
|
|
}
|
|
if (ndims > 1) {
|
|
printf("WARNING: May ignore terminal propagation in spectral quadri/octa section\n");
|
|
}
|
|
}
|
|
|
|
return (flag_params);
|
|
}
|
|
|
|
static int check_assignment(int *assignment, /* set numbers if read-from-file */
|
|
int nvtxs, /* number of vertices */
|
|
int nsets_tot, /* total number of desired sets */
|
|
int ndims, /* partitioning level */
|
|
int local_method /* local partitioning algorithm */
|
|
)
|
|
{
|
|
int flag; /* return status */
|
|
int nsets; /* number of sets created at each level */
|
|
int i; /* loop counter */
|
|
|
|
nsets = 1 << ndims;
|
|
flag = FALSE;
|
|
|
|
for (i = 1; i <= nvtxs && !flag; i++) {
|
|
if (assignment[i] < 0) {
|
|
printf("Assignment[%d] = %d less than zero.\n", i, assignment[i]);
|
|
flag = TRUE;
|
|
}
|
|
else if (assignment[i] >= nsets_tot) {
|
|
printf("Assignment[%d] = %d, too large for %d sets.\n", i, assignment[i], nsets_tot);
|
|
flag = TRUE;
|
|
}
|
|
else if (local_method == 1 && assignment[i] >= nsets) {
|
|
printf("Can only use local method on single level of read-in assignment,\n");
|
|
printf(" but assignment[%d] = %d.\n", i, assignment[i]);
|
|
flag = TRUE;
|
|
}
|
|
}
|
|
|
|
return (flag);
|
|
}
|
|
|