1*c4762a1bSJed Brown #include "water.h" 2*c4762a1bSJed Brown #include <string.h> 3*c4762a1bSJed Brown #include <ctype.h> 4*c4762a1bSJed Brown 5*c4762a1bSJed Brown PetscErrorCode PumpHeadCurveResidual(SNES snes,Vec X, Vec F,void *ctx) 6*c4762a1bSJed Brown { 7*c4762a1bSJed Brown PetscErrorCode ierr; 8*c4762a1bSJed Brown const PetscScalar *x; 9*c4762a1bSJed Brown PetscScalar *f; 10*c4762a1bSJed Brown Pump *pump=(Pump*)ctx; 11*c4762a1bSJed Brown PetscScalar *head=pump->headcurve.head,*flow=pump->headcurve.flow; 12*c4762a1bSJed Brown PetscInt i; 13*c4762a1bSJed Brown 14*c4762a1bSJed Brown PetscFunctionBegin; 15*c4762a1bSJed Brown ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 16*c4762a1bSJed Brown ierr = VecGetArray(F,&f);CHKERRQ(ierr); 17*c4762a1bSJed Brown 18*c4762a1bSJed Brown f[0] = f[1] = f[2] = 0; 19*c4762a1bSJed Brown for(i=0; i < pump->headcurve.npt;i++) { 20*c4762a1bSJed Brown f[0] += x[0] - x[1]*PetscPowScalar(flow[i],x[2]) - head[i]; /* Partial w.r.t x[0] */ 21*c4762a1bSJed Brown f[1] += (x[0] - x[1]*PetscPowScalar(flow[i],x[2]) - head[i])*-1*PetscPowScalar(flow[i],x[2]); /*Partial w.r.t x[1] */ 22*c4762a1bSJed Brown f[2] += (x[0] - x[1]*PetscPowScalar(flow[i],x[2]) - head[i])*-1*x[1]*x[2]*PetscPowScalar(flow[i],x[2]-1); /*Partial w.r.t x[2] */ 23*c4762a1bSJed Brown } 24*c4762a1bSJed Brown 25*c4762a1bSJed Brown ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 26*c4762a1bSJed Brown ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); 27*c4762a1bSJed Brown 28*c4762a1bSJed Brown PetscFunctionReturn(0); 29*c4762a1bSJed Brown } 30*c4762a1bSJed Brown 31*c4762a1bSJed Brown PetscErrorCode SetPumpHeadCurveParams(Pump *pump) 32*c4762a1bSJed Brown { 33*c4762a1bSJed Brown PetscErrorCode ierr; 34*c4762a1bSJed Brown SNES snes; 35*c4762a1bSJed Brown Vec X,F; 36*c4762a1bSJed Brown PetscScalar *head,*flow,*x; 37*c4762a1bSJed Brown SNESConvergedReason reason; 38*c4762a1bSJed Brown 39*c4762a1bSJed Brown PetscFunctionBegin; 40*c4762a1bSJed Brown head = pump->headcurve.head; 41*c4762a1bSJed Brown flow = pump->headcurve.flow; 42*c4762a1bSJed Brown if(pump->headcurve.npt == 1) { 43*c4762a1bSJed Brown /* Single point head curve, set the other two data points */ 44*c4762a1bSJed Brown flow[1] = 0; 45*c4762a1bSJed Brown head[1] = 1.33*head[0]; /* 133% of design head -- From EPANET manual */ 46*c4762a1bSJed Brown flow[2] = 2*flow[0]; /* 200% of design flow -- From EPANET manual */ 47*c4762a1bSJed Brown head[2] = 0; 48*c4762a1bSJed Brown pump->headcurve.npt += 2; 49*c4762a1bSJed Brown } 50*c4762a1bSJed Brown 51*c4762a1bSJed Brown ierr = SNESCreate(PETSC_COMM_SELF,&snes);CHKERRQ(ierr); 52*c4762a1bSJed Brown 53*c4762a1bSJed Brown ierr = VecCreate(PETSC_COMM_SELF,&X);CHKERRQ(ierr); 54*c4762a1bSJed Brown ierr = VecSetSizes(X,3,3);CHKERRQ(ierr); 55*c4762a1bSJed Brown ierr = VecSetFromOptions(X);CHKERRQ(ierr); 56*c4762a1bSJed Brown ierr = VecDuplicate(X,&F);CHKERRQ(ierr); 57*c4762a1bSJed Brown 58*c4762a1bSJed Brown ierr = SNESSetFunction(snes,F,PumpHeadCurveResidual,(void*)pump);CHKERRQ(ierr); 59*c4762a1bSJed Brown ierr = SNESSetJacobian(snes,NULL,NULL,SNESComputeJacobianDefault,NULL);CHKERRQ(ierr); 60*c4762a1bSJed Brown ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); 61*c4762a1bSJed Brown 62*c4762a1bSJed Brown ierr = VecGetArray(X,&x);CHKERRQ(ierr); 63*c4762a1bSJed Brown x[0] = head[1]; x[1] = 10; x[2] = 3; 64*c4762a1bSJed Brown ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); 65*c4762a1bSJed Brown 66*c4762a1bSJed Brown ierr = SNESSolve(snes,NULL,X);CHKERRQ(ierr); 67*c4762a1bSJed Brown 68*c4762a1bSJed Brown ierr = SNESGetConvergedReason(snes,&reason);CHKERRQ(ierr); 69*c4762a1bSJed Brown if(reason < 0) { 70*c4762a1bSJed Brown SETERRQ(PETSC_COMM_SELF,0,"Pump head curve did not converge\n"); 71*c4762a1bSJed Brown } 72*c4762a1bSJed Brown 73*c4762a1bSJed Brown ierr = VecGetArray(X,&x);CHKERRQ(ierr); 74*c4762a1bSJed Brown pump->h0 = x[0]; 75*c4762a1bSJed Brown pump->r = x[1]; 76*c4762a1bSJed Brown pump->n = x[2]; 77*c4762a1bSJed Brown ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); 78*c4762a1bSJed Brown 79*c4762a1bSJed Brown ierr = VecDestroy(&X);CHKERRQ(ierr); 80*c4762a1bSJed Brown ierr = VecDestroy(&F);CHKERRQ(ierr); 81*c4762a1bSJed Brown ierr = SNESDestroy(&snes);CHKERRQ(ierr); 82*c4762a1bSJed Brown PetscFunctionReturn(0); 83*c4762a1bSJed Brown } 84*c4762a1bSJed Brown 85*c4762a1bSJed Brown int LineStartsWith(const char *a, const char *b) 86*c4762a1bSJed Brown { 87*c4762a1bSJed Brown if(strncmp(a, b, strlen(b)) == 0) return 1; 88*c4762a1bSJed Brown return 0; 89*c4762a1bSJed Brown } 90*c4762a1bSJed Brown 91*c4762a1bSJed Brown int CheckDataSegmentEnd(const char *line) 92*c4762a1bSJed Brown { 93*c4762a1bSJed Brown if(LineStartsWith(line,"[JUNCTIONS]") || \ 94*c4762a1bSJed Brown LineStartsWith(line,"[RESERVOIRS]") || \ 95*c4762a1bSJed Brown LineStartsWith(line,"[TANKS]") || \ 96*c4762a1bSJed Brown LineStartsWith(line,"[PIPES]") || \ 97*c4762a1bSJed Brown LineStartsWith(line,"[PUMPS]") || \ 98*c4762a1bSJed Brown LineStartsWith(line,"[CURVES]") || \ 99*c4762a1bSJed Brown LineStartsWith(line,"[VALVES]") || \ 100*c4762a1bSJed Brown LineStartsWith(line,"[PATTERNS]") || \ 101*c4762a1bSJed Brown LineStartsWith(line,"[VALVES]") || \ 102*c4762a1bSJed Brown LineStartsWith(line,"[QUALITY]") || \ 103*c4762a1bSJed Brown LineStartsWith(line,"\n") || LineStartsWith(line,"\r\n")) { 104*c4762a1bSJed Brown return 1; 105*c4762a1bSJed Brown } 106*c4762a1bSJed Brown return 0; 107*c4762a1bSJed Brown } 108*c4762a1bSJed Brown 109*c4762a1bSJed Brown /* Gets the file pointer positiion for the start of the data segment and the 110*c4762a1bSJed Brown number of data segments (lines) read 111*c4762a1bSJed Brown */ 112*c4762a1bSJed Brown PetscErrorCode GetDataSegment(FILE *fp,char *line,fpos_t *data_segment_start_pos,PetscInt *ndatalines) 113*c4762a1bSJed Brown { 114*c4762a1bSJed Brown PetscInt data_segment_end; 115*c4762a1bSJed Brown PetscInt nlines=0; 116*c4762a1bSJed Brown 117*c4762a1bSJed Brown PetscFunctionBegin; 118*c4762a1bSJed Brown data_segment_end = 0; 119*c4762a1bSJed Brown fgetpos(fp,data_segment_start_pos); 120*c4762a1bSJed Brown if (!fgets(line,MAXLINE,fp)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Cannot read data segment from file"); 121*c4762a1bSJed Brown while(LineStartsWith(line,";")) { 122*c4762a1bSJed Brown fgetpos(fp,data_segment_start_pos); 123*c4762a1bSJed Brown if (!fgets(line,MAXLINE,fp)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Cannot read data segment from file"); 124*c4762a1bSJed Brown } 125*c4762a1bSJed Brown while(!data_segment_end) { 126*c4762a1bSJed Brown if (!fgets(line,MAXLINE,fp)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Cannot read data segment from file"); 127*c4762a1bSJed Brown nlines++; 128*c4762a1bSJed Brown data_segment_end = CheckDataSegmentEnd(line); 129*c4762a1bSJed Brown } 130*c4762a1bSJed Brown *ndatalines = nlines; 131*c4762a1bSJed Brown PetscFunctionReturn(0); 132*c4762a1bSJed Brown } 133*c4762a1bSJed Brown 134*c4762a1bSJed Brown 135*c4762a1bSJed Brown PetscErrorCode WaterReadData(WATERDATA *water,char *filename) 136*c4762a1bSJed Brown { 137*c4762a1bSJed Brown FILE *fp=NULL; 138*c4762a1bSJed Brown PetscErrorCode ierr; 139*c4762a1bSJed Brown VERTEX_Water vert; 140*c4762a1bSJed Brown EDGE_Water edge; 141*c4762a1bSJed Brown fpos_t junc_start_pos,res_start_pos,tank_start_pos,pipe_start_pos,pump_start_pos; 142*c4762a1bSJed Brown fpos_t curve_start_pos,title_start_pos; 143*c4762a1bSJed Brown char line[MAXLINE]; 144*c4762a1bSJed Brown PetscInt i,j,nv=0,ne=0,ncurve=0,ntitle=0,nlines,ndata,curve_id; 145*c4762a1bSJed Brown Junction *junction=NULL; 146*c4762a1bSJed Brown Reservoir *reservoir=NULL; 147*c4762a1bSJed Brown Tank *tank=NULL; 148*c4762a1bSJed Brown Pipe *pipe=NULL; 149*c4762a1bSJed Brown Pump *pump=NULL; 150*c4762a1bSJed Brown PetscScalar curve_x,curve_y; 151*c4762a1bSJed Brown double v1,v2,v3,v4,v5,v6; 152*c4762a1bSJed Brown 153*c4762a1bSJed Brown PetscFunctionBegin; 154*c4762a1bSJed Brown water->nvertex = water->nedge = 0; 155*c4762a1bSJed Brown fp = fopen(filename,"rb"); 156*c4762a1bSJed Brown /* Check for valid file */ 157*c4762a1bSJed Brown if (!fp) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Can't open EPANET data file %s",filename); 158*c4762a1bSJed Brown 159*c4762a1bSJed Brown /* Read file and get line numbers for different data segments */ 160*c4762a1bSJed Brown while(fgets(line,MAXLINE,fp)) { 161*c4762a1bSJed Brown 162*c4762a1bSJed Brown if (strstr(line,"[TITLE]")) { 163*c4762a1bSJed Brown GetDataSegment(fp,line,&title_start_pos,&ntitle); 164*c4762a1bSJed Brown } 165*c4762a1bSJed Brown 166*c4762a1bSJed Brown if (strstr(line,"[JUNCTIONS]")) { 167*c4762a1bSJed Brown GetDataSegment(fp,line,&junc_start_pos,&nlines); 168*c4762a1bSJed Brown water->nvertex += nlines; 169*c4762a1bSJed Brown water->njunction = nlines; 170*c4762a1bSJed Brown } 171*c4762a1bSJed Brown 172*c4762a1bSJed Brown if (strstr(line,"[RESERVOIRS]")) { 173*c4762a1bSJed Brown GetDataSegment(fp,line,&res_start_pos,&nlines); 174*c4762a1bSJed Brown water->nvertex += nlines; 175*c4762a1bSJed Brown water->nreservoir = nlines; 176*c4762a1bSJed Brown } 177*c4762a1bSJed Brown 178*c4762a1bSJed Brown if (strstr(line,"[TANKS]")) { 179*c4762a1bSJed Brown GetDataSegment(fp,line,&tank_start_pos,&nlines); 180*c4762a1bSJed Brown water->nvertex += nlines; 181*c4762a1bSJed Brown water->ntank = nlines; 182*c4762a1bSJed Brown } 183*c4762a1bSJed Brown 184*c4762a1bSJed Brown if (strstr(line,"[PIPES]")) { 185*c4762a1bSJed Brown GetDataSegment(fp,line,&pipe_start_pos,&nlines); 186*c4762a1bSJed Brown water->nedge += nlines; 187*c4762a1bSJed Brown water->npipe = nlines; 188*c4762a1bSJed Brown } 189*c4762a1bSJed Brown 190*c4762a1bSJed Brown if (strstr(line,"[PUMPS]")) { 191*c4762a1bSJed Brown GetDataSegment(fp,line,&pump_start_pos,&nlines); 192*c4762a1bSJed Brown water->nedge += nlines; 193*c4762a1bSJed Brown water->npump = nlines; 194*c4762a1bSJed Brown } 195*c4762a1bSJed Brown 196*c4762a1bSJed Brown if (strstr(line,"[CURVES]")) { 197*c4762a1bSJed Brown GetDataSegment(fp,line,&curve_start_pos,&ncurve); 198*c4762a1bSJed Brown } 199*c4762a1bSJed Brown } 200*c4762a1bSJed Brown 201*c4762a1bSJed Brown /* Allocate vertex and edge data structs */ 202*c4762a1bSJed Brown ierr = PetscCalloc1(water->nvertex,&water->vertex);CHKERRQ(ierr); 203*c4762a1bSJed Brown ierr = PetscCalloc1(water->nedge,&water->edge);CHKERRQ(ierr); 204*c4762a1bSJed Brown vert = water->vertex; 205*c4762a1bSJed Brown edge = water->edge; 206*c4762a1bSJed Brown 207*c4762a1bSJed Brown /* Junctions */ 208*c4762a1bSJed Brown fsetpos(fp,&junc_start_pos); 209*c4762a1bSJed Brown for (i=0; i < water->njunction; i++) { 210*c4762a1bSJed Brown int id=0,pattern=0; 211*c4762a1bSJed Brown if (!fgets(line,MAXLINE,fp)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Cannot read junction from file"); 212*c4762a1bSJed Brown vert[nv].type = VERTEX_TYPE_JUNCTION; 213*c4762a1bSJed Brown junction = &vert[nv].junc; 214*c4762a1bSJed Brown ndata = sscanf(line,"%d %lf %lf %d",&id,&v1,&v2,&pattern);if (ndata < 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Unable to read junction data"); 215*c4762a1bSJed Brown vert[nv].id = id; 216*c4762a1bSJed Brown junction->dempattern = pattern; 217*c4762a1bSJed Brown junction->elev = (PetscScalar)v1; 218*c4762a1bSJed Brown junction->demand = (PetscScalar)v2; 219*c4762a1bSJed Brown junction->demand *= GPM_CFS; 220*c4762a1bSJed Brown junction->id = vert[nv].id; 221*c4762a1bSJed Brown nv++; 222*c4762a1bSJed Brown } 223*c4762a1bSJed Brown 224*c4762a1bSJed Brown /* Reservoirs */ 225*c4762a1bSJed Brown fsetpos(fp,&res_start_pos); 226*c4762a1bSJed Brown for (i=0; i < water->nreservoir; i++) { 227*c4762a1bSJed Brown int id=0,pattern=0; 228*c4762a1bSJed Brown if (!fgets(line,MAXLINE,fp)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Cannot read reservoir from file"); 229*c4762a1bSJed Brown vert[nv].type = VERTEX_TYPE_RESERVOIR; 230*c4762a1bSJed Brown reservoir = &vert[nv].res; 231*c4762a1bSJed Brown ndata = sscanf(line,"%d %lf %d",&id,&v1,&pattern);if (ndata < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Unable to read reservoir data"); 232*c4762a1bSJed Brown vert[nv].id = id; 233*c4762a1bSJed Brown reservoir->headpattern = pattern; 234*c4762a1bSJed Brown reservoir->head = (PetscScalar)v1; 235*c4762a1bSJed Brown reservoir->id = vert[nv].id; 236*c4762a1bSJed Brown nv++; 237*c4762a1bSJed Brown } 238*c4762a1bSJed Brown 239*c4762a1bSJed Brown /* Tanks */ 240*c4762a1bSJed Brown fsetpos(fp,&tank_start_pos); 241*c4762a1bSJed Brown for (i=0; i < water->ntank; i++) { 242*c4762a1bSJed Brown int id=0,curve=0; 243*c4762a1bSJed Brown if (!fgets(line,MAXLINE,fp)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Cannot read data tank from file"); 244*c4762a1bSJed Brown vert[nv].type = VERTEX_TYPE_TANK; 245*c4762a1bSJed Brown tank = &vert[nv].tank; 246*c4762a1bSJed Brown ndata = sscanf(line,"%d %lf %lf %lf %lf %lf %lf %d",&id,&v1,&v2,&v3,&v4,&v5,&v6,&curve);if (ndata < 7) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Unable to read tank data"); 247*c4762a1bSJed Brown vert[nv].id = id; 248*c4762a1bSJed Brown tank->volumecurve = curve; 249*c4762a1bSJed Brown tank->elev = (PetscScalar)v1; 250*c4762a1bSJed Brown tank->initlvl = (PetscScalar)v2; 251*c4762a1bSJed Brown tank->minlvl = (PetscScalar)v3; 252*c4762a1bSJed Brown tank->maxlvl = (PetscScalar)v4; 253*c4762a1bSJed Brown tank->diam = (PetscScalar)v5; 254*c4762a1bSJed Brown tank->minvolume = (PetscScalar)v6; 255*c4762a1bSJed Brown tank->id = vert[nv].id; 256*c4762a1bSJed Brown nv++; 257*c4762a1bSJed Brown } 258*c4762a1bSJed Brown 259*c4762a1bSJed Brown /* Pipes */ 260*c4762a1bSJed Brown fsetpos(fp,&pipe_start_pos); 261*c4762a1bSJed Brown for (i=0; i < water->npipe; i++) { 262*c4762a1bSJed Brown int id=0,node1=0,node2=0; 263*c4762a1bSJed Brown if (!fgets(line,MAXLINE,fp)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Cannot read data pipe from file"); 264*c4762a1bSJed Brown edge[ne].type = EDGE_TYPE_PIPE; 265*c4762a1bSJed Brown pipe = &edge[ne].pipe; 266*c4762a1bSJed Brown ndata = sscanf(line,"%d %d %d %lf %lf %lf %lf %s",&id,&node1,&node2,&v1,&v2,&v3,&v4,pipe->stat); 267*c4762a1bSJed Brown pipe->id = id; 268*c4762a1bSJed Brown pipe->node1 = node1; 269*c4762a1bSJed Brown pipe->node2 = node2; 270*c4762a1bSJed Brown pipe->length = (PetscScalar)v1; 271*c4762a1bSJed Brown pipe->diam = (PetscScalar)v2; 272*c4762a1bSJed Brown pipe->roughness = (PetscScalar)v3; 273*c4762a1bSJed Brown pipe->minorloss = (PetscScalar)v4; 274*c4762a1bSJed Brown edge[ne].id = pipe->id; 275*c4762a1bSJed Brown if (strcmp(pipe->stat,"OPEN") == 0) pipe->status = PIPE_STATUS_OPEN; 276*c4762a1bSJed Brown if (ndata < 8) { 277*c4762a1bSJed Brown strcpy(pipe->stat,"OPEN"); /* default OPEN */ 278*c4762a1bSJed Brown pipe->status = PIPE_STATUS_OPEN; 279*c4762a1bSJed Brown } 280*c4762a1bSJed Brown if (ndata < 7) pipe->minorloss = 0.; 281*c4762a1bSJed Brown pipe->n = 1.85; 282*c4762a1bSJed Brown pipe->k = 4.72*pipe->length/(PetscPowScalar(pipe->roughness,pipe->n)*PetscPowScalar(0.0833333*pipe->diam,4.87)); 283*c4762a1bSJed Brown ne++; 284*c4762a1bSJed Brown } 285*c4762a1bSJed Brown 286*c4762a1bSJed Brown /* Pumps */ 287*c4762a1bSJed Brown fsetpos(fp,&pump_start_pos); 288*c4762a1bSJed Brown for (i=0; i < water->npump; i++) { 289*c4762a1bSJed Brown int id=0,node1=0,node2=0,paramid=0; 290*c4762a1bSJed Brown if (!fgets(line,MAXLINE,fp)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Cannot read data pump from file"); 291*c4762a1bSJed Brown edge[ne].type = EDGE_TYPE_PUMP; 292*c4762a1bSJed Brown pump = &edge[ne].pump; 293*c4762a1bSJed Brown ndata = sscanf(line,"%d %d %d %s %d",&id,&node1,&node2,pump->param,¶mid);if (ndata != 5) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Unable to read pump data"); 294*c4762a1bSJed Brown pump->id = id; 295*c4762a1bSJed Brown pump->node1 = node1; 296*c4762a1bSJed Brown pump->node2 = node2; 297*c4762a1bSJed Brown pump->paramid = paramid; 298*c4762a1bSJed Brown edge[ne].id = pump->id; 299*c4762a1bSJed Brown ne++; 300*c4762a1bSJed Brown } 301*c4762a1bSJed Brown 302*c4762a1bSJed Brown /* Curves */ 303*c4762a1bSJed Brown fsetpos(fp,&curve_start_pos); 304*c4762a1bSJed Brown for (i=0; i < ncurve; i++) { 305*c4762a1bSJed Brown int icurve_id=0; 306*c4762a1bSJed Brown if (!fgets(line,MAXLINE,fp)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Cannot read data curve from file"); 307*c4762a1bSJed Brown ndata = sscanf(line,"%d %lf %lf",&icurve_id,&v1,&v2);if (ndata != 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Unable to read curve data"); 308*c4762a1bSJed Brown curve_id = icurve_id; 309*c4762a1bSJed Brown curve_x = (PetscScalar)v1; 310*c4762a1bSJed Brown curve_y = (PetscScalar)v2; 311*c4762a1bSJed Brown /* Check for pump with the curve_id */ 312*c4762a1bSJed Brown for (j=water->npipe;j < water->npipe+water->npump;j++) { 313*c4762a1bSJed Brown if(water->edge[j].pump.paramid == curve_id) { 314*c4762a1bSJed Brown if(pump->headcurve.npt == 3) { 315*c4762a1bSJed Brown SETERRQ3(PETSC_COMM_SELF,0,"Pump %d [%d --> %d]: No support for more than 3-pt head-flow curve",pump->id,pump->node1,pump->node2); 316*c4762a1bSJed Brown } 317*c4762a1bSJed Brown pump = &water->edge[j].pump; 318*c4762a1bSJed Brown pump->headcurve.flow[pump->headcurve.npt] = curve_x*GPM_CFS; 319*c4762a1bSJed Brown pump->headcurve.head[pump->headcurve.npt] = curve_y; 320*c4762a1bSJed Brown pump->headcurve.npt++; 321*c4762a1bSJed Brown break; 322*c4762a1bSJed Brown } 323*c4762a1bSJed Brown } 324*c4762a1bSJed Brown } 325*c4762a1bSJed Brown 326*c4762a1bSJed Brown fclose(fp); 327*c4762a1bSJed Brown 328*c4762a1bSJed Brown /* Get pump curve parameters */ 329*c4762a1bSJed Brown for(j=water->npipe;j < water->npipe+water->npump;j++) { 330*c4762a1bSJed Brown pump = &water->edge[j].pump; 331*c4762a1bSJed Brown if (strcmp(pump->param,"HEAD") == 0) { 332*c4762a1bSJed Brown /* Head-flow curve */ 333*c4762a1bSJed Brown ierr = SetPumpHeadCurveParams(pump);CHKERRQ(ierr); 334*c4762a1bSJed Brown } 335*c4762a1bSJed Brown } 336*c4762a1bSJed Brown PetscFunctionReturn(0); 337*c4762a1bSJed Brown } 338