iface.c
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | //----------------------------------------------------------------------------- | ||
| 2 | // iface.c | ||
| 3 | // | ||
| 4 | // Project: EPA SWMM5 | ||
| 5 | // Version: 5.2 | ||
| 6 | // Date: 11/01/21 (Build 5.2.0) | ||
| 7 | // Author: L. Rossman | ||
| 8 | // | ||
| 9 | // Routing interface file functions. | ||
| 10 | // | ||
| 11 | // Build 5.2.0: | ||
| 12 | // - Support added for relative file names. | ||
| 13 | //----------------------------------------------------------------------------- | ||
| 14 | #define _CRT_SECURE_NO_DEPRECATE | ||
| 15 | |||
| 16 | #include <stdlib.h> | ||
| 17 | #include <string.h> | ||
| 18 | #include "headers.h" | ||
| 19 | |||
| 20 | //----------------------------------------------------------------------------- | ||
| 21 | // Imported variables | ||
| 22 | //----------------------------------------------------------------------------- | ||
| 23 | extern double Qcf[]; // flow units conversion factors | ||
| 24 | // (see swmm5.c) | ||
| 25 | |||
| 26 | //----------------------------------------------------------------------------- | ||
| 27 | // Shared variables | ||
| 28 | //----------------------------------------------------------------------------- | ||
| 29 | static int IfaceFlowUnits; // flow units for routing interface file | ||
| 30 | static int IfaceStep; // interface file time step (sec) | ||
| 31 | static int NumIfacePolluts; // number of pollutants in interface file | ||
| 32 | static int* IfacePolluts; // indexes of interface file pollutants | ||
| 33 | static int NumIfaceNodes; // number of nodes on interface file | ||
| 34 | static int* IfaceNodes; // indexes of nodes on interface file | ||
| 35 | static double** OldIfaceValues; // interface flows & WQ at previous time | ||
| 36 | static double** NewIfaceValues; // interface flows & WQ at next time | ||
| 37 | static double IfaceFrac; // fraction of interface file time step | ||
| 38 | static DateTime OldIfaceDate; // previous date of interface values | ||
| 39 | static DateTime NewIfaceDate; // next date of interface values | ||
| 40 | |||
| 41 | //----------------------------------------------------------------------------- | ||
| 42 | // External Functions (declared in funcs.h) | ||
| 43 | //----------------------------------------------------------------------------- | ||
| 44 | // iface_readFileParams (called by input_readLine) | ||
| 45 | // iface_openRoutingFiles (called by routing_open) | ||
| 46 | // iface_closeRoutingFiles (called by routing_close) | ||
| 47 | // iface_getNumIfaceNodes (called by addIfaceInflows in routing.c) | ||
| 48 | // iface_getIfaceNode (called by addIfaceInflows in routing.c) | ||
| 49 | // iface_getIfaceFlow (called by addIfaceInflows in routing.c) | ||
| 50 | // iface_getIfaceQual (called by addIfaceInflows in routing.c) | ||
| 51 | // iface_saveOutletResults (called by output_saveResults) | ||
| 52 | |||
| 53 | //----------------------------------------------------------------------------- | ||
| 54 | // Local functions | ||
| 55 | //----------------------------------------------------------------------------- | ||
| 56 | static void openFileForOutput(void); | ||
| 57 | static void openFileForInput(void); | ||
| 58 | static int getIfaceFilePolluts(void); | ||
| 59 | static int getIfaceFileNodes(void); | ||
| 60 | static void setOldIfaceValues(void); | ||
| 61 | static void readNewIfaceValues(void); | ||
| 62 | static int isOutletNode(int node); | ||
| 63 | |||
| 64 | //============================================================================= | ||
| 65 | |||
| 66 | 13 | int iface_readFileParams(char* tok[], int ntoks) | |
| 67 | // | ||
| 68 | // Input: tok[] = array of string tokens | ||
| 69 | // ntoks = number of tokens | ||
| 70 | // Output: returns an error code | ||
| 71 | // Purpose: reads interface file information from a line of input data. | ||
| 72 | // | ||
| 73 | // Data format is: | ||
| 74 | // USE/SAVE FileType FileName | ||
| 75 | // | ||
| 76 | { | ||
| 77 | char k; | ||
| 78 | int j; | ||
| 79 | char fname[MAXFNAME+1]; | ||
| 80 | |||
| 81 | // --- determine file disposition and type | ||
| 82 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if ( ntoks < 2 ) return error_setInpError(ERR_ITEMS, ""); |
| 83 | 13 | k = (char)findmatch(tok[0], FileModeWords); | |
| 84 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if ( k < 0 ) return error_setInpError(ERR_KEYWORD, tok[0]); |
| 85 | 13 | j = findmatch(tok[1], FileTypeWords); | |
| 86 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if ( j < 0 ) return error_setInpError(ERR_KEYWORD, tok[1]); |
| 87 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if ( ntoks < 3 ) return 0; |
| 88 | 13 | sstrncpy(fname, tok[2], MAXFNAME); | |
| 89 | |||
| 90 | // --- process file name | ||
| 91 |
6/7✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 6 not taken.
|
13 | switch ( j ) |
| 92 | { | ||
| 93 | 2 | case RAINFALL_FILE: | |
| 94 | 2 | Frain.mode = k; | |
| 95 | 2 | sstrncpy(Frain.name, addAbsolutePath(fname), MAXFNAME); | |
| 96 | 2 | break; | |
| 97 | |||
| 98 | 4 | case RUNOFF_FILE: | |
| 99 | 4 | Frunoff.mode = k; | |
| 100 | 4 | sstrncpy(Frunoff.name, addAbsolutePath(fname), MAXFNAME); | |
| 101 | 4 | break; | |
| 102 | |||
| 103 | 2 | case HOTSTART_FILE: | |
| 104 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
|
2 | if ( k == USE_FILE ) |
| 105 | { | ||
| 106 | 1 | Fhotstart1.mode = k; | |
| 107 | 1 | sstrncpy(Fhotstart1.name, addAbsolutePath(fname), MAXFNAME); | |
| 108 | } | ||
| 109 |
1/2✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
|
1 | else if ( k == SAVE_FILE ) |
| 110 | { | ||
| 111 | 1 | Fhotstart2.mode = k; | |
| 112 | 1 | sstrncpy(Fhotstart2.name, addAbsolutePath(fname), MAXFNAME); | |
| 113 | } | ||
| 114 | 2 | break; | |
| 115 | |||
| 116 | 3 | case RDII_FILE: | |
| 117 | 3 | Frdii.mode = k; | |
| 118 | 3 | sstrncpy(Frdii.name, fname, MAXFNAME); | |
| 119 | 3 | break; | |
| 120 | |||
| 121 | 1 | case INFLOWS_FILE: | |
| 122 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | if ( k != USE_FILE ) return error_setInpError(ERR_ITEMS, ""); |
| 123 | 1 | Finflows.mode = k; | |
| 124 | 1 | sstrncpy(Finflows.name, addAbsolutePath(fname), MAXFNAME); | |
| 125 | 1 | break; | |
| 126 | |||
| 127 | 1 | case OUTFLOWS_FILE: | |
| 128 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | if ( k != SAVE_FILE ) return error_setInpError(ERR_ITEMS, ""); |
| 129 | 1 | Foutflows.mode = k; | |
| 130 | 1 | sstrncpy(Foutflows.name, addAbsolutePath(fname), MAXFNAME); | |
| 131 | 1 | break; | |
| 132 | } | ||
| 133 | 13 | return 0; | |
| 134 | } | ||
| 135 | |||
| 136 | //============================================================================= | ||
| 137 | |||
| 138 | 58 | void iface_openRoutingFiles() | |
| 139 | // | ||
| 140 | // Input: none | ||
| 141 | // Output: none | ||
| 142 | // Purpose: opens routing interface files. | ||
| 143 | // | ||
| 144 | { | ||
| 145 | // --- initialize shared variables | ||
| 146 | 58 | NumIfacePolluts = 0; | |
| 147 | 58 | IfacePolluts = NULL; | |
| 148 | 58 | NumIfaceNodes = 0; | |
| 149 | 58 | IfaceNodes = NULL; | |
| 150 | 58 | OldIfaceValues = NULL; | |
| 151 | 58 | NewIfaceValues = NULL; | |
| 152 | |||
| 153 | // --- check that inflows & outflows files are not the same | ||
| 154 |
3/4✓ Branch 0 taken 1 time.
✓ Branch 1 taken 57 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
|
58 | if ( Foutflows.mode != NO_FILE && Finflows.mode != NO_FILE ) |
| 155 | { | ||
| 156 | ✗ | if ( strcomp(Foutflows.name, Finflows.name) ) | |
| 157 | { | ||
| 158 | ✗ | report_writeErrorMsg(ERR_ROUTING_FILE_NAMES, ""); | |
| 159 | ✗ | return; | |
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 163 | // --- open the file for reading or writing | ||
| 164 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 57 times.
|
58 | if ( Foutflows.mode == SAVE_FILE ) openFileForOutput(); |
| 165 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 57 times.
|
58 | if ( Finflows.mode == USE_FILE ) openFileForInput(); |
| 166 | } | ||
| 167 | |||
| 168 | //============================================================================= | ||
| 169 | |||
| 170 | 58 | void iface_closeRoutingFiles() | |
| 171 | // | ||
| 172 | // Input: none | ||
| 173 | // Output: none | ||
| 174 | // Purpose: closes routing interface files. | ||
| 175 | // | ||
| 176 | { | ||
| 177 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
|
58 | FREE(IfacePolluts); |
| 178 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 57 times.
|
58 | FREE(IfaceNodes); |
| 179 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 57 times.
|
58 | if ( OldIfaceValues != NULL ) project_freeMatrix(OldIfaceValues); |
| 180 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 57 times.
|
58 | if ( NewIfaceValues != NULL ) project_freeMatrix(NewIfaceValues); |
| 181 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 57 times.
|
58 | if ( Finflows.file ) fclose(Finflows.file); |
| 182 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 57 times.
|
58 | if ( Foutflows.file ) fclose(Foutflows.file); |
| 183 | 58 | } | |
| 184 | |||
| 185 | //============================================================================= | ||
| 186 | |||
| 187 | 4321 | int iface_getNumIfaceNodes(DateTime currentDate) | |
| 188 | // | ||
| 189 | // Input: currentDate = current date/time | ||
| 190 | // Output: returns number of interface nodes if data exists or | ||
| 191 | // 0 otherwise | ||
| 192 | // Purpose: reads inflow data from interface file at current date. | ||
| 193 | // | ||
| 194 | { | ||
| 195 | // --- return 0 if file begins after current date | ||
| 196 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4321 times.
|
4321 | if ( OldIfaceDate > currentDate ) return 0; |
| 197 | |||
| 198 | // --- keep updating new interface values until current date bracketed | ||
| 199 |
3/4✓ Branch 0 taken 72 times.
✓ Branch 1 taken 4321 times.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
|
4393 | while ( NewIfaceDate < currentDate && NewIfaceDate != NO_DATE ) |
| 200 | { | ||
| 201 | 72 | setOldIfaceValues(); | |
| 202 | 72 | readNewIfaceValues(); | |
| 203 | } | ||
| 204 | |||
| 205 | // --- return 0 if no data available | ||
| 206 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4321 times.
|
4321 | if ( NewIfaceDate == NO_DATE ) return 0; |
| 207 | |||
| 208 | // --- find fraction current date is bewteen old & new interface dates | ||
| 209 | 4321 | IfaceFrac = (currentDate - OldIfaceDate) / (NewIfaceDate - OldIfaceDate); | |
| 210 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4321 times.
|
4321 | IfaceFrac = MAX(0.0, IfaceFrac); |
| 211 |
1/2✓ Branch 0 taken 4321 times.
✗ Branch 1 not taken.
|
4321 | IfaceFrac = MIN(IfaceFrac, 1.0); |
| 212 | |||
| 213 | // --- return number of interface nodes | ||
| 214 | 4321 | return NumIfaceNodes; | |
| 215 | } | ||
| 216 | |||
| 217 | //============================================================================= | ||
| 218 | |||
| 219 | 4321 | int iface_getIfaceNode(int index) | |
| 220 | // | ||
| 221 | // Input: index = interface file node index | ||
| 222 | // Output: returns project node index | ||
| 223 | // Purpose: finds index of project node associated with interface node index | ||
| 224 | // | ||
| 225 | { | ||
| 226 |
2/4✓ Branch 0 taken 4321 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4321 times.
✗ Branch 3 not taken.
|
4321 | if ( index >= 0 && index < NumIfaceNodes ) return IfaceNodes[index]; |
| 227 | ✗ | else return -1; | |
| 228 | } | ||
| 229 | |||
| 230 | //============================================================================= | ||
| 231 | |||
| 232 | 4321 | double iface_getIfaceFlow(int index) | |
| 233 | // | ||
| 234 | // Input: index = interface file node index | ||
| 235 | // Output: returns inflow to node | ||
| 236 | // Purpose: finds interface flow for particular node index. | ||
| 237 | // | ||
| 238 | { | ||
| 239 | double q1, q2; | ||
| 240 | |||
| 241 |
2/4✓ Branch 0 taken 4321 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4321 times.
✗ Branch 3 not taken.
|
4321 | if ( index >= 0 && index < NumIfaceNodes ) |
| 242 | { | ||
| 243 | // --- interpolate flow between old and new values | ||
| 244 | 4321 | q1 = OldIfaceValues[index][0]; | |
| 245 | 4321 | q2 = NewIfaceValues[index][0]; | |
| 246 | 4321 | return (1.0 - IfaceFrac)*q1 + IfaceFrac*q2; | |
| 247 | } | ||
| 248 | ✗ | else return 0.0; | |
| 249 | } | ||
| 250 | |||
| 251 | //============================================================================= | ||
| 252 | |||
| 253 | ✗ | double iface_getIfaceQual(int index, int pollut) | |
| 254 | // | ||
| 255 | // Input: index = index of node on interface file | ||
| 256 | // pollut = index of pollutant on interface file | ||
| 257 | // Output: returns inflow pollutant concentration | ||
| 258 | // Purpose: finds interface concentration for particular node index & pollutant. | ||
| 259 | // | ||
| 260 | { | ||
| 261 | int j; | ||
| 262 | double c1, c2; | ||
| 263 | |||
| 264 | ✗ | if ( index >= 0 && index < NumIfaceNodes ) | |
| 265 | { | ||
| 266 | // --- find index of pollut on interface file | ||
| 267 | ✗ | j = IfacePolluts[pollut]; | |
| 268 | ✗ | if ( j < 0 ) return 0.0; | |
| 269 | |||
| 270 | // --- interpolate flow between old and new values | ||
| 271 | // (remember that 1st col. of values matrix is for flow) | ||
| 272 | ✗ | c1 = OldIfaceValues[index][j+1]; | |
| 273 | ✗ | c2 = NewIfaceValues[index][j+1]; | |
| 274 | ✗ | return (1.0 - IfaceFrac)*c1 + IfaceFrac*c2; | |
| 275 | } | ||
| 276 | ✗ | else return 0.0; | |
| 277 | } | ||
| 278 | |||
| 279 | //============================================================================= | ||
| 280 | |||
| 281 | 73 | void iface_saveOutletResults(DateTime reportDate, FILE* file) | |
| 282 | // | ||
| 283 | // Input: reportDate = reporting date/time | ||
| 284 | // file = ptr. to interface file | ||
| 285 | // Output: none | ||
| 286 | // Purpose: saves system outflows to routing interface file. | ||
| 287 | // | ||
| 288 | { | ||
| 289 | int i, p, yr, mon, day, hr, min, sec; | ||
| 290 | char theDate[26]; | ||
| 291 | 73 | datetime_decodeDate(reportDate, &yr, &mon, &day); | |
| 292 | 73 | datetime_decodeTime(reportDate, &hr, &min, &sec); | |
| 293 | 73 | snprintf(theDate, 26, " %04d %02d %02d %02d %02d %02d ", | |
| 294 | yr, mon, day, hr, min, sec); | ||
| 295 |
2/2✓ Branch 0 taken 146 times.
✓ Branch 1 taken 73 times.
|
219 | for (i=0; i<Nobjects[NODE]; i++) |
| 296 | { | ||
| 297 | // --- check that node is an outlet node | ||
| 298 |
2/2✓ Branch 1 taken 73 times.
✓ Branch 2 taken 73 times.
|
146 | if ( !isOutletNode(i) ) continue; |
| 299 | |||
| 300 | // --- write node ID, date, flow, and quality to file | ||
| 301 | 73 | fprintf(file, "\n%-16s", Node[i].ID); | |
| 302 | 73 | fprintf(file, "%s", theDate); | |
| 303 | 73 | fprintf(file, " %-10f", Node[i].inflow * UCF(FLOW)); | |
| 304 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
|
73 | for ( p = 0; p < Nobjects[POLLUT]; p++ ) |
| 305 | { | ||
| 306 | ✗ | fprintf(file, " %-10f", Node[i].newQual[p]); | |
| 307 | } | ||
| 308 | } | ||
| 309 | 73 | } | |
| 310 | |||
| 311 | //============================================================================= | ||
| 312 | |||
| 313 | 1 | void openFileForOutput() | |
| 314 | // | ||
| 315 | // Input: none | ||
| 316 | // Output: none | ||
| 317 | // Purpose: opens a routing interface file for writing. | ||
| 318 | // | ||
| 319 | { | ||
| 320 | int i, n; | ||
| 321 | |||
| 322 | // --- open the routing file for writing text | ||
| 323 | 1 | Foutflows.file = fopen(Foutflows.name, "wt"); | |
| 324 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | if ( Foutflows.file == NULL ) |
| 325 | { | ||
| 326 | ✗ | report_writeErrorMsg(ERR_ROUTING_FILE_OPEN, Foutflows.name); | |
| 327 | ✗ | return; | |
| 328 | } | ||
| 329 | |||
| 330 | // --- write title & reporting time step to file | ||
| 331 | 1 | fprintf(Foutflows.file, "SWMM5 Interface File"); | |
| 332 | 1 | fprintf(Foutflows.file, "\n%s", Title[0]); | |
| 333 | 1 | fprintf(Foutflows.file, "\n%-4d - reporting time step in sec", ReportStep); | |
| 334 | |||
| 335 | // --- write number & names of each constituent (including flow) to file | ||
| 336 | 1 | fprintf(Foutflows.file, "\n%-4d - number of constituents as listed below:", | |
| 337 | 1 | Nobjects[POLLUT] + 1); | |
| 338 | 1 | fprintf(Foutflows.file, "\nFLOW %s", FlowUnitWords[FlowUnits]); | |
| 339 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | for (i=0; i<Nobjects[POLLUT]; i++) |
| 340 | { | ||
| 341 | ✗ | fprintf(Foutflows.file, "\n%s %s", Pollut[i].ID, | |
| 342 | ✗ | QualUnitsWords[Pollut[i].units]); | |
| 343 | } | ||
| 344 | |||
| 345 | // --- count number of outlet nodes | ||
| 346 | 1 | n = 0; | |
| 347 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
|
3 | for (i=0; i<Nobjects[NODE]; i++) |
| 348 | { | ||
| 349 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
|
2 | if ( isOutletNode(i) ) n++; |
| 350 | } | ||
| 351 | |||
| 352 | // --- write number and names of outlet nodes to file | ||
| 353 | 1 | fprintf(Foutflows.file, "\n%-4d - number of nodes as listed below:", n); | |
| 354 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
|
3 | for (i=0; i<Nobjects[NODE]; i++) |
| 355 | { | ||
| 356 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
|
2 | if ( isOutletNode(i) ) |
| 357 | 1 | fprintf(Foutflows.file, "\n%s", Node[i].ID); | |
| 358 | } | ||
| 359 | |||
| 360 | // --- write column headings | ||
| 361 | 1 | fprintf(Foutflows.file, | |
| 362 | "\nNode Year Mon Day Hr Min Sec FLOW "); | ||
| 363 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | for (i=0; i<Nobjects[POLLUT]; i++) |
| 364 | { | ||
| 365 | ✗ | fprintf(Foutflows.file, " %-10s", Pollut[i].ID); | |
| 366 | } | ||
| 367 | |||
| 368 | // --- if reporting starts immediately, save initial outlet values | ||
| 369 |
1/2✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
|
1 | if ( ReportStart == StartDateTime ) |
| 370 | { | ||
| 371 | 1 | iface_saveOutletResults(ReportStart, Foutflows.file); | |
| 372 | } | ||
| 373 | } | ||
| 374 | |||
| 375 | //============================================================================= | ||
| 376 | |||
| 377 | 1 | void openFileForInput() | |
| 378 | // | ||
| 379 | // Input: none | ||
| 380 | // Output: none | ||
| 381 | // Purpose: opens a routing interface file for reading. | ||
| 382 | // | ||
| 383 | { | ||
| 384 | int err; // error code | ||
| 385 | char line[MAXLINE+1]; // line from Routing interface file | ||
| 386 | char s[MAXLINE+1]; // general string variable | ||
| 387 | |||
| 388 | // --- open the routing interface file for reading text | ||
| 389 | 1 | Finflows.file = fopen(Finflows.name, "rt"); | |
| 390 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | if ( Finflows.file == NULL ) |
| 391 | { | ||
| 392 | ✗ | report_writeErrorMsg(ERR_ROUTING_FILE_OPEN, Finflows.name); | |
| 393 | ✗ | return; | |
| 394 | } | ||
| 395 | |||
| 396 | // --- check for correct file type | ||
| 397 | 1 | fgets(line, MAXLINE, Finflows.file); | |
| 398 |
2/4✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
|
1 | if ( !sscanf(line, "%s", s) || !strcomp(s, "SWMM5") ) |
| 399 | { | ||
| 400 | ✗ | report_writeErrorMsg(ERR_ROUTING_FILE_FORMAT, Finflows.name); | |
| 401 | ✗ | return; | |
| 402 | } | ||
| 403 | |||
| 404 | // --- skip title line | ||
| 405 | 1 | fgets(line, MAXLINE, Finflows.file); | |
| 406 | |||
| 407 | // --- read reporting time step (sec) | ||
| 408 | 1 | IfaceStep = 0; | |
| 409 | 1 | fgets(line, MAXLINE, Finflows.file); | |
| 410 |
2/4✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
|
1 | if ( !sscanf(line, "%d", &IfaceStep) || IfaceStep <= 0 ) |
| 411 | { | ||
| 412 | ✗ | report_writeErrorMsg(ERR_ROUTING_FILE_FORMAT, Finflows.name); | |
| 413 | ✗ | return; | |
| 414 | } | ||
| 415 | |||
| 416 | // --- match constituents in file with those in project | ||
| 417 | 1 | err = getIfaceFilePolluts(); | |
| 418 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | if ( err > 0 ) |
| 419 | { | ||
| 420 | ✗ | report_writeErrorMsg(err, Finflows.name); | |
| 421 | ✗ | return; | |
| 422 | } | ||
| 423 | |||
| 424 | // --- match nodes in file with those in project | ||
| 425 | 1 | err = getIfaceFileNodes(); | |
| 426 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | if ( err > 0 ) |
| 427 | { | ||
| 428 | ✗ | report_writeErrorMsg(err, Finflows.name); | |
| 429 | ✗ | return; | |
| 430 | } | ||
| 431 | |||
| 432 | // --- create matrices for old & new interface flows & WQ values | ||
| 433 | 1 | OldIfaceValues = project_createMatrix(NumIfaceNodes, | |
| 434 | 1+NumIfacePolluts); | ||
| 435 | 1 | NewIfaceValues = project_createMatrix(NumIfaceNodes, | |
| 436 | 1+NumIfacePolluts); | ||
| 437 |
2/4✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
|
1 | if ( OldIfaceValues == NULL || NewIfaceValues == NULL ) |
| 438 | { | ||
| 439 | ✗ | report_writeErrorMsg(ERR_MEMORY, ""); | |
| 440 | ✗ | return; | |
| 441 | } | ||
| 442 | |||
| 443 | // --- read in new interface flows & WQ values | ||
| 444 | 1 | readNewIfaceValues(); | |
| 445 | 1 | OldIfaceDate = NewIfaceDate; | |
| 446 | } | ||
| 447 | |||
| 448 | //============================================================================= | ||
| 449 | |||
| 450 | 1 | int getIfaceFilePolluts() | |
| 451 | // | ||
| 452 | // Input: none | ||
| 453 | // Output: returns an error code | ||
| 454 | // Purpose: reads names of pollutants saved on the inflows interface file. | ||
| 455 | // | ||
| 456 | { | ||
| 457 | int i, j; | ||
| 458 | char line[MAXLINE+1]; // line from inflows interface file | ||
| 459 | char s1[MAXLINE+1]; // general string variable | ||
| 460 | char s2[MAXLINE+1]; | ||
| 461 | |||
| 462 | // --- read number of pollutants (minus FLOW) | ||
| 463 | 1 | fgets(line, MAXLINE, Finflows.file); | |
| 464 | 1 | NumIfacePolluts = -1; | |
| 465 |
1/2✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
|
1 | if (sscanf(line, "%d", &NumIfacePolluts)) |
| 466 | 1 | NumIfacePolluts--; | |
| 467 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | if ( NumIfacePolluts < 0 ) return ERR_ROUTING_FILE_FORMAT; |
| 468 | |||
| 469 | // --- read flow units | ||
| 470 | 1 | fgets(line, MAXLINE, Finflows.file); | |
| 471 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | if (sscanf(line, "%s %s", s1, s2) < 2) |
| 472 | ✗ | return ERR_ROUTING_FILE_FORMAT; | |
| 473 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
|
1 | if ( !strcomp(s1, "FLOW") ) |
| 474 | ✗ | return ERR_ROUTING_FILE_FORMAT; | |
| 475 | 1 | IfaceFlowUnits = findmatch(s2, FlowUnitWords); | |
| 476 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | if ( IfaceFlowUnits < 0 ) |
| 477 | ✗ | return ERR_ROUTING_FILE_FORMAT; | |
| 478 | |||
| 479 | // --- allocate memory for pollutant index array | ||
| 480 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | if ( Nobjects[POLLUT] > 0 ) |
| 481 | { | ||
| 482 | ✗ | IfacePolluts = (int *) calloc(Nobjects[POLLUT], sizeof(int)); | |
| 483 | ✗ | if ( !IfacePolluts ) return ERR_MEMORY; | |
| 484 | ✗ | for (i=0; i<Nobjects[POLLUT]; i++) IfacePolluts[i] = -1; | |
| 485 | } | ||
| 486 | |||
| 487 | // --- read pollutant names & units | ||
| 488 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
1 | if ( NumIfacePolluts > 0 && Nobjects[POLLUT] > 0 ) |
| 489 | { | ||
| 490 | // --- check each pollutant name on file with project's pollutants | ||
| 491 | ✗ | for (i=0; i<NumIfacePolluts; i++) | |
| 492 | { | ||
| 493 | ✗ | if ( feof(Finflows.file) ) | |
| 494 | ✗ | return ERR_ROUTING_FILE_FORMAT; | |
| 495 | ✗ | fgets(line, MAXLINE, Finflows.file); | |
| 496 | ✗ | if ( sscanf(line, "%s %s", s1, s2) < 2 ) | |
| 497 | ✗ | return ERR_ROUTING_FILE_FORMAT; | |
| 498 | ✗ | j = project_findObject(POLLUT, s1); | |
| 499 | ✗ | if ( j < 0 ) continue; | |
| 500 | ✗ | if ( !strcomp(s2, QualUnitsWords[Pollut[j].units]) ) | |
| 501 | ✗ | return ERR_ROUTING_FILE_NOMATCH; | |
| 502 | ✗ | IfacePolluts[j] = i; | |
| 503 | } | ||
| 504 | } | ||
| 505 | 1 | return 0; | |
| 506 | } | ||
| 507 | |||
| 508 | //============================================================================= | ||
| 509 | |||
| 510 | 1 | int getIfaceFileNodes() | |
| 511 | // | ||
| 512 | // Input: none | ||
| 513 | // Output: returns an error code | ||
| 514 | // Purpose: reads names of nodes contained on inflows interface file. | ||
| 515 | // | ||
| 516 | { | ||
| 517 | int i; | ||
| 518 | char line[MAXLINE+1]; // line from inflows interface file | ||
| 519 | char s[MAXLINE+1]; // general string variable | ||
| 520 | |||
| 521 | // --- read number of interface nodes | ||
| 522 | 1 | fgets(line, MAXLINE, Finflows.file); | |
| 523 |
2/4✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
|
1 | if ( !sscanf(line, "%d", &NumIfaceNodes) || NumIfaceNodes <= 0 ) |
| 524 | ✗ | return ERR_ROUTING_FILE_FORMAT; | |
| 525 | |||
| 526 | // --- allocate memory for interface nodes index array | ||
| 527 | 1 | IfaceNodes = (int *) calloc(NumIfaceNodes, sizeof(int)); | |
| 528 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | if ( !IfaceNodes ) return ERR_MEMORY; |
| 529 | |||
| 530 | // --- read names of interface nodes from file & save their indexes | ||
| 531 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
|
2 | for ( i=0; i<NumIfaceNodes; i++ ) |
| 532 | { | ||
| 533 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
|
1 | if ( feof(Finflows.file) ) |
| 534 | ✗ | return ERR_ROUTING_FILE_FORMAT; | |
| 535 | 1 | IfaceNodes[i] = 0; | |
| 536 | 1 | fgets(line, MAXLINE, Finflows.file); | |
| 537 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | if (!sscanf(line, "%s", s)) |
| 538 | ✗ | return ERR_ROUTING_FILE_FORMAT; | |
| 539 | 1 | IfaceNodes[i] = project_findObject(NODE, s); | |
| 540 | } | ||
| 541 | |||
| 542 | // --- skip over column headings line | ||
| 543 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
|
1 | if ( feof(Finflows.file) ) return ERR_ROUTING_FILE_FORMAT; |
| 544 | 1 | fgets(line, MAXLINE, Finflows.file); | |
| 545 | 1 | return 0; | |
| 546 | } | ||
| 547 | |||
| 548 | //============================================================================= | ||
| 549 | |||
| 550 | 73 | void readNewIfaceValues() | |
| 551 | // | ||
| 552 | // Input: none | ||
| 553 | // Output: none | ||
| 554 | // Purpose: reads data from inflows interface file for next date. | ||
| 555 | // | ||
| 556 | { | ||
| 557 | int i, j; | ||
| 558 | char* s; | ||
| 559 | 73 | int yr = 0, mon = 0, day = 0, | |
| 560 | 73 | hr = 0, min = 0, sec = 0; // year, month, day, hour, minute, second | |
| 561 | char line[MAXLINE+1]; // line from interface file | ||
| 562 | |||
| 563 | // --- read a line for each interface node | ||
| 564 | 73 | NewIfaceDate = NO_DATE; | |
| 565 |
2/2✓ Branch 0 taken 73 times.
✓ Branch 1 taken 73 times.
|
146 | for (i=0; i<NumIfaceNodes; i++) |
| 566 | { | ||
| 567 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 73 times.
|
73 | if ( feof(Finflows.file) ) return; |
| 568 | 73 | fgets(line, MAXLINE, Finflows.file); | |
| 569 | |||
| 570 | // --- parse date & time from line | ||
| 571 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 73 times.
|
73 | if ( strtok(line, SEPSTR) == NULL ) return; |
| 572 | 73 | s = strtok(NULL, SEPSTR); | |
| 573 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
|
73 | if ( s == NULL ) return; |
| 574 | 73 | yr = atoi(s); | |
| 575 | 73 | s = strtok(NULL, SEPSTR); | |
| 576 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
|
73 | if ( s == NULL ) return; |
| 577 | 73 | mon = atoi(s); | |
| 578 | 73 | s = strtok(NULL, SEPSTR); | |
| 579 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
|
73 | if ( s == NULL ) return; |
| 580 | 73 | day = atoi(s); | |
| 581 | 73 | s = strtok(NULL, SEPSTR); | |
| 582 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
|
73 | if ( s == NULL ) return; |
| 583 | 73 | hr = atoi(s); | |
| 584 | 73 | s = strtok(NULL, SEPSTR); | |
| 585 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
|
73 | if ( s == NULL ) return; |
| 586 | 73 | min = atoi(s); | |
| 587 | 73 | s = strtok(NULL, SEPSTR); | |
| 588 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
|
73 | if ( s == NULL ) return; |
| 589 | 73 | sec = atoi(s); | |
| 590 | |||
| 591 | // --- parse flow value | ||
| 592 | 73 | s = strtok(NULL, SEPSTR); | |
| 593 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
|
73 | if ( s == NULL ) return; |
| 594 | 73 | NewIfaceValues[i][0] = atof(s) / Qcf[IfaceFlowUnits]; | |
| 595 | |||
| 596 | // --- parse pollutant values | ||
| 597 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
|
73 | for (j=1; j<=NumIfacePolluts; j++) |
| 598 | { | ||
| 599 | ✗ | s = strtok(NULL, SEPSTR); | |
| 600 | ✗ | if ( s == NULL ) return; | |
| 601 | ✗ | NewIfaceValues[i][j] = atof(s); | |
| 602 | } | ||
| 603 | |||
| 604 | } | ||
| 605 | |||
| 606 | // --- encode date & time values | ||
| 607 | 146 | NewIfaceDate = datetime_encodeDate(yr, mon, day) + | |
| 608 | 73 | datetime_encodeTime(hr, min, sec); | |
| 609 | } | ||
| 610 | |||
| 611 | //============================================================================= | ||
| 612 | |||
| 613 | 72 | void setOldIfaceValues() | |
| 614 | // | ||
| 615 | // Input: none | ||
| 616 | // Output: none | ||
| 617 | // Purpose: replaces old values read from routing interface file with new ones. | ||
| 618 | // | ||
| 619 | { | ||
| 620 | int i, j; | ||
| 621 | 72 | OldIfaceDate = NewIfaceDate; | |
| 622 |
2/2✓ Branch 0 taken 72 times.
✓ Branch 1 taken 72 times.
|
144 | for ( i=0; i<NumIfaceNodes; i++) |
| 623 | { | ||
| 624 |
2/2✓ Branch 0 taken 72 times.
✓ Branch 1 taken 72 times.
|
144 | for ( j=0; j<NumIfacePolluts+1; j++ ) |
| 625 | { | ||
| 626 | 72 | OldIfaceValues[i][j] = NewIfaceValues[i][j]; | |
| 627 | } | ||
| 628 | } | ||
| 629 | 72 | } | |
| 630 | |||
| 631 | //============================================================================= | ||
| 632 | |||
| 633 | 150 | int isOutletNode(int i) | |
| 634 | // | ||
| 635 | // Input: i = node index | ||
| 636 | // Output: returns 1 if node is an outlet, 0 if not. | ||
| 637 | // Purpose: determines if a node is an outlet point or not. | ||
| 638 | // | ||
| 639 | { | ||
| 640 | // --- for DW routing only outfalls are outlets | ||
| 641 |
1/2✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
|
150 | if ( RouteModel == DW ) |
| 642 | { | ||
| 643 | 150 | return (Node[i].type == OUTFALL); | |
| 644 | } | ||
| 645 | |||
| 646 | // --- otherwise outlets are nodes with no outflow links (degree is 0) | ||
| 647 | ✗ | else return (Node[i].degree == 0); | |
| 648 | } | ||
| 649 |