int read_chaco_file(int Proc, int Num_Proc, PROB_INFO_PTR prob, PARIO_INFO_PTR pio_info, MESH_INFO_PTR mesh) { /* Local declarations. */ const char *yo = "read_chaco_mesh"; char cmesg[256]; char chaco_fname[FILENAME_MAX + 8]; int nvtxs, gnvtxs; int vwgt_dim=0, ewgt_dim=0; int ndim = 0; int *start = NULL, *adj = NULL; int no_geom = FALSE; float *ewgts = NULL, *vwgts = NULL; float *x = NULL, *y = NULL, *z = NULL; short *assignments = NULL; ZOLTAN_FILE *fp = NULL; int file_error; /***************************** BEGIN EXECUTION ******************************/ DEBUG_TRACE_START(Proc, yo); /* Set Debug_Chaco_Input */ if (Debug_Driver > 2) Debug_Chaco_Input = 1; if (Proc == 0) { /* Open and read the Chaco graph file. */ sprintf(chaco_fname, "%s.graph", pio_info->pexo_fname); fp = ZOLTAN_FILE_open(chaco_fname, "r", pio_info->file_comp); file_error = (fp == NULL); } MPI_Bcast(&file_error, 1, MPI_INT, 0, MPI_COMM_WORLD); if (file_error) { sprintf(cmesg, "fatal: Could not open Chaco graph file %s", chaco_fname); Gen_Error(0, cmesg); return 0; } if (Proc == 0) { /* read the array in on processor 0 */ if (chaco_input_graph(fp, chaco_fname, &start, &adj, &nvtxs, &vwgt_dim, &vwgts, &ewgt_dim, &ewgts) != 0) { Gen_Error(0, "fatal: Error returned from chaco_input_graph"); return 0; } /* Read Chaco geometry file, if provided. */ sprintf(chaco_fname, "%s.coords", pio_info->pexo_fname); fp = ZOLTAN_FILE_open(chaco_fname, "r", pio_info->file_comp); if (fp == NULL) { no_geom = TRUE; sprintf(cmesg, "warning: Could not open Chaco geometry file %s; " "no geometry data will be read", chaco_fname); Gen_Error(0, cmesg); } else { /* read the coordinates in on processor 0 */ if (chaco_input_geom(fp, chaco_fname, nvtxs, &ndim, &x, &y, &z) != 0) { Gen_Error(0, "fatal: Error returned from chaco_input_geom"); return 0; } } #ifdef MESS_UP_POINTS /* Try to create a geometry that isn't nicely symmetric */ { int i, j; double min[3], max[3], a[3], b[3]; min[0] = max[0] = x[0]; if (ndim > 1){ min[1] = max[1] = y[0]; if (ndim > 2) min[2] = max[2] = z[0]; } for (i=1; i<nvtxs; i++) { if (x[i] < min[0]) min[0] = x[i]; else if (x[i] > max[0]) max[0] = x[i]; if (ndim > 1){ if (y[i] < min[1]) min[1] = y[i]; else if (y[i] > max[1]) max[1] = y[i]; if (ndim > 2){ if (z[i] < min[2]) min[2] = z[i]; else if (z[i] > max[2]) max[2] = z[i]; } } } for (i=0; i<ndim; i++) /* point inside but near edge of geometry */ a[i] = ((max[i] - min[i]) * .1) + min[i]; for (i=0; i<nvtxs; i++) { /* move 2/3 of points much closer to "a" */ if (i%3 == 0) continue; b[0] = x[i]; if (ndim > 1){ b[1] = y[i]; if (ndim > 2){ b[2] = z[i]; } } for (j=0; j<ndim; j++){ b[j] = a[j] + ((b[j] - a[j])*.1); } x[i] = b[0]; if (ndim > 1){ y[i] = b[1]; if (ndim > 2){ z[i] = b[2]; } } } } #endif /* Read Chaco assignment file, if requested */ if (pio_info->init_dist_type == INITIAL_FILE) { sprintf(chaco_fname, "%s.assign", pio_info->pexo_fname); if (pio_info->file_comp == GZIP) sprintf(chaco_fname, "%s.gz", chaco_fname); fp = ZOLTAN_FILE_open(chaco_fname, "r", pio_info->file_comp); if (fp == NULL) { sprintf(cmesg, "Error: Could not open Chaco assignment file %s; " "initial distribution cannot be read", chaco_fname); Gen_Error(0, cmesg); return 0; } else { /* read the coordinates in on processor 0 */ assignments = (short *) malloc(nvtxs * sizeof(short)); if (!assignments) { Gen_Error(0, "fatal: insufficient memory"); return 0; } if (chaco_input_assign(fp, chaco_fname, nvtxs, assignments) != 0) { Gen_Error(0, "fatal: Error returned from chaco_input_assign"); return 0; } } } } /* Distribute graph */ if (!chaco_dist_graph(MPI_COMM_WORLD, pio_info, 0, &gnvtxs, &nvtxs, &start, &adj, &vwgt_dim, &vwgts, &ewgt_dim, &ewgts, &ndim, &x, &y, &z, &assignments) != 0) { Gen_Error(0, "fatal: Error returned from chaco_dist_graph"); return 0; } if (!chaco_setup_mesh_struct(Proc, Num_Proc, prob, mesh, gnvtxs, nvtxs, start, adj, vwgt_dim, vwgts, ewgt_dim, ewgts, ndim, x, y, z, assignments, 1, no_geom)) { Gen_Error(0, "fatal: Error returned from chaco_setup_mesh_struct"); return 0; } safe_free((void **)(void *) &adj); safe_free((void **)(void *) &vwgts); safe_free((void **)(void *) &ewgts); safe_free((void **)(void *) &start); safe_free((void **)(void *) &x); safe_free((void **)(void *) &y); safe_free((void **)(void *) &z); safe_free((void **)(void *) &assignments); DEBUG_TRACE_END(Proc, yo); return 1; }
/* Read from file and set up hypergraph. */ int read_hypergraph_file( int Proc, int Num_Proc, PROB_INFO_PTR prob, PARIO_INFO_PTR pio_info, MESH_INFO_PTR mesh ) { /* Local declarations. */ const char *yo = "read_hypergraph_file"; char cmesg[256]; int i, gnvtxs, distributed_pins = 0, edge, vertex, nextEdge; int nvtxs = 0, gnhedges = 0, nhedges = 0, npins = 0; int vwgt_dim=0, hewgt_dim=0, vtx, edgeSize, global_npins; int *hindex = NULL, *hvertex = NULL, *hvertex_proc = NULL; int *hgid = NULL; float *hewgts = NULL, *vwgts = NULL; ZOLTAN_FILE* fp = NULL; int base = 0; /* Smallest vertex number; usually zero or one. */ char filename[256]; /* Variables that allow graph-based functions to be reused. */ /* If no chaco.graph or chaco.coords files exist, values are NULL or 0, * since graph is not being built. If chaco.graph and/or chaco.coords * exist, these arrays are filled and values stored in mesh. * Including these files allows for comparison of HG methods with other * methods, along with visualization of results and comparison of * LB_Eval results. */ int ch_nvtxs = 0; /* Temporary values for chaco_read_graph. */ #ifdef KDDKDD int ch_vwgt_dim = 0; /* Their values are ignored, as vertex */ #endif float *ch_vwgts = NULL; /* info is provided by hypergraph file. */ int *ch_start = NULL, *ch_adj = NULL, ch_ewgt_dim = 0; short *ch_assignments = NULL; float *ch_ewgts = NULL; int ch_ndim = 0; float *ch_x = NULL, *ch_y = NULL, *ch_z = NULL; int ch_no_geom = TRUE; /* Assume no geometry info is given; reset if it is provided. */ int file_error = 0; /***************************** BEGIN EXECUTION ******************************/ DEBUG_TRACE_START(Proc, yo); if (Proc == 0) { /* Open and read the hypergraph file. */ if (pio_info->file_type == HYPERGRAPH_FILE) sprintf(filename, "%s.hg", pio_info->pexo_fname); else if (pio_info->file_type == MATRIXMARKET_FILE) sprintf(filename, "%s.mtx", pio_info->pexo_fname); else { sprintf(cmesg, "fatal: invalid file type %d", pio_info->file_type); Gen_Error(0, cmesg); return 0; } fp = ZOLTAN_FILE_open(filename, "r", pio_info->file_comp); file_error = (fp == NULL); } MPI_Bcast(&file_error, 1, MPI_INT, 0, MPI_COMM_WORLD); if (file_error) { sprintf(cmesg, "fatal: Could not open hypergraph file %s",pio_info->pexo_fname); Gen_Error(0, cmesg); return 0; } if (pio_info->file_type == HYPERGRAPH_FILE) { /* read the array in on processor 0 */ if (Proc == 0) { if (HG_readfile(Proc, fp, &nvtxs, &nhedges, &npins, &hindex, &hvertex, &vwgt_dim, &vwgts, &hewgt_dim, &hewgts, &base) != 0){ Gen_Error(0, "fatal: Error returned from HG_readfile"); return 0; } } } else if (pio_info->file_type == MATRIXMARKET_FILE) { /* * pio_info->chunk_reader == 0 (the usual case) * process 0 will read entire file in MM_readfile, * and will distribute vertices in chaco_dist_graph and pins in * dist_hyperedges later. (distributed_pins==0) * * pio_info->chunk_reader == 1 ("initial read = chunks" in zdrive.inp) * process 0 will read the file in chunks, and will send vertices * and pins to other processes before reading the next chunk, all * in MM_readfile. (distributed_pins==1) */ if (MM_readfile(Proc, Num_Proc, fp, pio_info, &nvtxs, /* global number of vertices */ &nhedges, /* global number of hyperedges */ &npins, /* local number of pins */ &hindex, &hvertex, &vwgt_dim, &vwgts, &hewgt_dim, &hewgts, &ch_start, &ch_adj, &ch_ewgt_dim, &ch_ewgts, &base, &global_npins)) { Gen_Error(0, "fatal: Error returned from MM_readfile"); return 0; } if (Proc == 0) ZOLTAN_FILE_close(fp); if ((Num_Proc > 1) && pio_info->chunk_reader && (global_npins > Num_Proc)){ distributed_pins = 1; } else{ distributed_pins = 0; } } #ifdef KDDKDD { /* If CHACO graph file is available, read it. */ sprintf(filename, "%s.graph", pio_info->pexo_fname); fp = ZOLTAN_FILE_open(filename, "r", pio_info->file_comp); file_error = #ifndef ZOLTAN_COMPRESS (fp == NULL); #else fp.error; #endif if (!file_error) { /* CHACO graph file is available. */ /* Assuming hypergraph vertices are same as chaco vertices. */ /* Chaco vertices and their weights are ignored in rest of function. */ if (chaco_input_graph(fp, filename, &ch_start, &ch_adj, &ch_nvtxs, &ch_vwgt_dim, &ch_vwgts, &ch_ewgt_dim, &ch_ewgts) != 0) { Gen_Error(0, "fatal: Error returned from chaco_input_graph"); return 0; } } else ch_nvtxs = nvtxs; /* If coordinate file is available, read it. */ sprintf(filename, "%s.coords", pio_info->pexo_fname); fp = ZOLTAN_FILE_open(filename, "r", pio_info->file_comp); file_error = #ifndef ZOLTAN_COMPRESS (fp == NULL); #else fp.error; #endif if (!file_error) { /* CHACO coordinates file is available. */ ch_no_geom = FALSE; if (chaco_input_geom(fpkdd, filename, ch_nvtxs, &ch_ndim, &ch_x, &ch_y, &ch_z) != 0) { Gen_Error(0, "fatal: Error returned from chaco_input_geom"); return 0; } } } #else /* KDDKDD */ ch_nvtxs = nvtxs; #endif /* KDDKDD */ { /* Read Chaco assignment file, if requested */ if (pio_info->init_dist_type == INITIAL_FILE) { sprintf(filename, "%s.assign", pio_info->pexo_fname); fp = ZOLTAN_FILE_open(filename, "r", pio_info->file_comp); if (fp == NULL) { sprintf(cmesg, "Error: Could not open Chaco assignment file %s; " "initial distribution cannot be read", filename); Gen_Error(0, cmesg); return 0; } else { /* read the coordinates in on processor 0 */ ch_assignments = (short *) malloc(nvtxs * sizeof(short)); if (nvtxs && !ch_assignments) { Gen_Error(0, "fatal: memory error in read_hypergraph_file"); return 0; } /* closes fpassign when done */ if (chaco_input_assign(fp, filename, ch_nvtxs, ch_assignments) != 0){ Gen_Error(0, "fatal: Error returned from chaco_input_assign"); return 0; } } } } MPI_Bcast(&base, 1, MPI_INT, 0, MPI_COMM_WORLD); if (distributed_pins){ gnhedges = nhedges; nhedges = 0; hewgt_dim = 0; hewgts = NULL; for (edge=0; edge<gnhedges; edge++){ edgeSize = hindex[edge+1] - hindex[edge]; if (edgeSize > 0) nhedges++; } hgid = (int *)malloc(nhedges * sizeof(int)); hvertex_proc = (int *)malloc(npins * sizeof(int)); nextEdge=0; vtx=0; for (edge=0; edge<gnhedges; edge++){ edgeSize = hindex[edge+1] - hindex[edge]; if (edgeSize > 0){ hgid[nextEdge] = edge+1; if (nextEdge < edge){ hindex[nextEdge+1] = hindex[nextEdge] + edgeSize; } for (vertex=0; vertex<edgeSize; vertex++,vtx++){ hvertex_proc[vtx] = ch_dist_proc(hvertex[vtx], NULL, 1); } nextEdge++; } } gnvtxs = nvtxs; nvtxs = ch_dist_num_vtx(Proc, NULL); if (ch_start){ /* need to include only vertices this process owns */ for (i=0,vertex=0; i<gnvtxs; i++){ if ((ch_start[i+1] > ch_start[vertex]) || /* vtx has adjacencies so it's mine */ (ch_dist_proc(i, NULL, 0) == Proc)) /* my vtx with no adjacencies */ { if (i > vertex){ ch_start[vertex+1] = ch_start[i+1]; } vertex++; } } } #if 0 debug_lists(Proc, Num_Proc, nhedges, hindex, hvertex, hvertex_proc, hgid); #endif } else{ /* Distribute hypergraph graph */ /* Use hypergraph vertex information and chaco edge information. */ if (!chaco_dist_graph(MPI_COMM_WORLD, pio_info, 0, &gnvtxs, &nvtxs, &ch_start, &ch_adj, &vwgt_dim, &vwgts, &ch_ewgt_dim, &ch_ewgts, &ch_ndim, &ch_x, &ch_y, &ch_z, &ch_assignments) != 0) { Gen_Error(0, "fatal: Error returned from chaco_dist_graph"); return 0; } if (!dist_hyperedges(MPI_COMM_WORLD, pio_info, 0, base, gnvtxs, &gnhedges, &nhedges, &hgid, &hindex, &hvertex, &hvertex_proc, &hewgt_dim, &hewgts, ch_assignments)) { Gen_Error(0, "fatal: Error returned from dist_hyperedges"); return 0; } } /* Initialize mesh structure for Hypergraph. */ mesh->data_type = HYPERGRAPH; mesh->num_elems = nvtxs; mesh->vwgt_dim = vwgt_dim; mesh->ewgt_dim = ch_ewgt_dim; mesh->elem_array_len = mesh->num_elems + 5; mesh->num_dims = ch_ndim; mesh->num_el_blks = 1; mesh->gnhedges = gnhedges; mesh->nhedges = nhedges; mesh->hewgt_dim = hewgt_dim; mesh->hgid = hgid; mesh->hindex = hindex; mesh->hvertex = hvertex; mesh->hvertex_proc = hvertex_proc; mesh->heNumWgts = nhedges; mesh->heWgtId = NULL; mesh->hewgts = hewgts; mesh->eb_etypes = (int *) malloc (5 * mesh->num_el_blks * sizeof(int)); if (!mesh->eb_etypes) { Gen_Error(0, "fatal: insufficient memory"); return 0; } mesh->eb_ids = mesh->eb_etypes + mesh->num_el_blks; mesh->eb_cnts = mesh->eb_ids + mesh->num_el_blks; mesh->eb_nnodes = mesh->eb_cnts + mesh->num_el_blks; mesh->eb_nattrs = mesh->eb_nnodes + mesh->num_el_blks; mesh->eb_names = (char **) malloc (mesh->num_el_blks * sizeof(char *)); if (!mesh->eb_names) { Gen_Error(0, "fatal: insufficient memory"); return 0; } mesh->eb_etypes[0] = -1; mesh->eb_ids[0] = 1; mesh->eb_cnts[0] = nvtxs; mesh->eb_nattrs[0] = 0; /* * Each element has one set of coordinates (i.e., node) if a coords file * was provided; zero otherwise. */ MPI_Bcast( &ch_no_geom, 1, MPI_INT, 0, MPI_COMM_WORLD); if (ch_no_geom) mesh->eb_nnodes[0] = 0; else mesh->eb_nnodes[0] = 1; /* allocate space for name */ mesh->eb_names[0] = (char *) malloc((MAX_STR_LENGTH+1) * sizeof(char)); if (!mesh->eb_names[0]) { Gen_Error(0, "fatal: insufficient memory"); return 0; } strcpy(mesh->eb_names[0], "hypergraph"); /* allocate the element structure array */ mesh->elements = (ELEM_INFO_PTR) malloc (mesh->elem_array_len * sizeof(ELEM_INFO)); if (!(mesh->elements)) { Gen_Error(0, "fatal: insufficient memory"); return 0; } /* * initialize all of the element structs as unused by * setting the globalID to -1 */ for (i = 0; i < mesh->elem_array_len; i++) initialize_element(&(mesh->elements[i])); /* * now fill the element structure array with the * information from the Chaco file * Use hypergraph vertex information and chaco edge information. */ if (!chaco_fill_elements(Proc, Num_Proc, prob, mesh, gnvtxs, nvtxs, ch_start, ch_adj, vwgt_dim, vwgts, ch_ewgt_dim, ch_ewgts, ch_ndim, ch_x, ch_y, ch_z, ch_assignments, base)) { Gen_Error(0, "fatal: Error returned from chaco_fill_elements"); return 0; } #if 0 debug_elements(Proc, Num_Proc, mesh->num_elems,mesh->elements); #endif safe_free((void **)(void *) &vwgts); safe_free((void **)(void *) &ch_ewgts); safe_free((void **)(void *) &ch_vwgts); safe_free((void **)(void *) &ch_x); safe_free((void **)(void *) &ch_y); safe_free((void **)(void *) &ch_z); safe_free((void **)(void *) &ch_start); safe_free((void **)(void *) &ch_adj); safe_free((void **)(void *) &ch_assignments); if (Debug_Driver > 3) print_distributed_mesh(Proc, Num_Proc, mesh); DEBUG_TRACE_END(Proc, yo); return 1; }