Path: blob/devel/elmergrid/src/metis-5.1.0/programs/io.c
3206 views
/*1* Copyright 1997, Regents of the University of Minnesota2*3* io.c4*5* This file contains routines related to I/O6*7* Started 8/28/948* George9*10* $Id: io.c 11932 2012-05-10 18:18:23Z dominique $11*12*/1314#include "metisbin.h"15161718/*************************************************************************/19/*! This function reads in a sparse graph */20/*************************************************************************/21graph_t *ReadGraph(params_t *params)22{23idx_t i, j, k, l, fmt, ncon, nfields, readew, readvw, readvs, edge, ewgt;24idx_t *xadj, *adjncy, *vwgt, *adjwgt, *vsize;25char *line=NULL, fmtstr[256], *curstr, *newstr;26size_t lnlen=0;27FILE *fpin;28graph_t *graph;2930if (!gk_fexists(params->filename))31errexit("File %s does not exist!\n", params->filename);3233graph = CreateGraph();3435fpin = gk_fopen(params->filename, "r", "ReadGRaph: Graph");3637/* Skip comment lines until you get to the first valid line */38do {39if (gk_getline(&line, &lnlen, fpin) == -1)40errexit("Premature end of input file: file: %s\n", params->filename);41} while (line[0] == '%');424344fmt = ncon = 0;45nfields = sscanf(line, "%"SCIDX" %"SCIDX" %"SCIDX" %"SCIDX,46&(graph->nvtxs), &(graph->nedges), &fmt, &ncon);4748if (nfields < 2)49errexit("The input file does not specify the number of vertices and edges.\n");5051if (graph->nvtxs <= 0 || graph->nedges <= 0)52errexit("The supplied nvtxs:%"PRIDX" and nedges:%"PRIDX" must be positive.\n",53graph->nvtxs, graph->nedges);5455if (fmt > 111)56errexit("Cannot read this type of file format [fmt=%"PRIDX"]!\n", fmt);5758sprintf(fmtstr, "%03"PRIDX, fmt%1000);59readvs = (fmtstr[0] == '1');60readvw = (fmtstr[1] == '1');61readew = (fmtstr[2] == '1');6263/*printf("%s %"PRIDX" %"PRIDX" %"PRIDX"\n", fmtstr, readvs, readvw, readew); */646566if (ncon > 0 && !readvw)67errexit(68"------------------------------------------------------------------------------\n"69"*** I detected an error in your input file ***\n\n"70"You specified ncon=%"PRIDX", but the fmt parameter does not specify vertex weights\n"71"Make sure that the fmt parameter is set to either 10 or 11.\n"72"------------------------------------------------------------------------------\n", ncon);7374graph->nedges *=2;75ncon = graph->ncon = (ncon == 0 ? 1 : ncon);7677xadj = graph->xadj = ismalloc(graph->nvtxs+1, 0, "ReadGraph: xadj");78adjncy = graph->adjncy = imalloc(graph->nedges, "ReadGraph: adjncy");79vwgt = graph->vwgt = ismalloc(ncon*graph->nvtxs, 1, "ReadGraph: vwgt");80adjwgt = graph->adjwgt = ismalloc(graph->nedges, 1, "ReadGraph: adjwgt");81vsize = graph->vsize = ismalloc(graph->nvtxs, 1, "ReadGraph: vsize");828384/*----------------------------------------------------------------------85* Read the sparse graph file86*---------------------------------------------------------------------*/87for (xadj[0]=0, k=0, i=0; i<graph->nvtxs; i++) {88do {89if (gk_getline(&line, &lnlen, fpin) == -1)90errexit("Premature end of input file while reading vertex %"PRIDX".\n", i+1);91} while (line[0] == '%');9293curstr = line;94newstr = NULL;9596/* Read vertex sizes */97if (readvs) {98vsize[i] = strtoidx(curstr, &newstr, 10);99if (newstr == curstr)100errexit("The line for vertex %"PRIDX" does not have vsize information\n", i+1);101if (vsize[i] < 0)102errexit("The size for vertex %"PRIDX" must be >= 0\n", i+1);103curstr = newstr;104}105106107/* Read vertex weights */108if (readvw) {109for (l=0; l<ncon; l++) {110vwgt[i*ncon+l] = strtoidx(curstr, &newstr, 10);111if (newstr == curstr)112errexit("The line for vertex %"PRIDX" does not have enough weights "113"for the %"PRIDX" constraints.\n", i+1, ncon);114if (vwgt[i*ncon+l] < 0)115errexit("The weight vertex %"PRIDX" and constraint %"PRIDX" must be >= 0\n", i+1, l);116curstr = newstr;117}118}119120while (1) {121edge = strtoidx(curstr, &newstr, 10);122if (newstr == curstr)123break; /* End of line */124curstr = newstr;125126if (edge < 1 || edge > graph->nvtxs)127errexit("Edge %"PRIDX" for vertex %"PRIDX" is out of bounds\n", edge, i+1);128129ewgt = 1;130if (readew) {131ewgt = strtoidx(curstr, &newstr, 10);132if (newstr == curstr)133errexit("Premature end of line for vertex %"PRIDX"\n", i+1);134if (ewgt <= 0)135errexit("The weight (%"PRIDX") for edge (%"PRIDX", %"PRIDX") must be positive.\n",136ewgt, i+1, edge);137curstr = newstr;138}139140if (k == graph->nedges)141errexit("There are more edges in the file than the %"PRIDX" specified.\n",142graph->nedges/2);143144adjncy[k] = edge-1;145adjwgt[k] = ewgt;146k++;147}148xadj[i+1] = k;149}150gk_fclose(fpin);151152if (k != graph->nedges) {153printf("------------------------------------------------------------------------------\n");154printf("*** I detected an error in your input file ***\n\n");155printf("In the first line of the file, you specified that the graph contained\n"156"%"PRIDX" edges. However, I only found %"PRIDX" edges in the file.\n",157graph->nedges/2, k/2);158if (2*k == graph->nedges) {159printf("\n *> I detected that you specified twice the number of edges that you have in\n");160printf(" the file. Remember that the number of edges specified in the first line\n");161printf(" counts each edge between vertices v and u only once.\n\n");162}163printf("Please specify the correct number of edges in the first line of the file.\n");164printf("------------------------------------------------------------------------------\n");165exit(0);166}167168gk_free((void *)&line, LTERM);169170return graph;171}172173174/*************************************************************************/175/*! This function reads in a mesh */176/*************************************************************************/177mesh_t *ReadMesh(params_t *params)178{179idx_t i, j, k, l, nfields, ncon, node;180idx_t *eptr, *eind, *ewgt;181size_t nlines, ntokens;182char *line=NULL, *curstr, *newstr;183size_t lnlen=0;184FILE *fpin;185mesh_t *mesh;186187if (!gk_fexists(params->filename))188errexit("File %s does not exist!\n", params->filename);189190mesh = CreateMesh();191192/* get some file stats */193gk_getfilestats(params->filename, &nlines, &ntokens, NULL, NULL);194195fpin = gk_fopen(params->filename, "r", __func__);196197/* Skip comment lines until you get to the first valid line */198do {199if (gk_getline(&line, &lnlen, fpin) == -1)200errexit("Premature end of input file: file: %s\n", params->filename);201} while (line[0] == '%');202203204mesh->ncon = 0;205nfields = sscanf(line, "%"SCIDX" %"SCIDX, &(mesh->ne), &(mesh->ncon));206207if (nfields < 1)208errexit("The input file does not specify the number of elements.\n");209210if (mesh->ne <= 0)211errexit("The supplied number of elements:%"PRIDX" must be positive.\n", mesh->ne);212213if (mesh->ne > nlines)214errexit("The file has %zu lines which smaller than the number of "215"elements of %"PRIDX" specified in the header line.\n", nlines, mesh->ne);216217ncon = mesh->ncon;218eptr = mesh->eptr = ismalloc(mesh->ne+1, 0, "ReadMesh: eptr");219eind = mesh->eind = imalloc(ntokens, "ReadMesh: eind");220ewgt = mesh->ewgt = ismalloc((ncon == 0 ? 1 : ncon)*mesh->ne, 1, "ReadMesh: ewgt");221222223/*----------------------------------------------------------------------224* Read the mesh file225*---------------------------------------------------------------------*/226for (eptr[0]=0, k=0, i=0; i<mesh->ne; i++) {227do {228if (gk_getline(&line, &lnlen, fpin) == -1)229errexit("Premature end of input file while reading element %"PRIDX".\n", i+1);230} while (line[0] == '%');231232curstr = line;233newstr = NULL;234235/* Read element weights */236for (l=0; l<ncon; l++) {237ewgt[i*ncon+l] = strtoidx(curstr, &newstr, 10);238if (newstr == curstr)239errexit("The line for vertex %"PRIDX" does not have enough weights "240"for the %"PRIDX" constraints.\n", i+1, ncon);241if (ewgt[i*ncon+l] < 0)242errexit("The weight for element %"PRIDX" and constraint %"PRIDX" must be >= 0\n", i+1, l);243curstr = newstr;244}245246while (1) {247node = strtoidx(curstr, &newstr, 10);248if (newstr == curstr)249break; /* End of line */250curstr = newstr;251252if (node < 1)253errexit("Node %"PRIDX" for element %"PRIDX" is out of bounds\n", node, i+1);254255eind[k++] = node-1;256}257eptr[i+1] = k;258}259gk_fclose(fpin);260261mesh->ncon = (ncon == 0 ? 1 : ncon);262mesh->nn = imax(eptr[mesh->ne], eind)+1;263264gk_free((void *)&line, LTERM);265266return mesh;267}268269270/*************************************************************************/271/*! This function reads in the target partition weights. If no file is272specified the weights are set to 1/nparts */273/*************************************************************************/274void ReadTPwgts(params_t *params, idx_t ncon)275{276idx_t i, j, from, to, fromcnum, tocnum, nleft;277real_t awgt=0.0, twgt;278char *line=NULL, *curstr, *newstr;279size_t lnlen=0;280FILE *fpin;281282params->tpwgts = rsmalloc(params->nparts*ncon, -1.0, "ReadTPwgts: tpwgts");283284if (params->tpwgtsfile == NULL) {285for (i=0; i<params->nparts; i++) {286for (j=0; j<ncon; j++)287params->tpwgts[i*ncon+j] = 1.0/params->nparts;288}289return;290}291292if (!gk_fexists(params->tpwgtsfile))293errexit("Graph file %s does not exist!\n", params->tpwgtsfile);294295fpin = gk_fopen(params->tpwgtsfile, "r", "ReadTPwgts: tpwgtsfile");296297while (gk_getline(&line, &lnlen, fpin) != -1) {298gk_strchr_replace(line, " ", "");299/* start extracting the fields */300301curstr = line;302newstr = NULL;303304from = strtoidx(curstr, &newstr, 10);305if (newstr == curstr)306errexit("The 'from' component of line <%s> in the tpwgts file is incorrect.\n", line);307curstr = newstr;308309if (curstr[0] == '-') {310to = strtoidx(curstr+1, &newstr, 10);311if (newstr == curstr)312errexit("The 'to' component of line <%s> in the tpwgts file is incorrect.\n", line);313curstr = newstr;314}315else {316to = from;317}318319if (curstr[0] == ':') {320fromcnum = strtoidx(curstr+1, &newstr, 10);321if (newstr == curstr)322errexit("The 'fromcnum' component of line <%s> in the tpwgts file is incorrect.\n", line);323curstr = newstr;324325if (curstr[0] == '-') {326tocnum = strtoidx(curstr+1, &newstr, 10);327if (newstr == curstr)328errexit("The 'tocnum' component of line <%s> in the tpwgts file is incorrect.\n", line);329curstr = newstr;330}331else {332tocnum = fromcnum;333}334}335else {336fromcnum = 0;337tocnum = ncon-1;338}339340if (curstr[0] == '=') {341awgt = strtoreal(curstr+1, &newstr);342if (newstr == curstr)343errexit("The 'wgt' component of line <%s> in the tpwgts file is incorrect.\n", line);344curstr = newstr;345}346else {347errexit("The 'wgt' component of line <%s> in the tpwgts file is missing.\n", line);348}349350/*printf("Read: %"PRIDX"-%"PRIDX":%"PRIDX"-%"PRIDX"=%"PRREAL"\n",351from, to, fromcnum, tocnum, awgt);*/352353if (from < 0 || to < 0 || from >= params->nparts || to >= params->nparts)354errexit("Invalid partition range for %"PRIDX":%"PRIDX"\n", from, to);355if (fromcnum < 0 || tocnum < 0 || fromcnum >= ncon || tocnum >= ncon)356errexit("Invalid constraint number range for %"PRIDX":%"PRIDX"\n",357fromcnum, tocnum);358if (awgt <= 0.0 || awgt >= 1.0)359errexit("Invalid partition weight of %"PRREAL"\n", awgt);360for (i=from; i<=to; i++) {361for (j=fromcnum; j<=tocnum; j++)362params->tpwgts[i*ncon+j] = awgt;363}364}365366gk_fclose(fpin);367368/* Assign weight to the unspecified constraints x partitions */369for (j=0; j<ncon; j++) {370/* Sum up the specified weights for the jth constraint */371for (twgt=0.0, nleft=params->nparts, i=0; i<params->nparts; i++) {372if (params->tpwgts[i*ncon+j] > 0) {373twgt += params->tpwgts[i*ncon+j];374nleft--;375}376}377378/* Rescale the weights to be on the safe side */379if (nleft == 0)380rscale(params->nparts, 1.0/twgt, params->tpwgts+j, ncon);381382/* Assign the left-over weight to the remaining partitions */383if (nleft > 0) {384if (twgt > 1)385errexit("The total specified target partition weights for constraint #%"PRIDX386" of %"PRREAL" exceeds 1.0.\n", j, twgt);387388awgt = (1.0 - twgt)/nleft;389for (i=0; i<params->nparts; i++)390params->tpwgts[i*ncon+j] =391(params->tpwgts[i*ncon+j] < 0 ? awgt : params->tpwgts[i*ncon+j]);392}393}394#ifdef HAVE_GETLINE395free(line);396line = NULL; /* set to null to match behavior of gk_free() */397#else398gk_free((void *)&line, LTERM);399#endif400}401402403/*************************************************************************/404/*! This function reads in a partition/ordering vector */405/**************************************************************************/406void ReadPOVector(graph_t *graph, char *filename, idx_t *vector)407{408idx_t i;409FILE *fpin;410411fpin = gk_fopen(filename, "r", __func__);412for (i=0; i<graph->nvtxs; i++) {413if (fscanf(fpin, "%"SCIDX"\n", vector+i) != 1)414errexit("[%s] Premature end of file %s at line %d [nvtxs: %d]\n",415__func__, filename, i, graph->nvtxs);416}417gk_fclose(fpin);418}419420421/*************************************************************************/422/*! This function writes out the partition vector */423/*************************************************************************/424void WritePartition(char *fname, idx_t *part, idx_t n, idx_t nparts)425{426FILE *fpout;427idx_t i;428char filename[MAXLINE];429430sprintf(filename, "%s.part.%"PRIDX, fname, nparts);431432fpout = gk_fopen(filename, "w", __func__);433434for (i=0; i<n; i++)435fprintf(fpout,"%" PRIDX "\n", part[i]);436437gk_fclose(fpout);438}439440441/*************************************************************************/442/*! This function writes out the partition vectors for a mesh */443/*************************************************************************/444void WriteMeshPartition(char *fname, idx_t nparts, idx_t ne, idx_t *epart,445idx_t nn, idx_t *npart)446{447FILE *fpout;448idx_t i;449char filename[256];450451sprintf(filename,"%s.epart.%"PRIDX,fname, nparts);452453fpout = gk_fopen(filename, "w", __func__);454455for (i=0; i<ne; i++)456fprintf(fpout,"%" PRIDX "\n", epart[i]);457458gk_fclose(fpout);459460461sprintf(filename,"%s.npart.%"PRIDX,fname, nparts);462463fpout = gk_fopen(filename, "w", __func__);464465for (i=0; i<nn; i++)466fprintf(fpout, "%" PRIDX "\n", npart[i]);467468gk_fclose(fpout);469470}471472473/*************************************************************************/474/*! This function writes out the permutation vector */475/*************************************************************************/476void WritePermutation(char *fname, idx_t *iperm, idx_t n)477{478FILE *fpout;479idx_t i;480char filename[MAXLINE];481482sprintf(filename, "%s.iperm", fname);483484fpout = gk_fopen(filename, "w", __func__);485486for (i=0; i<n; i++)487fprintf(fpout, "%" PRIDX "\n", iperm[i]);488489gk_fclose(fpout);490}491492493/*************************************************************************/494/*! This function writes a graph into a file */495/*************************************************************************/496void WriteGraph(graph_t *graph, char *filename)497{498idx_t i, j, nvtxs, ncon;499idx_t *xadj, *adjncy, *adjwgt, *vwgt, *vsize;500int hasvwgt=0, hasewgt=0, hasvsize=0;501FILE *fpout;502503nvtxs = graph->nvtxs;504ncon = graph->ncon;505xadj = graph->xadj;506adjncy = graph->adjncy;507vwgt = graph->vwgt;508vsize = graph->vsize;509adjwgt = graph->adjwgt;510511/* determine if the graph has non-unity vwgt, vsize, or adjwgt */512if (vwgt) {513for (i=0; i<nvtxs*ncon; i++) {514if (vwgt[i] != 1) {515hasvwgt = 1;516break;517}518}519}520if (vsize) {521for (i=0; i<nvtxs; i++) {522if (vsize[i] != 1) {523hasvsize = 1;524break;525}526}527}528if (adjwgt) {529for (i=0; i<xadj[nvtxs]; i++) {530if (adjwgt[i] != 1) {531hasewgt = 1;532break;533}534}535}536537fpout = gk_fopen(filename, "w", __func__);538539/* write the header line */540fprintf(fpout, "%"PRIDX" %"PRIDX, nvtxs, xadj[nvtxs]/2);541if (hasvwgt || hasvsize || hasewgt) {542fprintf(fpout, " %d%d%d", hasvsize, hasvwgt, hasewgt);543if (hasvwgt)544fprintf(fpout, " %d", (int)graph->ncon);545}546547548/* write the rest of the graph */549for (i=0; i<nvtxs; i++) {550fprintf(fpout, "\n");551if (hasvsize)552fprintf(fpout, " %"PRIDX, vsize[i]);553554if (hasvwgt) {555for (j=0; j<ncon; j++)556fprintf(fpout, " %"PRIDX, vwgt[i*ncon+j]);557}558559for (j=xadj[i]; j<xadj[i+1]; j++) {560fprintf(fpout, " %"PRIDX, adjncy[j]+1);561if (hasewgt)562fprintf(fpout, " %"PRIDX, adjwgt[j]);563}564}565566gk_fclose(fpout);567}568569570