int saveinpfile(char *fname) /* ------------------------------------------------- Writes network data to text file. ------------------------------------------------- */ { int i,j,n; double d,kc,ke,km,ucf; char s[MAXLINE+1], s1[MAXLINE+1], s2[MAXLINE+1]; Pdemand demand; Psource source; FILE *f; /* Open the new text file */ if ((f = fopen(fname,"wt")) == NULL) return(308); /* Write [TITLE] section */ fprintf(f,"[TITLE]"); for (i=0; i<3; i++) { if (strlen(Title[i]) > 0) fprintf(f,"\n%s",Title[i]); } /* Write [JUNCTIONS] section */ /* (Leave demands for [DEMANDS] section) */ fprintf(f,"\n\n[JUNCTIONS]"); for (i=1; i<=Njuncs; i++) fprintf(f,"\n %-31s %12.4f", Node[i].ID, Node[i].El*Ucf[ELEV]); /* Write [RESERVOIRS] section */ fprintf(f,"\n\n[RESERVOIRS]"); for (i=1; i<=Ntanks; i++) { if (Tank[i].A == 0.0) { n = Tank[i].Node; sprintf(s," %-31s %12.4f",Node[n].ID, Node[n].El*Ucf[ELEV]); if ((j = Tank[i].Pat) > 0) sprintf(s1," %-31s",Pattern[j].ID); else strcpy(s1,""); fprintf(f, "\n%s %s", s,s1); } } /* Write [TANKS] section */ fprintf(f,"\n\n[TANKS]"); for (i=1; i<=Ntanks; i++) { if (Tank[i].A > 0.0) { n = Tank[i].Node; sprintf(s," %-31s %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f", Node[n].ID, Node[n].El*Ucf[ELEV], (Tank[i].H0 - Node[n].El)*Ucf[ELEV], (Tank[i].Hmin - Node[n].El)*Ucf[ELEV], (Tank[i].Hmax - Node[n].El)*Ucf[ELEV], sqrt(4.0*Tank[i].A/PI)*Ucf[ELEV], Tank[i].Vmin*SQR(Ucf[ELEV])*Ucf[ELEV]); if ((j = Tank[i].Vcurve) > 0) sprintf(s1,"%-31s",Curve[j].ID); else strcpy(s1,""); fprintf(f, "\n%s %s", s,s1); } } /* Write [PIPES] section */ fprintf(f,"\n\n[PIPES]"); for (i=1; i<=Nlinks; i++) { if (Link[i].Type <= PIPE) { d = Link[i].Diam; kc = Link[i].Kc; if (Formflag == DW) kc = kc*Ucf[ELEV]*1000.0; km = Link[i].Km*SQR(d)*SQR(d)/0.02517; sprintf(s," %-31s %-31s %-31s %12.4f %12.4f", Link[i].ID, Node[Link[i].N1].ID, Node[Link[i].N2].ID, Link[i].Len*Ucf[LENGTH], d*Ucf[DIAM]); if (Formflag == DW) sprintf(s1, "%12.4f %12.4f", kc, km); else sprintf(s1, "%12.4f %12.4f", kc, km); if (Link[i].Type == CV) sprintf(s2,"CV"); else if (Link[i].Stat == CLOSED) sprintf(s2,"CLOSED"); else strcpy(s2,""); fprintf(f,"\n%s %s %s",s,s1,s2); } } /* Write [PUMPS] section */ fprintf(f, "\n\n[PUMPS]"); for (i=1; i<=Npumps; i++) { n = Pump[i].Link; sprintf(s," %-31s %-31s %-31s", Link[n].ID, Node[Link[n].N1].ID, Node[Link[n].N2].ID); /* Pump has constant power */ if (Pump[i].Ptype == CONST_HP) sprintf(s1, " POWER %.4f", Link[n].Km); /* Pump has a head curve */ else if ((j = Pump[i].Hcurve) > 0) sprintf(s1, " HEAD %s", Curve[j].ID); /* Old format used for pump curve */ else { fprintf(f, "\n%s %12.4f %12.4f %12.4f 0.0 %12.4f",s, -Pump[i].H0*Ucf[HEAD], (-Pump[i].H0 - Pump[i].R*pow(Pump[i].Q0,Pump[i].N))*Ucf[HEAD], Pump[i].Q0*Ucf[FLOW], Pump[i].Qmax*Ucf[FLOW]); continue; } strcat(s,s1); if ((j = Pump[i].Upat) > 0) sprintf(s1," PATTERN %s",Pattern[j].ID); else strcpy(s1,""); strcat(s,s1); if (Link[n].Kc != 1.0) sprintf(s1, " SPEED %.4f", Link[n].Kc); else strcpy(s1,""); strcat(s,s1); fprintf(f,"\n%s",s); } /* Write [VALVES] section */ fprintf(f, "\n\n[VALVES]"); for (i=1; i<=Nvalves; i++) { n = Valve[i].Link; d = Link[n].Diam; kc = Link[n].Kc; if (kc == MISSING) kc = 0.0; switch (Link[n].Type) { case FCV: kc *= Ucf[FLOW]; break; case PRV: case PSV: case PBV: kc *= Ucf[PRESSURE]; break; } km = Link[n].Km*SQR(d)*SQR(d)/0.02517; sprintf(s," %-31s %-31s %-31s %12.4f %5s", Link[n].ID, Node[Link[n].N1].ID, Node[Link[n].N2].ID, d*Ucf[DIAM], LinkTxt[Link[n].Type]); if (Link[n].Type == GPV && (j = ROUND(Link[n].Kc)) > 0) sprintf(s1,"%-31s %12.4f", Curve[j].ID, km); else sprintf(s1,"%12.4f %12.4f",kc,km); fprintf(f, "\n%s %s", s,s1); } /* Write [DEMANDS] section */ fprintf(f, "\n\n[DEMANDS]"); ucf = Ucf[DEMAND]; for (i=1; i<=Njuncs; i++) { for (demand = Node[i].D; demand != NULL; demand = demand->next) { sprintf(s," %-31s %14.6f",Node[i].ID,ucf*demand->Base); if ((j = demand->Pat) > 0) sprintf(s1," %s",Pattern[j].ID); else strcpy(s1,""); fprintf(f,"\n%s %s",s,s1); } } /* Write [EMITTERS] section */ fprintf(f, "\n\n[EMITTERS]"); for (i=1; i<=Njuncs; i++) { if (Node[i].Ke == 0.0) continue; ke = Ucf[FLOW]/pow(Ucf[PRESSURE]*Node[i].Ke,(1.0/Qexp)); fprintf(f,"\n %-31s %14.6f",Node[i].ID,ke); } /* Write [STATUS] section */ fprintf(f, "\n\n[STATUS]"); for (i=1; i<=Nlinks; i++) { if (Link[i].Type <= PUMP) { if (Link[i].Stat == CLOSED) fprintf(f, "\n %-31s %s",Link[i].ID,StatTxt[CLOSED]); /* Write pump speed here for pumps with old-style pump curve input */ else if (Link[i].Type == PUMP) { n = PUMPINDEX(i); if ( Pump[n].Hcurve == 0 && Pump[n].Ptype != CONST_HP && Link[i].Kc != 1.0 ) fprintf(f, "\n %-31s %-.4f",Link[i].ID, Link[i].Kc); } } /* Write fixed-status PRVs & PSVs (setting = MISSING) */ else if (Link[i].Kc == MISSING) { if (Link[i].Stat == OPEN) fprintf(f, "\n %-31s %s",Link[i].ID,StatTxt[OPEN]); if (Link[i].Stat == CLOSED) fprintf(f, "\n%-31s %s",Link[i].ID,StatTxt[CLOSED]); } } /* Write [PATTERNS] section */ /* (Use 6 pattern factors per line) */ fprintf(f, "\n\n[PATTERNS]"); for (i=1; i<=Npats; i++) { for (j=0; j<Pattern[i].Length; j++) { if (j % 6 == 0) fprintf(f,"\n %-31s",Pattern[i].ID); fprintf(f," %12.4f",Pattern[i].F[j]); } } /* Write [CURVES] section */ fprintf(f, "\n\n[CURVES]"); for (i=1; i<=Ncurves; i++) { for (j=0; j<Curve[i].Npts; j++) fprintf(f,"\n %-31s %12.4f %12.4f", Curve[i].ID,Curve[i].X[j],Curve[i].Y[j]); } /* Write [CONTROLS] section */ fprintf(f, "\n\n[CONTROLS]"); for (i=1; i<=Ncontrols; i++) { /* Check that controlled link exists */ if ( (j = Control[i].Link) <= 0) continue; /* Get text of control's link status/setting */ if (Control[i].Setting == MISSING) sprintf(s, " LINK %s %s ", Link[j].ID, StatTxt[Control[i].Status]); else { kc = Control[i].Setting; switch(Link[j].Type) { case PRV: case PSV: case PBV: kc *= Ucf[PRESSURE]; break; case FCV: kc *= Ucf[FLOW]; break; } sprintf(s, " LINK %s %.4f",Link[j].ID, kc); } switch (Control[i].Type) { /* Print level control */ case LOWLEVEL: case HILEVEL: n = Control[i].Node; kc = Control[i].Grade - Node[n].El; if (n > Njuncs) kc *= Ucf[HEAD]; else kc *= Ucf[PRESSURE]; fprintf(f, "\n%s IF NODE %s %s %.4f", s, Node[n].ID, ControlTxt[Control[i].Type], kc); break; /* Print timer control */ case TIMER: fprintf(f, "\n%s AT %s %.4f HOURS", s, ControlTxt[TIMER], Control[i].Time/3600.); break; /* Print time-of-day control */ case TIMEOFDAY: fprintf(f, "\n%s AT %s %s", s, ControlTxt[TIMEOFDAY], clocktime(Atime, Control[i].Time)); break; } } /* Write [QUALITY] section */ /* (Skip nodes with default quality of 0) */ fprintf(f, "\n\n[QUALITY]"); for (i=1; i<=Nnodes; i++) { if (Node[i].C0 == 0.0) continue; fprintf(f, "\n %-31s %14.6f",Node[i].ID,Node[i].C0*Ucf[QUALITY]); } /* Write [SOURCES] section */ fprintf(f, "\n\n[SOURCES]"); for (i=1; i<=Nnodes; i++) { source = Node[i].S; if (source == NULL) continue; sprintf(s," %-31s %-8s %14.6f", Node[i].ID, SourceTxt[source->Type], source->C0); if ((j = source->Pat) > 0) sprintf(s1,"%s",Pattern[j].ID); else strcpy(s1,""); fprintf(f,"\n%s %s",s,s1); } /* Write [MIXING] section */ fprintf(f, "\n\n[MIXING]"); for (i=1; i<=Ntanks; i++) { if (Tank[i].A == 0.0) continue; fprintf(f, "\n %-31s %-8s %12.4f", Node[Tank[i].Node].ID, MixTxt[Tank[i].MixModel], (Tank[i].V1max/Tank[i].Vmax)); } /* Write [REACTIONS] section */ fprintf(f, "\n\n[REACTIONS]"); fprintf(f, "\n ORDER BULK %-.2f", BulkOrder); fprintf(f, "\n ORDER WALL %-.0f", WallOrder); fprintf(f, "\n ORDER TANK %-.2f", TankOrder); fprintf(f, "\n GLOBAL BULK %-.6f", Kbulk*SECperDAY); fprintf(f, "\n GLOBAL WALL %-.6f", Kwall*SECperDAY); if (Climit > 0.0) fprintf(f, "\n LIMITING POTENTIAL %-.6f", Climit); if (Rfactor != MISSING && Rfactor != 0.0) fprintf(f, "\n ROUGHNESS CORRELATION %-.6f",Rfactor); for (i=1; i<=Nlinks; i++) { if (Link[i].Type > PIPE) continue; if (Link[i].Kb != Kbulk) fprintf(f, "\n BULK %-31s %-.6f",Link[i].ID,Link[i].Kb*SECperDAY); if (Link[i].Kw != Kwall) fprintf(f, "\n WALL %-31s %-.6f",Link[i].ID,Link[i].Kw*SECperDAY); } for (i=1; i<=Ntanks; i++) { if (Tank[i].A == 0.0) continue; if (Tank[i].Kb != Kbulk) fprintf(f, "\n TANK %-31s %-.6f",Node[Tank[i].Node].ID, Tank[i].Kb*SECperDAY); } /* Write [ENERGY] section */ fprintf(f, "\n\n[ENERGY]"); if (Ecost != 0.0) fprintf(f, "\n GLOBAL PRICE %-.4f", Ecost); if (Epat != 0) fprintf(f, "\n GLOBAL PATTERN %s", Pattern[Epat].ID); fprintf(f, "\n GLOBAL EFFIC %-.4f", Epump); fprintf(f, "\n DEMAND CHARGE %-.4f", Dcost); for (i=1; i<=Npumps; i++) { if (Pump[i].Ecost > 0.0) fprintf(f, "\n PUMP %-31s PRICE %-.4f", Link[Pump[i].Link].ID,Pump[i].Ecost); if (Pump[i].Epat > 0.0) fprintf(f, "\n PUMP %-31s PATTERN %s", Link[Pump[i].Link].ID,Pattern[Pump[i].Epat].ID); if (Pump[i].Ecurve > 0.0) fprintf(f, "\n PUMP %-31s EFFIC %s", Link[Pump[i].Link].ID,Curve[Pump[i].Ecurve].ID); } /* Write [TIMES] section */ fprintf(f, "\n\n[TIMES]"); fprintf(f, "\n DURATION %s",clocktime(Atime,Dur)); fprintf(f, "\n HYDRAULIC TIMESTEP %s",clocktime(Atime,Hstep)); fprintf(f, "\n QUALITY TIMESTEP %s",clocktime(Atime,Qstep)); fprintf(f, "\n REPORT TIMESTEP %s",clocktime(Atime,Rstep)); fprintf(f, "\n REPORT START %s",clocktime(Atime,Rstart)); fprintf(f, "\n PATTERN TIMESTEP %s",clocktime(Atime,Pstep)); fprintf(f, "\n PATTERN START %s",clocktime(Atime,Pstart)); fprintf(f, "\n RULE TIMESTEP %s",clocktime(Atime,Rulestep)); fprintf(f, "\n START CLOCKTIME %s",clocktime(Atime,Tstart)); fprintf(f, "\n STATISTIC %s",TstatTxt[Tstatflag]); /* Write [OPTIONS] section */ fprintf(f, "\n\n[OPTIONS]"); fprintf(f, "\n UNITS %s", FlowUnitsTxt[Flowflag]); fprintf(f, "\n PRESSURE %s", PressUnitsTxt[Pressflag]); fprintf(f, "\n HEADLOSS %s", FormTxt[Formflag]); if (DefPat >= 1 && DefPat <= Npats) fprintf(f, "\n PATTERN %s", Pattern[DefPat].ID); if (Hydflag == USE) fprintf(f, "\n HYDRAULICS USE %s", HydFname); if (Hydflag == SAVE) fprintf(f, "\n HYDRAULICS SAVE %s", HydFname); if (ExtraIter == -1) fprintf(f, "\n UNBALANCED STOP"); if (ExtraIter >= 0) fprintf(f, "\n UNBALANCED CONTINUE %d", ExtraIter); if (Qualflag == CHEM) fprintf(f, "\n QUALITY %s %s", ChemName, ChemUnits); if (Qualflag == TRACE) fprintf(f, "\n QUALITY TRACE %-31s", Node[TraceNode].ID); if (Qualflag == AGE) fprintf(f, "\n QUALITY AGE"); if (Qualflag == NONE) fprintf(f, "\n QUALITY NONE"); fprintf(f, "\n DEMAND MULTIPLIER %-.4f", Dmult); fprintf(f, "\n EMITTER EXPONENT %-.4f", 1.0/Qexp); fprintf(f, "\n VISCOSITY %-.6f", Viscos/VISCOS); fprintf(f, "\n DIFFUSIVITY %-.6f", Diffus/DIFFUS); fprintf(f, "\n SPECIFIC GRAVITY %-.6f", SpGrav); fprintf(f, "\n TRIALS %-d", MaxIter); fprintf(f, "\n ACCURACY %-.8f", Hacc); fprintf(f, "\n TOLERANCE %-.8f", Ctol*Ucf[QUALITY]); fprintf(f, "\n CHECKFREQ %-d", CheckFreq); fprintf(f, "\n MAXCHECK %-d", MaxCheck); fprintf(f, "\n DAMPLIMIT %-.8f", DampLimit); /* Write [REPORT] section */ fprintf(f, "\n\n[REPORT]"); fprintf(f, "\n PAGESIZE %d", PageSize); fprintf(f, "\n STATUS %s", RptFlagTxt[Statflag]); fprintf(f, "\n SUMMARY %s", RptFlagTxt[Summaryflag]); fprintf(f, "\n ENERGY %s", RptFlagTxt[Energyflag]); switch (Nodeflag) { case 0: fprintf(f, "\n NODES NONE"); break; case 1: fprintf(f, "\n NODES ALL"); break; default: j = 0; for (i=1; i<=Nnodes; i++) { if (Node[i].Rpt == 1) { if (j % 5 == 0) fprintf(f, "\n NODES "); fprintf(f, "%s ", Node[i].ID); j++; } } } switch (Linkflag) { case 0: fprintf(f, "\n LINKS NONE"); break; case 1: fprintf(f, "\n LINKS ALL"); break; default: j = 0; for (i=1; i<=Nlinks; i++) { if (Link[i].Rpt == 1) { if (j % 5 == 0) fprintf(f, "\n LINKS "); fprintf(f, "%s ", Link[i].ID); j++; } } } for (i=0; i<FRICTION; i++) { if (Field[i].Enabled == TRUE) { fprintf(f, "\n %-20sPRECISION %d", Field[i].Name, Field[i].Precision); if (Field[i].RptLim[LOW] < BIG) fprintf(f, "\n %-20sBELOW %.6f", Field[i].Name, Field[i].RptLim[LOW]); if (Field[i].RptLim[HI] > -BIG) fprintf(f, "\n %-20sABOVE %.6f", Field[i].Name, Field[i].RptLim[HI]); } else fprintf(f, "\n %-20sNO", Field[i].Name); } fprintf(f, "\n"); /* Save auxilary data to new input file */ saveauxdata(f); /* Close the new input file */ fprintf(f, "\n[END]"); fclose(f); return(0); }
void convertunits() /* **-------------------------------------------------------------- ** Input: none ** Output: none ** Purpose: converts units of input data **-------------------------------------------------------------- */ { int i,j,k; double ucf; /* Unit conversion factor */ Pdemand demand; /* Pointer to demand record */ /* Convert nodal elevations & initial WQ */ /* (WQ source units are converted in QUALITY.C */ for (i=1; i<=Nnodes; i++) { Node[i].El /= Ucf[ELEV]; Node[i].C0 /= Ucf[QUALITY]; } /* Convert demands */ for (i=1; i<=Njuncs; i++) { for (demand = Node[i].D; demand != NULL; demand = demand->next) demand->Base /= Ucf[DEMAND]; } /* Convert emitter discharge coeffs. to head loss coeff. */ ucf = pow(Ucf[FLOW],Qexp)/Ucf[PRESSURE]; for (i=1; i<=Njuncs; i++) if (Node[i].Ke > 0.0) Node[i].Ke = ucf/pow(Node[i].Ke,Qexp); /* Initialize tank variables (convert tank levels to elevations) */ for (j=1; j<=Ntanks; j++) { i = Tank[j].Node; Tank[j].H0 = Node[i].El + Tank[j].H0/Ucf[ELEV]; Tank[j].Hmin = Node[i].El + Tank[j].Hmin/Ucf[ELEV]; Tank[j].Hmax = Node[i].El + Tank[j].Hmax/Ucf[ELEV]; Tank[j].A = PI*SQR(Tank[j].A/Ucf[ELEV])/4.0; Tank[j].V0 /= Ucf[VOLUME]; Tank[j].Vmin /= Ucf[VOLUME]; Tank[j].Vmax /= Ucf[VOLUME]; Tank[j].Kb /= SECperDAY; Tank[j].V = Tank[j].V0; Tank[j].C = Node[i].C0; Tank[j].V1max *= Tank[j].Vmax; } /* Convert WQ option concentration units */ Climit /= Ucf[QUALITY]; Ctol /= Ucf[QUALITY]; /* Convert global reaction coeffs. */ Kbulk /= SECperDAY; Kwall /= SECperDAY; /* Convert units of link parameters */ for (k=1; k<=Nlinks; k++) { if (Link[k].Type <= PIPE) { /* Convert pipe parameter units: */ /* - for Darcy-Weisbach formula, convert roughness */ /* from millifeet (or mm) to ft (or m) */ /* - for US units, convert diameter from inches to ft */ if (Formflag == DW) Link[k].Kc /= (1000.0*Ucf[ELEV]); Link[k].Diam /= Ucf[DIAM]; Link[k].Len /= Ucf[LENGTH]; /* Convert minor loss coeff. from V^2/2g basis to Q^2 basis */ Link[k].Km = 0.02517*Link[k].Km/SQR(Link[k].Diam)/SQR(Link[k].Diam); /* Convert units on reaction coeffs. */ Link[k].Kb /= SECperDAY; Link[k].Kw /= SECperDAY; } else if (Link[k].Type == PUMP ) { /* Convert units for pump curve parameters */ i = PUMPINDEX(k); if (Pump[i].Ptype == CONST_HP) { /* For constant hp pump, convert kw to hp */ if (Unitsflag == SI) Pump[i].R /= Ucf[POWER]; } else { /* For power curve pumps, convert */ /* shutoff head and flow coefficient */ if (Pump[i].Ptype == POWER_FUNC) { Pump[i].H0 /= Ucf[HEAD]; Pump[i].R *= (pow(Ucf[FLOW],Pump[i].N)/Ucf[HEAD]); } /* Convert flow range & max. head units */ Pump[i].Q0 /= Ucf[FLOW]; Pump[i].Qmax /= Ucf[FLOW]; Pump[i].Hmax /= Ucf[HEAD]; } } else { /* For flow control valves, convert flow setting */ /* while for other valves convert pressure setting */ Link[k].Diam /= Ucf[DIAM]; Link[k].Km = 0.02517*Link[k].Km/SQR(Link[k].Diam)/SQR(Link[k].Diam); if (Link[k].Kc != MISSING) switch (Link[k].Type) { case FCV: Link[k].Kc /= Ucf[FLOW]; break; case PRV: case PSV: case PBV: Link[k].Kc /= Ucf[PRESSURE]; break; } } /* Compute flow resistances */ resistance(k); } /* Convert units on control settings */ for (i=1; i<=Ncontrols; i++) { if ( (k = Control[i].Link) == 0) continue; if ( (j = Control[i].Node) > 0) { /* j = index of controlling node, and if */ /* j > Njuncs, then control is based on tank level */ /* otherwise control is based on nodal pressure */ if (j > Njuncs) Control[i].Grade = Node[j].El + Control[i].Grade/Ucf[ELEV]; else Control[i].Grade = Node[j].El + Control[i].Grade/Ucf[PRESSURE]; } /* Convert units on valve settings */ if (Control[i].Setting != MISSING) switch (Link[k].Type) { case PRV: case PSV: case PBV: Control[i].Setting /= Ucf[PRESSURE]; break; case FCV: Control[i].Setting /= Ucf[FLOW]; } } } /* End of convertunits */