massbal.c
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | //----------------------------------------------------------------------------- | ||
| 2 | // massbal.c | ||
| 3 | // | ||
| 4 | // Project: EPA SWMM5 | ||
| 5 | // Version: 5.2 | ||
| 6 | // Date: 11/01/21 (Build 5.2.0) | ||
| 7 | // Author: L. Rossman | ||
| 8 | // M. Tryby (EPA) | ||
| 9 | // | ||
| 10 | // Mass balance functions | ||
| 11 | // | ||
| 12 | // Update History | ||
| 13 | // ============== | ||
| 14 | // Build 5.1.007: | ||
| 15 | // - Mass balances modified to to correctly handle negative external inflows. | ||
| 16 | // - Volume from minimum surface area at nodes included in mass balances. | ||
| 17 | // Build 5.1.008: | ||
| 18 | // - massbal_updateRunoffTotals() modified. | ||
| 19 | // - LID drain flows and returned outfall flows added to components of | ||
| 20 | // runoff mass balance. | ||
| 21 | // - Seepage pollutant loss added into mass balances. | ||
| 22 | // Build 5.1.010: | ||
| 23 | // - Remaining pollutant mass in "dry" elements now added to final storage. | ||
| 24 | // Build 5.1.011: | ||
| 25 | // - Final stored pollutant mass in links ignored for Steady Flow routing. | ||
| 26 | // Build 5.1.012: | ||
| 27 | // - Terminal storage nodes no longer treated as non-storage terminal | ||
| 28 | // nodes are when updating total outflow volume. | ||
| 29 | // Build 5.1.013: | ||
| 30 | // - Volume from MinSurfArea no longer included in initial & final storage. | ||
| 31 | //----------------------------------------------------------------------------- | ||
| 32 | #define _CRT_SECURE_NO_DEPRECATE | ||
| 33 | |||
| 34 | #include <string.h> | ||
| 35 | #include <stdlib.h> | ||
| 36 | #include <math.h> | ||
| 37 | #include "headers.h" | ||
| 38 | |||
| 39 | //----------------------------------------------------------------------------- | ||
| 40 | // Constants | ||
| 41 | //----------------------------------------------------------------------------- | ||
| 42 | static const double MAX_RUNOFF_BALANCE_ERR = 10.0; | ||
| 43 | static const double MAX_FLOW_BALANCE_ERR = 10.0; | ||
| 44 | |||
| 45 | //----------------------------------------------------------------------------- | ||
| 46 | // Shared variables | ||
| 47 | //----------------------------------------------------------------------------- | ||
| 48 | TRunoffTotals RunoffTotals; // overall surface runoff continuity totals | ||
| 49 | TLoadingTotals* LoadingTotals; // overall WQ washoff continuity totals | ||
| 50 | TGwaterTotals GwaterTotals; // overall groundwater continuity totals | ||
| 51 | TRoutingTotals FlowTotals; // overall routed flow continuity totals | ||
| 52 | TRoutingTotals* QualTotals; // overall routed WQ continuity totals | ||
| 53 | TRoutingTotals StepFlowTotals; // routed flow totals over time step | ||
| 54 | TRoutingTotals OldStepFlowTotals; | ||
| 55 | TRoutingTotals* StepQualTotals; // routed WQ totals over time step | ||
| 56 | |||
| 57 | //----------------------------------------------------------------------------- | ||
| 58 | // Exportable variables | ||
| 59 | //----------------------------------------------------------------------------- | ||
| 60 | double* NodeInflow; // total inflow volume to each node (ft3) | ||
| 61 | double* NodeOutflow; // total outflow volume from each node (ft3) | ||
| 62 | double TotalArea; // total drainage area (ft2) | ||
| 63 | |||
| 64 | //----------------------------------------------------------------------------- | ||
| 65 | // External functions (declared in funcs.h) | ||
| 66 | //----------------------------------------------------------------------------- | ||
| 67 | // massbal_open (called from swmm_start in swmm5.c) | ||
| 68 | // massbal_close (called from swmm_end in swmm5.c) | ||
| 69 | // massbal_report (called from swmm_end in swmm5.c) | ||
| 70 | // massbal_updateRunoffTotals (called from subcatch_getRunoff) | ||
| 71 | // massbal_updateDrainTotals (called from evalLidUnit in lid.c) | ||
| 72 | // massbal_updateLoadingTotals (called from subcatch_getBuildup) | ||
| 73 | // massbal_updateGwaterTotals (called from updateMassBal in gwater.c) | ||
| 74 | // massbal_updateRoutingTotals (called from routing_execute) | ||
| 75 | // massbal_initTimeStepTotals (called from routing_execute) | ||
| 76 | // massbal_addInflowFlow (called from routing.c) | ||
| 77 | // massbal_addInflowQual (called from routing.c) | ||
| 78 | // massbal_addOutflowFlow (called from removeOutflows in routing.c) | ||
| 79 | // massbal_addOutflowQual (called from removeOutflows in routing.c) | ||
| 80 | // massbal_addNodeLosses (called from removeStorageLosses in routing.c) | ||
| 81 | // massbal_addLinkLosses (called from removeConduitLosses in routing.c) | ||
| 82 | // massbal_addReactedMass (called from qualrout.c & treatmnt.c) | ||
| 83 | // massbal_addSeepageLoss (called from routing.c) | ||
| 84 | // massbal_addToFinalStorage (called from qualrout.c) | ||
| 85 | // massbal_getStepFlowError (called from routing.c) | ||
| 86 | |||
| 87 | //----------------------------------------------------------------------------- | ||
| 88 | // Local Functions | ||
| 89 | //----------------------------------------------------------------------------- | ||
| 90 | double massbal_getBuildup(int pollut); | ||
| 91 | double massbal_getStorage(char isFinalStorage); | ||
| 92 | double massbal_getStoredMass(int pollut); | ||
| 93 | double massbal_getLoadingError(void); | ||
| 94 | double massbal_getGwaterError(void); | ||
| 95 | double massbal_getQualError(void); | ||
| 96 | |||
| 97 | |||
| 98 | //============================================================================= | ||
| 99 | |||
| 100 | 58 | int massbal_open() | |
| 101 | // | ||
| 102 | // Input: none | ||
| 103 | // Output: returns error code | ||
| 104 | // Purpose: opens and initializes mass balance continuity checking. | ||
| 105 | // | ||
| 106 | { | ||
| 107 | int j, n; | ||
| 108 | |||
| 109 | // --- initialize global continuity errors | ||
| 110 | 58 | RunoffError = 0.0; | |
| 111 | 58 | GwaterError = 0.0; | |
| 112 | 58 | FlowError = 0.0; | |
| 113 | 58 | QualError = 0.0; | |
| 114 | |||
| 115 | // --- initialize runoff totals | ||
| 116 | 58 | RunoffTotals.rainfall = 0.0; | |
| 117 | 58 | RunoffTotals.evap = 0.0; | |
| 118 | 58 | RunoffTotals.infil = 0.0; | |
| 119 | 58 | RunoffTotals.runoff = 0.0; | |
| 120 | 58 | RunoffTotals.runon = 0.0; | |
| 121 | 58 | RunoffTotals.drains = 0.0; | |
| 122 | 58 | RunoffTotals.snowRemoved = 0.0; | |
| 123 | 58 | RunoffTotals.initStorage = 0.0; | |
| 124 | 58 | RunoffTotals.initSnowCover = 0.0; | |
| 125 | 58 | TotalArea = 0.0; | |
| 126 |
2/2✓ Branch 0 taken 2393 times.
✓ Branch 1 taken 58 times.
|
2451 | for (j = 0; j < Nobjects[SUBCATCH]; j++) |
| 127 | { | ||
| 128 | 2393 | RunoffTotals.initStorage += subcatch_getStorage(j); | |
| 129 | 2393 | RunoffTotals.initSnowCover += snow_getSnowCover(j); | |
| 130 | 2393 | TotalArea += Subcatch[j].area; | |
| 131 | } | ||
| 132 | |||
| 133 | // --- initialize groundwater totals | ||
| 134 | 58 | GwaterTotals.infil = 0.0; | |
| 135 | 58 | GwaterTotals.upperEvap = 0.0; | |
| 136 | 58 | GwaterTotals.lowerEvap = 0.0; | |
| 137 | 58 | GwaterTotals.lowerPerc = 0.0; | |
| 138 | 58 | GwaterTotals.gwater = 0.0; | |
| 139 | 58 | GwaterTotals.initStorage = 0.0; | |
| 140 | 58 | GwaterTotals.finalStorage = 0.0; | |
| 141 |
2/2✓ Branch 0 taken 2393 times.
✓ Branch 1 taken 58 times.
|
2451 | for ( j = 0; j < Nobjects[SUBCATCH]; j++ ) |
| 142 | { | ||
| 143 | 2393 | GwaterTotals.initStorage += gwater_getVolume(j) * Subcatch[j].area; | |
| 144 | } | ||
| 145 | |||
| 146 | // --- initialize node flow & storage totals | ||
| 147 | 58 | FlowTotals.dwInflow = 0.0; | |
| 148 | 58 | FlowTotals.wwInflow = 0.0; | |
| 149 | 58 | FlowTotals.gwInflow = 0.0; | |
| 150 | 58 | FlowTotals.iiInflow = 0.0; | |
| 151 | 58 | FlowTotals.exInflow = 0.0; | |
| 152 | 58 | FlowTotals.flooding = 0.0; | |
| 153 | 58 | FlowTotals.outflow = 0.0; | |
| 154 | 58 | FlowTotals.evapLoss = 0.0; | |
| 155 | 58 | FlowTotals.seepLoss = 0.0; | |
| 156 | 58 | FlowTotals.reacted = 0.0; | |
| 157 | 58 | FlowTotals.initStorage = 0.0; | |
| 158 |
2/2✓ Branch 0 taken 10183 times.
✓ Branch 1 taken 58 times.
|
10241 | for (j = 0; j < Nobjects[NODE]; j++) |
| 159 | 10183 | FlowTotals.initStorage += Node[j].newVolume; | |
| 160 |
2/2✓ Branch 0 taken 10508 times.
✓ Branch 1 taken 58 times.
|
10566 | for (j = 0; j < Nobjects[LINK]; j++) |
| 161 | 10508 | FlowTotals.initStorage += Link[j].newVolume; | |
| 162 | 58 | StepFlowTotals = FlowTotals; | |
| 163 | |||
| 164 | // --- initialize arrays to null | ||
| 165 | 58 | LoadingTotals = NULL; | |
| 166 | 58 | QualTotals = NULL; | |
| 167 | 58 | StepQualTotals = NULL; | |
| 168 | 58 | NodeInflow = NULL; | |
| 169 | 58 | NodeOutflow = NULL; | |
| 170 | |||
| 171 | // --- allocate memory for WQ washoff continuity totals | ||
| 172 | 58 | n = Nobjects[POLLUT]; | |
| 173 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 43 times.
|
58 | if ( n > 0 ) |
| 174 | { | ||
| 175 | 15 | LoadingTotals = (TLoadingTotals *) calloc(n, sizeof(TLoadingTotals)); | |
| 176 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | if ( LoadingTotals == NULL ) |
| 177 | { | ||
| 178 | ✗ | report_writeErrorMsg(ERR_MEMORY, ""); | |
| 179 | ✗ | return ErrorCode; | |
| 180 | } | ||
| 181 |
2/2✓ Branch 0 taken 47 times.
✓ Branch 1 taken 15 times.
|
62 | for (j = 0; j < n; j++) |
| 182 | { | ||
| 183 | 47 | LoadingTotals[j].initLoad = massbal_getBuildup(j); | |
| 184 | 47 | LoadingTotals[j].buildup = 0.0; | |
| 185 | 47 | LoadingTotals[j].deposition = 0.0; | |
| 186 | 47 | LoadingTotals[j].sweeping = 0.0; | |
| 187 | 47 | LoadingTotals[j].infil = 0.0; | |
| 188 | 47 | LoadingTotals[j].bmpRemoval = 0.0; | |
| 189 | 47 | LoadingTotals[j].runoff = 0.0; | |
| 190 | 47 | LoadingTotals[j].finalLoad = 0.0; | |
| 191 | } | ||
| 192 | } | ||
| 193 | |||
| 194 | // --- allocate memory for nodal WQ continuity totals | ||
| 195 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 43 times.
|
58 | if ( n > 0 ) |
| 196 | { | ||
| 197 | 15 | QualTotals = (TRoutingTotals *) calloc(n, sizeof(TRoutingTotals)); | |
| 198 | 15 | StepQualTotals = (TRoutingTotals *) calloc(n, sizeof(TRoutingTotals)); | |
| 199 |
2/4✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
|
15 | if ( QualTotals == NULL || StepQualTotals == NULL ) |
| 200 | { | ||
| 201 | ✗ | report_writeErrorMsg(ERR_MEMORY, ""); | |
| 202 | ✗ | return ErrorCode; | |
| 203 | } | ||
| 204 | } | ||
| 205 | |||
| 206 | // --- initialize WQ totals | ||
| 207 |
2/2✓ Branch 0 taken 47 times.
✓ Branch 1 taken 58 times.
|
105 | for (j = 0; j < n; j++) |
| 208 | { | ||
| 209 | 47 | QualTotals[j].dwInflow = 0.0; | |
| 210 | 47 | QualTotals[j].wwInflow = 0.0; | |
| 211 | 47 | QualTotals[j].gwInflow = 0.0; | |
| 212 | 47 | QualTotals[j].exInflow = 0.0; | |
| 213 | 47 | QualTotals[j].flooding = 0.0; | |
| 214 | 47 | QualTotals[j].outflow = 0.0; | |
| 215 | 47 | QualTotals[j].evapLoss = 0.0; | |
| 216 | 47 | QualTotals[j].seepLoss = 0.0; | |
| 217 | 47 | QualTotals[j].reacted = 0.0; | |
| 218 | 47 | QualTotals[j].initStorage = massbal_getStoredMass(j); | |
| 219 | } | ||
| 220 | |||
| 221 | // --- initialize totals used over a single time step | ||
| 222 | 58 | massbal_initTimeStepTotals(); | |
| 223 | |||
| 224 | // --- allocate memory for nodal flow continuity | ||
| 225 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | if ( Nobjects[NODE] > 0 ) |
| 226 | { | ||
| 227 | 58 | NodeInflow = (double *) calloc(Nobjects[NODE], sizeof(double)); | |
| 228 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
|
58 | if ( NodeInflow == NULL ) |
| 229 | { | ||
| 230 | ✗ | report_writeErrorMsg(ERR_MEMORY, ""); | |
| 231 | ✗ | return ErrorCode; | |
| 232 | } | ||
| 233 | 58 | NodeOutflow = (double *) calloc(Nobjects[NODE], sizeof(double)); | |
| 234 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
|
58 | if ( NodeOutflow == NULL ) |
| 235 | { | ||
| 236 | ✗ | report_writeErrorMsg(ERR_MEMORY, ""); | |
| 237 | ✗ | return ErrorCode; | |
| 238 | } | ||
| 239 |
2/2✓ Branch 0 taken 10183 times.
✓ Branch 1 taken 58 times.
|
10241 | for (j = 0; j < Nobjects[NODE]; j++) NodeInflow[j] = Node[j].newVolume; |
| 240 | } | ||
| 241 | 58 | return ErrorCode; | |
| 242 | } | ||
| 243 | |||
| 244 | //============================================================================= | ||
| 245 | |||
| 246 | 58 | void massbal_close() | |
| 247 | // | ||
| 248 | // Input: none | ||
| 249 | // Output: none | ||
| 250 | // Purpose: frees memory used by mass balance system. | ||
| 251 | // | ||
| 252 | { | ||
| 253 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 43 times.
|
58 | FREE(LoadingTotals); |
| 254 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 43 times.
|
58 | FREE(QualTotals); |
| 255 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 43 times.
|
58 | FREE(StepQualTotals); |
| 256 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | FREE(NodeInflow); |
| 257 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | FREE(NodeOutflow); |
| 258 | 58 | } | |
| 259 | |||
| 260 | //============================================================================= | ||
| 261 | |||
| 262 | 58 | void massbal_report() | |
| 263 | // | ||
| 264 | // Input: none | ||
| 265 | // Output: none | ||
| 266 | // Purpose: reports mass balance results. | ||
| 267 | // | ||
| 268 | { | ||
| 269 | int j; | ||
| 270 | 58 | double gwArea = 0.0; | |
| 271 | |||
| 272 |
2/2✓ Branch 0 taken 37 times.
✓ Branch 1 taken 21 times.
|
58 | if ( Nobjects[SUBCATCH] > 0 ) |
| 273 | { | ||
| 274 |
1/2✓ Branch 1 taken 37 times.
✗ Branch 2 not taken.
|
37 | if ( massbal_getRunoffError() > MAX_RUNOFF_BALANCE_ERR || |
| 275 |
1/2✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
|
37 | RptFlags.continuity == TRUE |
| 276 | 37 | ) report_writeRunoffError(&RunoffTotals, TotalArea); | |
| 277 | |||
| 278 |
3/4✓ Branch 0 taken 14 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
|
37 | if ( Nobjects[POLLUT] > 0 && !IgnoreQuality ) |
| 279 | { | ||
| 280 |
2/2✓ Branch 1 taken 12 times.
✓ Branch 2 taken 2 times.
|
14 | if ( massbal_getLoadingError() > MAX_RUNOFF_BALANCE_ERR || |
| 281 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | RptFlags.continuity == TRUE |
| 282 | 14 | ) report_writeLoadingError(LoadingTotals); | |
| 283 | } | ||
| 284 | } | ||
| 285 | |||
| 286 |
3/4✓ Branch 0 taken 9 times.
✓ Branch 1 taken 49 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
58 | if ( Nobjects[AQUIFER] > 0 && !IgnoreGwater ) |
| 287 | { | ||
| 288 |
2/2✓ Branch 1 taken 8 times.
✓ Branch 2 taken 1 time.
|
9 | if ( massbal_getGwaterError() > MAX_RUNOFF_BALANCE_ERR || |
| 289 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | RptFlags.continuity == TRUE ) |
| 290 | { | ||
| 291 |
2/2✓ Branch 0 taken 2311 times.
✓ Branch 1 taken 9 times.
|
2320 | for ( j = 0; j < Nobjects[SUBCATCH]; j++ ) |
| 292 | { | ||
| 293 |
2/2✓ Branch 0 taken 2241 times.
✓ Branch 1 taken 70 times.
|
2311 | if ( Subcatch[j].groundwater ) gwArea += Subcatch[j].area; |
| 294 | } | ||
| 295 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | if ( gwArea > 0.0 ) report_writeGwaterError(&GwaterTotals, gwArea); |
| 296 | } | ||
| 297 | } | ||
| 298 | |||
| 299 |
2/4✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
✗ Branch 3 not taken.
|
58 | if ( Nobjects[NODE] > 0 && !IgnoreRouting ) |
| 300 | { | ||
| 301 |
2/2✓ Branch 1 taken 57 times.
✓ Branch 2 taken 1 time.
|
58 | if ( massbal_getFlowError() > MAX_FLOW_BALANCE_ERR || |
| 302 |
1/2✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
|
57 | RptFlags.continuity == TRUE |
| 303 | 58 | ) report_writeFlowError(&FlowTotals); | |
| 304 | |||
| 305 |
3/4✓ Branch 0 taken 15 times.
✓ Branch 1 taken 43 times.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
|
58 | if ( Nobjects[POLLUT] > 0 && !IgnoreQuality ) |
| 306 | { | ||
| 307 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | if ( massbal_getQualError() > MAX_FLOW_BALANCE_ERR || |
| 308 |
1/2✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
|
15 | RptFlags.continuity == TRUE |
| 309 | 15 | ) report_writeQualError(QualTotals); | |
| 310 | } | ||
| 311 | } | ||
| 312 | 58 | } | |
| 313 | |||
| 314 | //============================================================================= | ||
| 315 | |||
| 316 | 93 | double massbal_getBuildup(int p) | |
| 317 | // | ||
| 318 | // Input: p = pollutant index | ||
| 319 | // Output: returns total pollutant buildup (lbs or kg) | ||
| 320 | // Purpose: computes current total buildup of a pollutant over study area. | ||
| 321 | // | ||
| 322 | { | ||
| 323 | int i, j; | ||
| 324 | 93 | double load = 0.0; | |
| 325 | |||
| 326 |
2/2✓ Branch 0 taken 18588 times.
✓ Branch 1 taken 93 times.
|
18681 | for (j = 0; j < Nobjects[SUBCATCH]; j++) |
| 327 | { | ||
| 328 |
2/2✓ Branch 0 taken 248 times.
✓ Branch 1 taken 18588 times.
|
18836 | for (i = 0; i < Nobjects[LANDUSE]; i++) |
| 329 | { | ||
| 330 | 248 | load += Subcatch[j].landFactor[i].buildup[p]; | |
| 331 | } | ||
| 332 | 18588 | load += Subcatch[j].pondedQual[p] * Pollut[p].mcf; | |
| 333 | } | ||
| 334 | 93 | return load; | |
| 335 | } | ||
| 336 | |||
| 337 | //============================================================================= | ||
| 338 | |||
| 339 | 12927343 | void massbal_updateRunoffTotals(int flowType, double v) | |
| 340 | // | ||
| 341 | // Input: flowType = type of flow | ||
| 342 | // v = flow volume (ft3) | ||
| 343 | // Output: none | ||
| 344 | // Purpose: updates runoff totals after current time step. | ||
| 345 | // | ||
| 346 | { | ||
| 347 |
6/7✓ Branch 0 taken 3229694 times.
✓ Branch 1 taken 3229694 times.
✓ Branch 2 taken 3229694 times.
✓ Branch 3 taken 3229694 times.
✓ Branch 4 taken 8328 times.
✓ Branch 5 taken 239 times.
✗ Branch 6 not taken.
|
12927343 | switch(flowType) |
| 348 | { | ||
| 349 | 3229694 | case RUNOFF_RAINFALL: RunoffTotals.rainfall += v; break; | |
| 350 | 3229694 | case RUNOFF_EVAP: RunoffTotals.evap += v; break; | |
| 351 | 3229694 | case RUNOFF_INFIL: RunoffTotals.infil += v; break; | |
| 352 | 3229694 | case RUNOFF_RUNOFF: RunoffTotals.runoff += v; break; | |
| 353 | 8328 | case RUNOFF_DRAINS: RunoffTotals.drains += v; break; | |
| 354 | 239 | case RUNOFF_RUNON: RunoffTotals.runon += v; break; | |
| 355 | } | ||
| 356 | 12927343 | } | |
| 357 | |||
| 358 | //============================================================================= | ||
| 359 | |||
| 360 | 3033546 | void massbal_updateGwaterTotals(double vInfil, double vUpperEvap, double vLowerEvap, | |
| 361 | double vLowerPerc, double vGwater) | ||
| 362 | // | ||
| 363 | // Input: vInfil = volume depth of infiltrated water (ft) | ||
| 364 | // vUpperEvap = volume depth of upper evaporation (ft) | ||
| 365 | // vLowerEvap = volume depth of lower evaporation (ft) | ||
| 366 | // vLowerPerc = volume depth of percolation to deep GW (ft) | ||
| 367 | // vGwater = volume depth of groundwater outflow (ft) | ||
| 368 | // Output: none | ||
| 369 | // Purpose: updates groundwater totals after current time step. | ||
| 370 | // | ||
| 371 | { | ||
| 372 | 3033546 | GwaterTotals.infil += vInfil; | |
| 373 | 3033546 | GwaterTotals.upperEvap += vUpperEvap; | |
| 374 | 3033546 | GwaterTotals.lowerEvap += vLowerEvap; | |
| 375 | 3033546 | GwaterTotals.lowerPerc += vLowerPerc; | |
| 376 | 3033546 | GwaterTotals.gwater += vGwater; | |
| 377 | 3033546 | } | |
| 378 | |||
| 379 | //============================================================================= | ||
| 380 | |||
| 381 | 1066479 | void massbal_initTimeStepTotals() | |
| 382 | // | ||
| 383 | // Input: none | ||
| 384 | // Output: none | ||
| 385 | // Purpose: initializes routing totals for current time step. | ||
| 386 | // | ||
| 387 | { | ||
| 388 | int j; | ||
| 389 | 1066479 | OldStepFlowTotals = StepFlowTotals; | |
| 390 | 1066479 | StepFlowTotals.dwInflow = 0.0; | |
| 391 | 1066479 | StepFlowTotals.wwInflow = 0.0; | |
| 392 | 1066479 | StepFlowTotals.gwInflow = 0.0; | |
| 393 | 1066479 | StepFlowTotals.iiInflow = 0.0; | |
| 394 | 1066479 | StepFlowTotals.exInflow = 0.0; | |
| 395 | 1066479 | StepFlowTotals.flooding = 0.0; | |
| 396 | 1066479 | StepFlowTotals.outflow = 0.0; | |
| 397 | 1066479 | StepFlowTotals.evapLoss = 0.0; | |
| 398 | 1066479 | StepFlowTotals.seepLoss = 0.0; | |
| 399 | 1066479 | StepFlowTotals.reacted = 0.0; | |
| 400 |
2/2✓ Branch 0 taken 493992 times.
✓ Branch 1 taken 1066479 times.
|
1560471 | for (j=0; j<Nobjects[POLLUT]; j++) |
| 401 | { | ||
| 402 | 493992 | StepQualTotals[j].dwInflow = 0.0; | |
| 403 | 493992 | StepQualTotals[j].wwInflow = 0.0; | |
| 404 | 493992 | StepQualTotals[j].gwInflow = 0.0; | |
| 405 | 493992 | StepQualTotals[j].iiInflow = 0.0; | |
| 406 | 493992 | StepQualTotals[j].exInflow = 0.0; | |
| 407 | 493992 | StepQualTotals[j].flooding = 0.0; | |
| 408 | 493992 | StepQualTotals[j].outflow = 0.0; | |
| 409 | 493992 | StepQualTotals[j].reacted = 0.0; | |
| 410 | 493992 | StepQualTotals[j].seepLoss = 0.0; | |
| 411 | 493992 | StepQualTotals[j].initStorage = 0.0; | |
| 412 | 493992 | StepQualTotals[j].finalStorage = 0.0; | |
| 413 | } | ||
| 414 | 1066479 | } | |
| 415 | |||
| 416 | //============================================================================= | ||
| 417 | |||
| 418 | 98205616 | void massbal_addInflowFlow(int type, double q) | |
| 419 | // | ||
| 420 | // Input: type = type of inflow | ||
| 421 | // q = inflow rate (cfs) | ||
| 422 | // Output: none | ||
| 423 | // Purpose: adds flow inflow to routing totals for current time step. | ||
| 424 | // | ||
| 425 | { | ||
| 426 |
5/6✓ Branch 0 taken 17016863 times.
✓ Branch 1 taken 2170922 times.
✓ Branch 2 taken 170131 times.
✓ Branch 3 taken 3748360 times.
✓ Branch 4 taken 75099340 times.
✗ Branch 5 not taken.
|
98205616 | switch (type) |
| 427 | { | ||
| 428 | 17016863 | case DRY_WEATHER_INFLOW: StepFlowTotals.dwInflow += q; break; | |
| 429 | 2170922 | case WET_WEATHER_INFLOW: StepFlowTotals.wwInflow += q; break; | |
| 430 | 170131 | case GROUNDWATER_INFLOW: StepFlowTotals.gwInflow += q; break; | |
| 431 | 3748360 | case RDII_INFLOW: StepFlowTotals.iiInflow += q; break; | |
| 432 | 75099340 | case EXTERNAL_INFLOW: StepFlowTotals.exInflow += q; break; | |
| 433 | } | ||
| 434 | 98205616 | } | |
| 435 | |||
| 436 | //============================================================================= | ||
| 437 | |||
| 438 | 46886995 | void massbal_updateLoadingTotals(int type, int p, double w) | |
| 439 | // | ||
| 440 | // Input: type = type of inflow | ||
| 441 | // p = pollutant index | ||
| 442 | // w = mass loading | ||
| 443 | // Output: none | ||
| 444 | // Purpose: adds inflow mass loading to loading totals for current time step. | ||
| 445 | // | ||
| 446 | { | ||
| 447 |
6/8✓ Branch 0 taken 190668 times.
✓ Branch 1 taken 12617026 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8844804 times.
✓ Branch 4 taken 8845825 times.
✓ Branch 5 taken 12617026 times.
✓ Branch 6 taken 3771646 times.
✗ Branch 7 not taken.
|
46886995 | switch (type) |
| 448 | { | ||
| 449 | 190668 | case BUILDUP_LOAD: LoadingTotals[p].buildup += w; break; | |
| 450 | 12617026 | case DEPOSITION_LOAD: LoadingTotals[p].deposition += w; break; | |
| 451 | ✗ | case SWEEPING_LOAD: LoadingTotals[p].sweeping += w; break; | |
| 452 | 8844804 | case INFIL_LOAD: LoadingTotals[p].infil += w; break; | |
| 453 | 8845825 | case BMP_REMOVAL_LOAD: LoadingTotals[p].bmpRemoval += w; break; | |
| 454 | 12617026 | case RUNOFF_LOAD: LoadingTotals[p].runoff += w; break; | |
| 455 | 3771646 | case FINAL_LOAD: LoadingTotals[p].finalLoad += w; break; | |
| 456 | } | ||
| 457 | 46886995 | } | |
| 458 | |||
| 459 | //============================================================================= | ||
| 460 | |||
| 461 | 4018169 | void massbal_addInflowQual(int type, int p, double w) | |
| 462 | // | ||
| 463 | // Input: type = type of inflow | ||
| 464 | // p = pollutant index | ||
| 465 | // w = mass flow rate (mass/sec) | ||
| 466 | // Output: none | ||
| 467 | // Purpose: adds quality inflow to routing totals for current time step. | ||
| 468 | // | ||
| 469 | { | ||
| 470 |
2/4✓ Branch 0 taken 4018169 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4018169 times.
|
4018169 | if ( p < 0 || p >= Nobjects[POLLUT] ) return; |
| 471 |
4/6✓ Branch 0 taken 61612 times.
✓ Branch 1 taken 3400084 times.
✓ Branch 2 taken 533408 times.
✓ Branch 3 taken 23065 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
4018169 | switch (type) |
| 472 | { | ||
| 473 | 61612 | case DRY_WEATHER_INFLOW: StepQualTotals[p].dwInflow += w; break; | |
| 474 | 3400084 | case WET_WEATHER_INFLOW: StepQualTotals[p].wwInflow += w; break; | |
| 475 | 533408 | case GROUNDWATER_INFLOW: StepQualTotals[p].gwInflow += w; break; | |
| 476 | 23065 | case EXTERNAL_INFLOW: StepQualTotals[p].exInflow += w; break; | |
| 477 | ✗ | case RDII_INFLOW: StepQualTotals[p].iiInflow += w; break; | |
| 478 | } | ||
| 479 | } | ||
| 480 | |||
| 481 | //============================================================================= | ||
| 482 | |||
| 483 | 693070 | void massbal_addOutflowFlow(double q, int isFlooded) | |
| 484 | // | ||
| 485 | // Input: q = outflow flow rate (cfs) | ||
| 486 | // isFlooded = TRUE if outflow represents internal flooding | ||
| 487 | // Output: none | ||
| 488 | // Purpose: adds flow outflow over current time step to routing totals. | ||
| 489 | // | ||
| 490 | { | ||
| 491 |
2/2✓ Branch 0 taken 37764 times.
✓ Branch 1 taken 655306 times.
|
693070 | if ( isFlooded ) StepFlowTotals.flooding += q; |
| 492 | 655306 | else StepFlowTotals.outflow += q; | |
| 493 | 693070 | } | |
| 494 | |||
| 495 | //============================================================================= | ||
| 496 | |||
| 497 | 401304 | void massbal_addOutflowQual(int p, double w, int isFlooded) | |
| 498 | // | ||
| 499 | // Input: p = pollutant index | ||
| 500 | // w = mass outflow rate (mass/sec) | ||
| 501 | // isFlooded = TRUE if outflow represents internal flooding | ||
| 502 | // Output: none | ||
| 503 | // Purpose: adds pollutant outflow over current time step to routing totals. | ||
| 504 | // | ||
| 505 | { | ||
| 506 |
2/4✓ Branch 0 taken 401304 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 401304 times.
|
401304 | if ( p < 0 || p >= Nobjects[POLLUT] ) return; |
| 507 |
1/2✓ Branch 0 taken 401304 times.
✗ Branch 1 not taken.
|
401304 | if ( w >= 0.0 ) |
| 508 | { | ||
| 509 |
2/2✓ Branch 0 taken 6104 times.
✓ Branch 1 taken 395200 times.
|
401304 | if ( isFlooded ) StepQualTotals[p].flooding += w; |
| 510 | 395200 | else StepQualTotals[p].outflow += w; | |
| 511 | } | ||
| 512 | ✗ | else StepQualTotals[p].exInflow -= w; | |
| 513 | } | ||
| 514 | |||
| 515 | //============================================================================= | ||
| 516 | |||
| 517 | 126971 | void massbal_addReactedMass(int p, double w) | |
| 518 | // | ||
| 519 | // Input: p = pollutant index | ||
| 520 | // w = rate of mass reacted (mass/sec) | ||
| 521 | // Output: none | ||
| 522 | // Purpose: adds mass reacted during current time step to routing totals. | ||
| 523 | // | ||
| 524 | { | ||
| 525 |
2/4✓ Branch 0 taken 126971 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 126971 times.
|
126971 | if ( p < 0 || p >= Nobjects[POLLUT] ) return; |
| 526 | 126971 | StepQualTotals[p].reacted += w; | |
| 527 | } | ||
| 528 | |||
| 529 | //============================================================================= | ||
| 530 | |||
| 531 | 6086608 | void massbal_addSeepageLoss(int p, double w) | |
| 532 | // | ||
| 533 | // Input: p = pollutant index | ||
| 534 | // w = mass seepage rate (mass/sec) | ||
| 535 | // Output: none | ||
| 536 | // Purpose: adds mass lost to seepage during current time step to routing totals. | ||
| 537 | // | ||
| 538 | { | ||
| 539 |
2/4✓ Branch 0 taken 6086608 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6086608 times.
|
6086608 | if ( p < 0 || p >= Nobjects[POLLUT] ) return; |
| 540 | 6086608 | StepQualTotals[p].seepLoss += w; | |
| 541 | } | ||
| 542 | |||
| 543 | //============================================================================= | ||
| 544 | |||
| 545 | 1858976 | void massbal_addToFinalStorage(int p, double w) | |
| 546 | // | ||
| 547 | // Input: p = pollutant index | ||
| 548 | // w = pollutant mass | ||
| 549 | // Output: none | ||
| 550 | // Purpose: adds mass remaining on dry surface to routing totals. | ||
| 551 | // | ||
| 552 | { | ||
| 553 |
2/4✓ Branch 0 taken 1858976 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1858976 times.
|
1858976 | if ( p < 0 || p >= Nobjects[POLLUT] ) return; |
| 554 | 1858976 | StepQualTotals[p].finalStorage += w; | |
| 555 | } | ||
| 556 | |||
| 557 | //============================================================================= | ||
| 558 | |||
| 559 | 1030493 | void massbal_addNodeLosses(double evapLoss, double seepLoss) | |
| 560 | // | ||
| 561 | // Input: evapLoss = evaporation loss from all nodes (ft3/sec) | ||
| 562 | // seepLoss = seepage loss from all nodes (ft3/sec) | ||
| 563 | // Output: none | ||
| 564 | // Purpose: adds node losses over current time step to routing totals. | ||
| 565 | // | ||
| 566 | { | ||
| 567 | 1030493 | StepFlowTotals.evapLoss += evapLoss; | |
| 568 | 1030493 | StepFlowTotals.seepLoss += seepLoss; | |
| 569 | 1030493 | } | |
| 570 | |||
| 571 | //============================================================================= | ||
| 572 | |||
| 573 | 1030493 | void massbal_addLinkLosses(double evapLoss, double seepLoss) | |
| 574 | // | ||
| 575 | // Input: evapLoss = evaporation loss from all links (ft3/sec) | ||
| 576 | // infilLoss = infiltration loss from all links (ft3/sec) | ||
| 577 | // Output: none | ||
| 578 | // Purpose: adds link losses over current time step to routing totals. | ||
| 579 | // | ||
| 580 | { | ||
| 581 | 1030493 | StepFlowTotals.evapLoss += evapLoss; | |
| 582 | 1030493 | StepFlowTotals.seepLoss += seepLoss; | |
| 583 | 1030493 | } | |
| 584 | |||
| 585 | //============================================================================= | ||
| 586 | |||
| 587 | 2132842 | void massbal_updateRoutingTotals(double tStep) | |
| 588 | // | ||
| 589 | // Input: tStep = time step (sec) | ||
| 590 | // Output: none | ||
| 591 | // Purpose: updates overall routing totals with totals from current time step. | ||
| 592 | // | ||
| 593 | { | ||
| 594 | int j; | ||
| 595 | 2132842 | FlowTotals.dwInflow += StepFlowTotals.dwInflow * tStep; | |
| 596 | 2132842 | FlowTotals.wwInflow += StepFlowTotals.wwInflow * tStep; | |
| 597 | 2132842 | FlowTotals.gwInflow += StepFlowTotals.gwInflow * tStep; | |
| 598 | 2132842 | FlowTotals.iiInflow += StepFlowTotals.iiInflow * tStep; | |
| 599 | 2132842 | FlowTotals.exInflow += StepFlowTotals.exInflow * tStep; | |
| 600 | 2132842 | FlowTotals.flooding += StepFlowTotals.flooding * tStep; | |
| 601 | 2132842 | FlowTotals.outflow += StepFlowTotals.outflow * tStep; | |
| 602 | 2132842 | FlowTotals.evapLoss += StepFlowTotals.evapLoss * tStep; | |
| 603 | 2132842 | FlowTotals.seepLoss += StepFlowTotals.seepLoss * tStep; | |
| 604 | |||
| 605 |
2/2✓ Branch 0 taken 987890 times.
✓ Branch 1 taken 2132842 times.
|
3120732 | for (j = 0; j < Nobjects[POLLUT]; j++) |
| 606 | { | ||
| 607 | 987890 | QualTotals[j].dwInflow += StepQualTotals[j].dwInflow * tStep; | |
| 608 | 987890 | QualTotals[j].wwInflow += StepQualTotals[j].wwInflow * tStep; | |
| 609 | 987890 | QualTotals[j].gwInflow += StepQualTotals[j].gwInflow * tStep; | |
| 610 | 987890 | QualTotals[j].iiInflow += StepQualTotals[j].iiInflow * tStep; | |
| 611 | 987890 | QualTotals[j].exInflow += StepQualTotals[j].exInflow * tStep; | |
| 612 | 987890 | QualTotals[j].flooding += StepQualTotals[j].flooding * tStep; | |
| 613 | 987890 | QualTotals[j].outflow += StepQualTotals[j].outflow * tStep; | |
| 614 | 987890 | QualTotals[j].reacted += StepQualTotals[j].reacted * tStep; | |
| 615 | 987890 | QualTotals[j].seepLoss += StepQualTotals[j].seepLoss * tStep; | |
| 616 | 987890 | QualTotals[j].finalStorage += StepQualTotals[j].finalStorage; | |
| 617 | } | ||
| 618 | |||
| 619 |
2/2✓ Branch 0 taken 111864678 times.
✓ Branch 1 taken 2132842 times.
|
113997520 | for (j = 0; j < Nobjects[NODE]; j++) |
| 620 | { | ||
| 621 | 111864678 | NodeInflow[j] += Node[j].inflow * tStep; | |
| 622 |
2/2✓ Branch 0 taken 107813834 times.
✓ Branch 1 taken 4050844 times.
|
111864678 | if (Node[j].type == OUTFALL || |
| 623 |
3/4✓ Branch 0 taken 1009206 times.
✓ Branch 1 taken 106804628 times.
✓ Branch 2 taken 1009206 times.
✗ Branch 3 not taken.
|
107813834 | (Node[j].degree == 0 && Node[j].type != STORAGE)) |
| 624 | { | ||
| 625 | 5060050 | NodeOutflow[j] += Node[j].inflow * tStep; | |
| 626 | } | ||
| 627 | else | ||
| 628 | { | ||
| 629 | 106804628 | NodeOutflow[j] += Node[j].outflow * tStep; | |
| 630 |
2/2✓ Branch 0 taken 106628082 times.
✓ Branch 1 taken 176546 times.
|
106804628 | if (Node[j].newVolume <= Node[j].fullVolume) |
| 631 | 106628082 | NodeOutflow[j] += Node[j].overflow * tStep; | |
| 632 | } | ||
| 633 | } | ||
| 634 | 2132842 | } | |
| 635 | |||
| 636 | //============================================================================= | ||
| 637 | |||
| 638 | 58 | double massbal_getStorage(char isFinalStorage) | |
| 639 | // | ||
| 640 | // Input: isFinalStorage = TRUE if at final time period | ||
| 641 | // Output: returns storage volume used (ft3) | ||
| 642 | // Purpose: computes total system storage (nodes + links) filled | ||
| 643 | // | ||
| 644 | { | ||
| 645 | int j; | ||
| 646 | 58 | double totalStorage = 0.0; | |
| 647 | double nodeStorage; | ||
| 648 | |||
| 649 | // --- get volume in nodes | ||
| 650 |
2/2✓ Branch 0 taken 10183 times.
✓ Branch 1 taken 58 times.
|
10241 | for (j = 0; j < Nobjects[NODE]; j++) |
| 651 | { | ||
| 652 | 10183 | nodeStorage = Node[j].newVolume; | |
| 653 |
1/2✓ Branch 0 taken 10183 times.
✗ Branch 1 not taken.
|
10183 | if ( isFinalStorage ) NodeOutflow[j] += nodeStorage; |
| 654 | 10183 | totalStorage += nodeStorage; | |
| 655 | } | ||
| 656 | |||
| 657 | // --- skip final link storage for Steady Flow routing | ||
| 658 |
3/4✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 57 times.
|
58 | if ( isFinalStorage && RouteModel == SF ) return totalStorage; |
| 659 | |||
| 660 | // --- add on volume stored in links | ||
| 661 |
2/2✓ Branch 0 taken 10487 times.
✓ Branch 1 taken 57 times.
|
10544 | for (j = 0; j < Nobjects[LINK]; j++) |
| 662 | { | ||
| 663 | 10487 | totalStorage += Link[j].newVolume; | |
| 664 | } | ||
| 665 | 57 | return totalStorage; | |
| 666 | } | ||
| 667 | |||
| 668 | //============================================================================= | ||
| 669 | |||
| 670 | ✗ | void massbal_getSysFlows(double f, double sysFlows[]) | |
| 671 | // | ||
| 672 | // Input: f = time weighting factor | ||
| 673 | // Output: sysFlows = array of total system flows | ||
| 674 | // Purpose: retrieves time-weighted average of old and new system flows. | ||
| 675 | // | ||
| 676 | { | ||
| 677 | ✗ | double f1 = 1.0 - f; | |
| 678 | ✗ | sysFlows[SYS_DWFLOW] = (f1 * OldStepFlowTotals.dwInflow + | |
| 679 | ✗ | f * StepFlowTotals.dwInflow) * UCF(FLOW); | |
| 680 | ✗ | sysFlows[SYS_GWFLOW] = (f1 * OldStepFlowTotals.gwInflow + | |
| 681 | ✗ | f * StepFlowTotals.gwInflow) * UCF(FLOW); | |
| 682 | ✗ | sysFlows[SYS_IIFLOW] = (f1 * OldStepFlowTotals.iiInflow + | |
| 683 | ✗ | f * StepFlowTotals.iiInflow) * UCF(FLOW); | |
| 684 | ✗ | sysFlows[SYS_EXFLOW] = (f1 * OldStepFlowTotals.exInflow + | |
| 685 | ✗ | f * StepFlowTotals.exInflow) * UCF(FLOW); | |
| 686 | ✗ | sysFlows[SYS_FLOODING] = (f1 * OldStepFlowTotals.flooding + | |
| 687 | ✗ | f * StepFlowTotals.flooding) * UCF(FLOW); | |
| 688 | ✗ | sysFlows[SYS_OUTFLOW] = (f1 * OldStepFlowTotals.outflow + | |
| 689 | ✗ | f * StepFlowTotals.outflow) * UCF(FLOW); | |
| 690 | ✗ | sysFlows[SYS_STORAGE] = (f1 * OldStepFlowTotals.finalStorage + | |
| 691 | ✗ | f * StepFlowTotals.finalStorage) * UCF(VOLUME); | |
| 692 | ✗ | } | |
| 693 | |||
| 694 | //============================================================================= | ||
| 695 | |||
| 696 | 37 | double massbal_getRunoffError() | |
| 697 | // | ||
| 698 | // Input: none | ||
| 699 | // Output: none | ||
| 700 | // Purpose: computes runoff mass balance error. | ||
| 701 | // | ||
| 702 | { | ||
| 703 | int j; | ||
| 704 | double totalInflow; | ||
| 705 | double totalOutflow; | ||
| 706 | |||
| 707 | // --- find final storage on all subcatchments | ||
| 708 | 37 | RunoffTotals.finalStorage = 0.0; | |
| 709 | 37 | RunoffTotals.finalSnowCover = 0.0; | |
| 710 |
2/2✓ Branch 0 taken 2393 times.
✓ Branch 1 taken 37 times.
|
2430 | for (j = 0; j < Nobjects[SUBCATCH]; j++) |
| 711 | { | ||
| 712 | 2393 | RunoffTotals.finalStorage += subcatch_getStorage(j); | |
| 713 | 2393 | RunoffTotals.finalSnowCover += snow_getSnowCover(j); | |
| 714 | } | ||
| 715 | |||
| 716 | // --- get snow removed from system | ||
| 717 | 37 | RunoffTotals.snowRemoved = Snow.removed; | |
| 718 | |||
| 719 | // --- compute % difference between total inflow and outflow | ||
| 720 | 37 | totalInflow = RunoffTotals.rainfall + | |
| 721 | 37 | RunoffTotals.runon + | |
| 722 | 37 | RunoffTotals.initStorage + | |
| 723 | 37 | RunoffTotals.initSnowCover; | |
| 724 | 37 | totalOutflow = RunoffTotals.evap + | |
| 725 | 37 | RunoffTotals.infil + | |
| 726 | 37 | RunoffTotals.runoff + | |
| 727 | 37 | RunoffTotals.drains + | |
| 728 | 37 | RunoffTotals.snowRemoved + | |
| 729 | 37 | RunoffTotals.finalStorage + | |
| 730 | 37 | RunoffTotals.finalSnowCover; | |
| 731 | 37 | RunoffTotals.pctError = 0.0; | |
| 732 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 35 times.
|
37 | if ( fabs(totalInflow - totalOutflow) < 1.0 ) |
| 733 | { | ||
| 734 | 2 | RunoffTotals.pctError = TINY; | |
| 735 | } | ||
| 736 |
1/2✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
|
35 | else if ( totalInflow > 0.0 ) |
| 737 | { | ||
| 738 | 35 | RunoffTotals.pctError = 100.0 * (1.0 - totalOutflow / totalInflow); | |
| 739 | } | ||
| 740 | ✗ | else if ( totalOutflow > 0.0 ) | |
| 741 | { | ||
| 742 | ✗ | RunoffTotals.pctError = 100.0 * (totalInflow / totalOutflow - 1.0); | |
| 743 | } | ||
| 744 | 37 | RunoffError = RunoffTotals.pctError; | |
| 745 | 37 | return RunoffTotals.pctError; | |
| 746 | } | ||
| 747 | |||
| 748 | //============================================================================= | ||
| 749 | |||
| 750 | 14 | double massbal_getLoadingError() | |
| 751 | // | ||
| 752 | // Input: none | ||
| 753 | // Output: none | ||
| 754 | // Purpose: computes runoff load mass balance error. | ||
| 755 | // | ||
| 756 | { | ||
| 757 | int j; | ||
| 758 | double loadIn; | ||
| 759 | double loadOut; | ||
| 760 | 14 | double maxError = 0.0; | |
| 761 | |||
| 762 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 14 times.
|
60 | for (j = 0; j < Nobjects[POLLUT]; j++) |
| 763 | { | ||
| 764 | // --- get final pollutant loading remaining on land surface | ||
| 765 | 46 | LoadingTotals[j].finalLoad += massbal_getBuildup(j); | |
| 766 | |||
| 767 | // --- compute total load added to study area | ||
| 768 | 46 | loadIn = LoadingTotals[j].initLoad + | |
| 769 | 46 | LoadingTotals[j].buildup + | |
| 770 | 46 | LoadingTotals[j].deposition; | |
| 771 | |||
| 772 | // --- compute total load removed from study area | ||
| 773 | 46 | loadOut = LoadingTotals[j].sweeping + | |
| 774 | 46 | LoadingTotals[j].infil + | |
| 775 | 46 | LoadingTotals[j].bmpRemoval + | |
| 776 | 46 | LoadingTotals[j].runoff + | |
| 777 | 46 | LoadingTotals[j].finalLoad; | |
| 778 | |||
| 779 | // --- compute mass balance error | ||
| 780 | 46 | LoadingTotals[j].pctError = 0.0; | |
| 781 |
2/2✓ Branch 0 taken 30 times.
✓ Branch 1 taken 16 times.
|
46 | if ( fabs(loadIn - loadOut) < 0.001 ) |
| 782 | { | ||
| 783 | 30 | LoadingTotals[j].pctError = TINY; | |
| 784 | } | ||
| 785 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | else if ( loadIn > 0.0 ) |
| 786 | { | ||
| 787 | 16 | LoadingTotals[j].pctError = 100.0 * (1.0 - loadOut / loadIn); | |
| 788 | } | ||
| 789 | ✗ | else if ( loadOut > 0.0 ) | |
| 790 | { | ||
| 791 | ✗ | LoadingTotals[j].pctError = 100.0 * (loadIn / loadOut - 1.0); | |
| 792 | } | ||
| 793 |
2/2✓ Branch 0 taken 26 times.
✓ Branch 1 taken 20 times.
|
46 | maxError = MAX(maxError, LoadingTotals[j].pctError); |
| 794 | |||
| 795 | // --- report total counts as log10 | ||
| 796 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
|
46 | if ( Pollut[j].units == COUNT ) |
| 797 | { | ||
| 798 | ✗ | LoadingTotals[j].initLoad = LOG10(LoadingTotals[j].initLoad); | |
| 799 | ✗ | LoadingTotals[j].buildup = LOG10(LoadingTotals[j].buildup); | |
| 800 | ✗ | LoadingTotals[j].deposition = LOG10(LoadingTotals[j].deposition); | |
| 801 | ✗ | LoadingTotals[j].sweeping = LOG10(LoadingTotals[j].sweeping); | |
| 802 | ✗ | LoadingTotals[j].infil = LOG10(LoadingTotals[j].infil); | |
| 803 | ✗ | LoadingTotals[j].bmpRemoval = LOG10(LoadingTotals[j].bmpRemoval); | |
| 804 | ✗ | LoadingTotals[j].runoff = LOG10(LoadingTotals[j].runoff); | |
| 805 | ✗ | LoadingTotals[j].finalLoad = LOG10(LoadingTotals[j].finalLoad); | |
| 806 | } | ||
| 807 | } | ||
| 808 | 14 | return maxError; | |
| 809 | } | ||
| 810 | |||
| 811 | //============================================================================= | ||
| 812 | |||
| 813 | 9 | double massbal_getGwaterError() | |
| 814 | // | ||
| 815 | // Input: none | ||
| 816 | // Output: none | ||
| 817 | // Purpose: computes groundwater mass balance error. | ||
| 818 | // | ||
| 819 | { | ||
| 820 | int j; | ||
| 821 | double totalInflow; | ||
| 822 | double totalOutflow; | ||
| 823 | |||
| 824 | // --- find final storage in groundwater | ||
| 825 | 9 | GwaterTotals.finalStorage = 0.0; | |
| 826 |
2/2✓ Branch 0 taken 2311 times.
✓ Branch 1 taken 9 times.
|
2320 | for ( j = 0; j < Nobjects[SUBCATCH]; j++ ) |
| 827 | { | ||
| 828 | 2311 | GwaterTotals.finalStorage += gwater_getVolume(j) * Subcatch[j].area; | |
| 829 | } | ||
| 830 | |||
| 831 | // --- compute % difference between total inflow and outflow | ||
| 832 | 9 | totalInflow = GwaterTotals.infil + | |
| 833 | 9 | GwaterTotals.initStorage; | |
| 834 | 9 | totalOutflow = GwaterTotals.upperEvap + | |
| 835 | 9 | GwaterTotals.lowerEvap + | |
| 836 | 9 | GwaterTotals.lowerPerc + | |
| 837 | 9 | GwaterTotals.gwater + | |
| 838 | 9 | GwaterTotals.finalStorage; | |
| 839 | 9 | GwaterTotals.pctError = 0.0; | |
| 840 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | if ( fabs(totalInflow - totalOutflow) < 1.0 ) |
| 841 | { | ||
| 842 | ✗ | GwaterTotals.pctError = TINY; | |
| 843 | } | ||
| 844 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | else if ( totalInflow > 0.0 ) |
| 845 | { | ||
| 846 | 9 | GwaterTotals.pctError = 100.0 * (1.0 - totalOutflow / totalInflow); | |
| 847 | } | ||
| 848 | ✗ | else if ( totalOutflow > 0.0 ) | |
| 849 | { | ||
| 850 | ✗ | GwaterTotals.pctError = 100.0 * (totalInflow / totalOutflow - 1.0); | |
| 851 | } | ||
| 852 | 9 | GwaterError = GwaterTotals.pctError; | |
| 853 | 9 | return GwaterTotals.pctError; | |
| 854 | } | ||
| 855 | |||
| 856 | //============================================================================= | ||
| 857 | |||
| 858 | 58 | double massbal_getFlowError() | |
| 859 | // | ||
| 860 | // Input: none | ||
| 861 | // Output: none | ||
| 862 | // Purpose: computes flow routing mass balance error. | ||
| 863 | // | ||
| 864 | { | ||
| 865 | double totalInflow; | ||
| 866 | double totalOutflow; | ||
| 867 | |||
| 868 | // --- get final volume of nodes and links | ||
| 869 | 58 | FlowTotals.finalStorage = massbal_getStorage(TRUE); | |
| 870 | |||
| 871 | // --- add contributions to total inflow and outflow that are always positive | ||
| 872 | 58 | totalInflow = FlowTotals.initStorage + FlowTotals.wwInflow + FlowTotals.iiInflow; | |
| 873 | 58 | totalOutflow = FlowTotals.finalStorage + FlowTotals.flooding + FlowTotals.evapLoss + | |
| 874 | 58 | FlowTotals.seepLoss + FlowTotals.reacted; | |
| 875 | |||
| 876 | // --- add on contributions that might be either positive or negative | ||
| 877 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | if ( FlowTotals.dwInflow >= 0.0 ) totalInflow += FlowTotals.dwInflow; |
| 878 | ✗ | else totalOutflow -= FlowTotals.dwInflow; | |
| 879 |
2/2✓ Branch 0 taken 56 times.
✓ Branch 1 taken 2 times.
|
58 | if ( FlowTotals.gwInflow >= 0.0 ) totalInflow += FlowTotals.gwInflow; |
| 880 | 2 | else totalOutflow -= FlowTotals.gwInflow; | |
| 881 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | if ( FlowTotals.exInflow >= 0.0 ) totalInflow += FlowTotals.exInflow; |
| 882 | ✗ | else totalOutflow -= FlowTotals.exInflow; | |
| 883 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | if ( FlowTotals.outflow >= 0.0 ) totalOutflow += FlowTotals.outflow; |
| 884 | ✗ | else totalInflow -= FlowTotals.outflow; | |
| 885 | |||
| 886 | // --- find percent difference between total inflow and outflow | ||
| 887 | 58 | FlowTotals.pctError = 0.0; | |
| 888 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 38 times.
|
58 | if ( fabs(totalInflow - totalOutflow) < 1.0 ) |
| 889 | { | ||
| 890 | 20 | FlowTotals.pctError = TINY; | |
| 891 | } | ||
| 892 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | else if ( fabs(totalInflow) > 0.0 ) |
| 893 | { | ||
| 894 | 38 | FlowTotals.pctError = 100.0 * (1.0 - totalOutflow / totalInflow); | |
| 895 | } | ||
| 896 | ✗ | else if ( fabs(totalOutflow) > 0.0 ) | |
| 897 | { | ||
| 898 | ✗ | FlowTotals.pctError = 100.0 * (totalInflow / totalOutflow - 1.0); | |
| 899 | } | ||
| 900 | 58 | FlowError = FlowTotals.pctError; | |
| 901 | 58 | return FlowTotals.pctError; | |
| 902 | } | ||
| 903 | |||
| 904 | //============================================================================= | ||
| 905 | |||
| 906 | 15 | double massbal_getQualError() | |
| 907 | // | ||
| 908 | // Input: none | ||
| 909 | // Output: none | ||
| 910 | // Purpose: computes water quality routing mass balance error. | ||
| 911 | // | ||
| 912 | { | ||
| 913 | int p; | ||
| 914 | 15 | double maxQualError = 0.0; | |
| 915 | double totalInflow; | ||
| 916 | double totalOutflow; | ||
| 917 | double cf; | ||
| 918 | |||
| 919 | // --- analyze each pollutant | ||
| 920 |
2/2✓ Branch 0 taken 47 times.
✓ Branch 1 taken 15 times.
|
62 | for (p = 0; p < Nobjects[POLLUT]; p++) |
| 921 | { | ||
| 922 | // --- get final mass stored in nodes and links | ||
| 923 | 47 | QualTotals[p].finalStorage += massbal_getStoredMass(p); | |
| 924 | |||
| 925 | // --- compute % difference between total inflow and outflow | ||
| 926 | 47 | totalInflow = QualTotals[p].dwInflow + | |
| 927 | 47 | QualTotals[p].wwInflow + | |
| 928 | 47 | QualTotals[p].gwInflow + | |
| 929 | 47 | QualTotals[p].iiInflow + | |
| 930 | 47 | QualTotals[p].exInflow + | |
| 931 | 47 | QualTotals[p].initStorage; | |
| 932 | 47 | totalOutflow = QualTotals[p].flooding + | |
| 933 | 47 | QualTotals[p].outflow + | |
| 934 | 47 | QualTotals[p].reacted + | |
| 935 | 47 | QualTotals[p].seepLoss + | |
| 936 | 47 | QualTotals[p].finalStorage; | |
| 937 | 47 | QualTotals[p].pctError = 0.0; | |
| 938 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 20 times.
|
47 | if ( fabs(totalInflow - totalOutflow) < 0.001 ) |
| 939 | { | ||
| 940 | 27 | QualTotals[p].pctError = TINY; | |
| 941 | } | ||
| 942 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | else if ( totalInflow > 0.0 ) |
| 943 | { | ||
| 944 | 20 | QualTotals[p].pctError = 100.0 * (1.0 - totalOutflow / totalInflow); | |
| 945 | } | ||
| 946 | ✗ | else if ( totalOutflow > 0.0 ) | |
| 947 | { | ||
| 948 | ✗ | QualTotals[p].pctError = 100.0 * (totalInflow / totalOutflow - 1.0); | |
| 949 | } | ||
| 950 | |||
| 951 | // --- update max. error among all pollutants | ||
| 952 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 27 times.
|
47 | if ( fabs(QualTotals[p].pctError) > fabs(maxQualError) ) |
| 953 | { | ||
| 954 | 20 | maxQualError = QualTotals[p].pctError; | |
| 955 | } | ||
| 956 | |||
| 957 | // --- convert totals to reporting units (lbs, kg, or Log(Count)) | ||
| 958 | 47 | cf = LperFT3; | |
| 959 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
|
47 | if ( Pollut[p].units == COUNT ) |
| 960 | { | ||
| 961 | ✗ | QualTotals[p].dwInflow = LOG10(cf * QualTotals[p].dwInflow); | |
| 962 | ✗ | QualTotals[p].wwInflow = LOG10(cf * QualTotals[p].wwInflow); | |
| 963 | ✗ | QualTotals[p].gwInflow = LOG10(cf * QualTotals[p].gwInflow); | |
| 964 | ✗ | QualTotals[p].iiInflow = LOG10(cf * QualTotals[p].iiInflow); | |
| 965 | ✗ | QualTotals[p].exInflow = LOG10(cf * QualTotals[p].exInflow); | |
| 966 | ✗ | QualTotals[p].flooding = LOG10(cf * QualTotals[p].flooding); | |
| 967 | ✗ | QualTotals[p].outflow = LOG10(cf * QualTotals[p].outflow); | |
| 968 | ✗ | QualTotals[p].reacted = LOG10(cf * QualTotals[p].reacted); | |
| 969 | ✗ | QualTotals[p].seepLoss = LOG10(cf * QualTotals[p].seepLoss); | |
| 970 | ✗ | QualTotals[p].initStorage = LOG10(cf * QualTotals[p].initStorage); | |
| 971 | ✗ | QualTotals[p].finalStorage = LOG10(cf * QualTotals[p].finalStorage); | |
| 972 | } | ||
| 973 | else | ||
| 974 | { | ||
| 975 | 47 | cf = cf * UCF(MASS); | |
| 976 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 45 times.
|
47 | if ( Pollut[p].units == UG ) cf /= 1000.0; |
| 977 | 47 | QualTotals[p].dwInflow *= cf; | |
| 978 | 47 | QualTotals[p].wwInflow *= cf; | |
| 979 | 47 | QualTotals[p].gwInflow *= cf; | |
| 980 | 47 | QualTotals[p].iiInflow *= cf; | |
| 981 | 47 | QualTotals[p].exInflow *= cf; | |
| 982 | 47 | QualTotals[p].flooding *= cf; | |
| 983 | 47 | QualTotals[p].outflow *= cf; | |
| 984 | 47 | QualTotals[p].reacted *= cf; | |
| 985 | 47 | QualTotals[p].seepLoss *= cf; | |
| 986 | 47 | QualTotals[p].initStorage *= cf; | |
| 987 | 47 | QualTotals[p].finalStorage *= cf; | |
| 988 | } | ||
| 989 | } | ||
| 990 | 15 | QualError = maxQualError; | |
| 991 | 15 | return maxQualError; | |
| 992 | } | ||
| 993 | //============================================================================= | ||
| 994 | |||
| 995 | 1066421 | double massbal_getStepFlowError() | |
| 996 | // | ||
| 997 | // Input: none | ||
| 998 | // Output: returns fractional difference between total inflow and outflow. | ||
| 999 | // Purpose: computes flow routing mass balance error at current time step. | ||
| 1000 | // | ||
| 1001 | { | ||
| 1002 | double totalInflow; | ||
| 1003 | double totalOutflow; | ||
| 1004 | |||
| 1005 | // --- compute % difference between total inflow and outflow | ||
| 1006 | 1066421 | totalInflow = StepFlowTotals.dwInflow + | |
| 1007 | 1066421 | StepFlowTotals.wwInflow + | |
| 1008 | 1066421 | StepFlowTotals.gwInflow + | |
| 1009 | 1066421 | StepFlowTotals.iiInflow + | |
| 1010 | 1066421 | StepFlowTotals.exInflow; | |
| 1011 | 1066421 | totalOutflow = StepFlowTotals.flooding + | |
| 1012 | 1066421 | StepFlowTotals.outflow + | |
| 1013 | 1066421 | StepFlowTotals.evapLoss + | |
| 1014 | 1066421 | StepFlowTotals.seepLoss + | |
| 1015 | 1066421 | StepFlowTotals.reacted; | |
| 1016 |
2/2✓ Branch 0 taken 435179 times.
✓ Branch 1 taken 631242 times.
|
1066421 | if ( fabs(totalInflow) > 0.0 ) |
| 1017 | 435179 | return 1.0 - totalOutflow / totalInflow; | |
| 1018 |
2/2✓ Branch 0 taken 2944 times.
✓ Branch 1 taken 628298 times.
|
631242 | else if ( fabs(totalOutflow) > 0.0 ) |
| 1019 | 2944 | return totalInflow / totalOutflow - 1.0; | |
| 1020 | 628298 | else return 0.0; | |
| 1021 | } | ||
| 1022 | |||
| 1023 | //============================================================================= | ||
| 1024 | |||
| 1025 | 94 | double massbal_getStoredMass(int p) | |
| 1026 | // | ||
| 1027 | // Input: p = pollutant index | ||
| 1028 | // Output: returns mass of pollutant. | ||
| 1029 | // Purpose: computes mass of pollutant stored in conveyance network. | ||
| 1030 | // | ||
| 1031 | { | ||
| 1032 | int j; | ||
| 1033 | 94 | double storedMass = 0.0; | |
| 1034 | |||
| 1035 | // --- get mass stored in nodes | ||
| 1036 |
2/2✓ Branch 0 taken 51542 times.
✓ Branch 1 taken 94 times.
|
51636 | for (j = 0; j < Nobjects[NODE]; j++) |
| 1037 | 51542 | storedMass += Node[j].newVolume * Node[j].newQual[p]; | |
| 1038 | |||
| 1039 | // --- get mass stored in links (except for Steady Flow routing) | ||
| 1040 |
1/2✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
|
94 | if ( RouteModel != SF ) |
| 1041 | { | ||
| 1042 |
2/2✓ Branch 0 taken 54364 times.
✓ Branch 1 taken 94 times.
|
54458 | for (j = 0; j < Nobjects[LINK]; j++) |
| 1043 | 54364 | storedMass += Link[j].newVolume * Link[j].newQual[p]; | |
| 1044 | } | ||
| 1045 | 94 | return storedMass; | |
| 1046 | } | ||
| 1047 |