stats.c
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | //----------------------------------------------------------------------------- | ||
| 2 | // stats.c | ||
| 3 | // | ||
| 4 | // Project: EPA SWMM5 | ||
| 5 | // Version: 5.2 | ||
| 6 | // Date: 11/01/21 (Build 5.2.0) | ||
| 7 | // Author: L. Rossman | ||
| 8 | // R. Dickinson (CDM) | ||
| 9 | // | ||
| 10 | // Simulation statistics functions. | ||
| 11 | // | ||
| 12 | // Update History | ||
| 13 | // ============== | ||
| 14 | // Build 5.1.007: | ||
| 15 | // - Exfiltration losses added to storage node statistics. | ||
| 16 | // Build 5.1.008: | ||
| 17 | // - Support for updating groundwater statistics added. | ||
| 18 | // - Support for updating maximum reported nodal depths added. | ||
| 19 | // - OpenMP parallelization applied to updating node and link flow statistics. | ||
| 20 | // - Updating of time that conduit is upstrm/dnstrm full was modified. | ||
| 21 | // Build 5.1.011: | ||
| 22 | // - Surcharging is now evaluated only under dynamic wave flow routing and | ||
| 23 | // storage nodes cannot be classified as surcharged. | ||
| 24 | // Build 5.1.012: | ||
| 25 | // - Time step statistics now evaluated only in non-steady state periods. | ||
| 26 | // - Check for full conduit flow now accounts for number of barrels. | ||
| 27 | // Build 5.1.013: | ||
| 28 | // - Include omp.h protected against lack of compiler support for OpenMP. | ||
| 29 | // - Statistics on impervious and pervious runoff totals added. | ||
| 30 | // - Storage nodes with a non-zero surcharge depth (e.g. enclosed tanks) | ||
| 31 | // can now be classified as being surcharged. | ||
| 32 | // Build 5.1.015: | ||
| 33 | // - Fixes bug in summary statistics when Report Start date > Start Date. | ||
| 34 | // - Fixes failure to initialize all subcatchment groundwater statistics. | ||
| 35 | // - Support added for grouped freqency table of routing time steps. | ||
| 36 | // Build 5.2.0: | ||
| 37 | // - Support added for reporting most frequent non-converging nodes. | ||
| 38 | // - Support added for RptFlags.disabled option. | ||
| 39 | // - Fixed display of routing statistics report for RptFlags.flowStats = FALSE. | ||
| 40 | //----------------------------------------------------------------------------- | ||
| 41 | #define _CRT_SECURE_NO_DEPRECATE | ||
| 42 | |||
| 43 | #include <stdlib.h> | ||
| 44 | #include <string.h> | ||
| 45 | #include <math.h> | ||
| 46 | #include "headers.h" | ||
| 47 | |||
| 48 | //----------------------------------------------------------------------------- | ||
| 49 | // Shared variables | ||
| 50 | //----------------------------------------------------------------------------- | ||
| 51 | #define MAX_STATS 5 | ||
| 52 | static TTimeStepStats TimeStepStats; | ||
| 53 | static TMaxStats MaxMassBalErrs[MAX_STATS]; | ||
| 54 | static TMaxStats MaxCourantCrit[MAX_STATS]; | ||
| 55 | static TMaxStats MaxFlowTurns[MAX_STATS]; | ||
| 56 | static TMaxStats MaxNonConverged[MAX_STATS]; | ||
| 57 | static double SysOutfallFlow; | ||
| 58 | |||
| 59 | //----------------------------------------------------------------------------- | ||
| 60 | // Exportable variables (shared with statsrpt.c) | ||
| 61 | //----------------------------------------------------------------------------- | ||
| 62 | TSubcatchStats* SubcatchStats; | ||
| 63 | TNodeStats* NodeStats; | ||
| 64 | TLinkStats* LinkStats; | ||
| 65 | TStorageStats* StorageStats; | ||
| 66 | TOutfallStats* OutfallStats; | ||
| 67 | TPumpStats* PumpStats; | ||
| 68 | double MaxOutfallFlow; | ||
| 69 | double MaxRunoffFlow; | ||
| 70 | double RoutingTimeSpan; | ||
| 71 | |||
| 72 | //----------------------------------------------------------------------------- | ||
| 73 | // Imported variables | ||
| 74 | //----------------------------------------------------------------------------- | ||
| 75 | extern double* NodeInflow; // defined in massbal.c | ||
| 76 | extern double* NodeOutflow; // defined in massbal.c | ||
| 77 | |||
| 78 | //----------------------------------------------------------------------------- | ||
| 79 | // External functions (declared in funcs.h) | ||
| 80 | //----------------------------------------------------------------------------- | ||
| 81 | // stats_open (called from swmm_start in swmm5.c) | ||
| 82 | // stats_close (called from swmm_end in swmm5.c) | ||
| 83 | // stats_report (called from swmm_end in swmm5.c) | ||
| 84 | // stats_updateSubcatchStats (called from subcatch_getRunoff) | ||
| 85 | // stats_updateGwaterStats (called from gwater_getGroundwater) | ||
| 86 | // stats_updateFlowStats (called from routing_execute) | ||
| 87 | // stats_updateTimeStepStats (called from routing_execute) | ||
| 88 | // stats_updateCriticalTimeCount (called from getVariableStep in dynwave.c) | ||
| 89 | // stats_updateMaxNodeDepth (called from output_saveNodeResults) | ||
| 90 | // stats_updateConvergenceStats (called from updateConvergenceStats in dynwave.c) | ||
| 91 | |||
| 92 | //----------------------------------------------------------------------------- | ||
| 93 | // Local functions | ||
| 94 | //----------------------------------------------------------------------------- | ||
| 95 | static void stats_updateNodeStats(int node, double tStep, DateTime aDate); | ||
| 96 | static void stats_updateLinkStats(int link, double tStep, DateTime aDate); | ||
| 97 | static void stats_findMaxStats(void); | ||
| 98 | static void stats_updateMaxStats(TMaxStats maxStats[], int i, int j, double x); | ||
| 99 | |||
| 100 | //============================================================================= | ||
| 101 | |||
| 102 | 58 | int stats_open() | |
| 103 | // | ||
| 104 | // Input: none | ||
| 105 | // Output: returns an error code | ||
| 106 | // Purpose: opens the simulation statistics system. | ||
| 107 | // | ||
| 108 | { | ||
| 109 | int j, k; | ||
| 110 | double timeStepDelta; | ||
| 111 | double logMaxTimeStep; | ||
| 112 | double logMinTimeStep; | ||
| 113 | |||
| 114 | // --- set all pointers to NULL | ||
| 115 | 58 | NodeStats = NULL; | |
| 116 | 58 | LinkStats = NULL; | |
| 117 | 58 | StorageStats = NULL; | |
| 118 | 58 | OutfallStats = NULL; | |
| 119 | 58 | PumpStats = NULL; | |
| 120 | |||
| 121 | // --- allocate memory for & initialize subcatchment statistics | ||
| 122 | 58 | SubcatchStats = NULL; | |
| 123 |
2/2✓ Branch 0 taken 37 times.
✓ Branch 1 taken 21 times.
|
58 | if ( Nobjects[SUBCATCH] > 0 ) |
| 124 | { | ||
| 125 | 37 | SubcatchStats = (TSubcatchStats *) calloc(Nobjects[SUBCATCH], | |
| 126 | sizeof(TSubcatchStats)); | ||
| 127 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
|
37 | if ( !SubcatchStats ) |
| 128 | { | ||
| 129 | ✗ | report_writeErrorMsg(ERR_MEMORY, ""); | |
| 130 | ✗ | return ErrorCode; | |
| 131 | } | ||
| 132 |
2/2✓ Branch 0 taken 2393 times.
✓ Branch 1 taken 37 times.
|
2430 | for (j=0; j<Nobjects[SUBCATCH]; j++) |
| 133 | { | ||
| 134 | 2393 | SubcatchStats[j].precip = 0.0; | |
| 135 | 2393 | SubcatchStats[j].runon = 0.0; | |
| 136 | 2393 | SubcatchStats[j].evap = 0.0; | |
| 137 | 2393 | SubcatchStats[j].infil = 0.0; | |
| 138 | 2393 | SubcatchStats[j].runoff = 0.0; | |
| 139 | 2393 | SubcatchStats[j].maxFlow = 0.0; | |
| 140 | 2393 | SubcatchStats[j].impervRunoff = 0.0; | |
| 141 | 2393 | SubcatchStats[j].pervRunoff = 0.0; | |
| 142 | } | ||
| 143 | |||
| 144 |
2/2✓ Branch 0 taken 2393 times.
✓ Branch 1 taken 37 times.
|
2430 | for (j=0; j<Nobjects[SUBCATCH]; j++) |
| 145 | { | ||
| 146 |
2/2✓ Branch 0 taken 152 times.
✓ Branch 1 taken 2241 times.
|
2393 | if ( Subcatch[j].groundwater == NULL ) continue; |
| 147 | 2241 | Subcatch[j].groundwater->stats.avgUpperMoist = 0.0; | |
| 148 | 2241 | Subcatch[j].groundwater->stats.avgWaterTable = 0.0; | |
| 149 | 2241 | Subcatch[j].groundwater->stats.infil = 0.0; | |
| 150 | 2241 | Subcatch[j].groundwater->stats.latFlow = 0.0; | |
| 151 | 2241 | Subcatch[j].groundwater->stats.deepFlow = 0.0; | |
| 152 | 2241 | Subcatch[j].groundwater->stats.evap = 0.0; | |
| 153 | 2241 | Subcatch[j].groundwater->stats.maxFlow = 0.0; | |
| 154 | 2241 | Subcatch[j].groundwater->stats.finalUpperMoist = 0.0; | |
| 155 | 2241 | Subcatch[j].groundwater->stats.finalWaterTable = 0.0; | |
| 156 | } | ||
| 157 | } | ||
| 158 | |||
| 159 | // --- allocate memory for node & link stats | ||
| 160 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 10 times.
|
58 | if ( Nobjects[LINK] > 0 ) |
| 161 | { | ||
| 162 | 48 | NodeStats = (TNodeStats *) calloc(Nobjects[NODE], sizeof(TNodeStats)); | |
| 163 | 48 | LinkStats = (TLinkStats *) calloc(Nobjects[LINK], sizeof(TLinkStats)); | |
| 164 |
2/4✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
|
48 | if ( !NodeStats || !LinkStats ) |
| 165 | { | ||
| 166 | ✗ | report_writeErrorMsg(ERR_MEMORY, ""); | |
| 167 | ✗ | return ErrorCode; | |
| 168 | } | ||
| 169 | } | ||
| 170 | |||
| 171 | // --- initialize node stats | ||
| 172 |
4/4✓ Branch 0 taken 48 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 10173 times.
✓ Branch 3 taken 48 times.
|
10231 | if ( NodeStats ) for ( j = 0; j < Nobjects[NODE]; j++ ) |
| 173 | { | ||
| 174 | 10173 | NodeStats[j].avgDepth = 0.0; | |
| 175 | 10173 | NodeStats[j].maxDepth = 0.0; | |
| 176 | 10173 | NodeStats[j].maxDepthDate = StartDateTime; | |
| 177 | 10173 | NodeStats[j].maxRptDepth = 0.0; | |
| 178 | 10173 | NodeStats[j].volFlooded = 0.0; | |
| 179 | 10173 | NodeStats[j].timeFlooded = 0.0; | |
| 180 | 10173 | NodeStats[j].timeSurcharged = 0.0; | |
| 181 | 10173 | NodeStats[j].timeCourantCritical = 0.0; | |
| 182 | 10173 | NodeStats[j].totLatFlow = 0.0; | |
| 183 | 10173 | NodeStats[j].maxLatFlow = 0.0; | |
| 184 | 10173 | NodeStats[j].maxInflow = 0.0; | |
| 185 | 10173 | NodeStats[j].maxOverflow = 0.0; | |
| 186 | 10173 | NodeStats[j].maxPondedVol = 0.0; | |
| 187 | 10173 | NodeStats[j].nonConvergedCount = 0; | |
| 188 | 10173 | NodeStats[j].maxInflowDate = StartDateTime; | |
| 189 | 10173 | NodeStats[j].maxOverflowDate = StartDateTime; | |
| 190 | } | ||
| 191 | |||
| 192 | // --- initialize link stats | ||
| 193 |
4/4✓ Branch 0 taken 48 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 10508 times.
✓ Branch 3 taken 48 times.
|
10566 | if ( LinkStats ) for ( j = 0; j < Nobjects[LINK]; j++ ) |
| 194 | { | ||
| 195 | 10508 | LinkStats[j].maxFlow = 0.0; | |
| 196 | 10508 | LinkStats[j].maxVeloc = 0.0; | |
| 197 | 10508 | LinkStats[j].maxDepth = 0.0; | |
| 198 | 10508 | LinkStats[j].maxStreetFilled = 0.0; | |
| 199 | 10508 | LinkStats[j].timeSurcharged = 0.0; | |
| 200 | 10508 | LinkStats[j].timeFullUpstream = 0.0; | |
| 201 | 10508 | LinkStats[j].timeFullDnstream = 0.0; | |
| 202 | 10508 | LinkStats[j].timeFullFlow = 0.0; | |
| 203 | 10508 | LinkStats[j].timeCapacityLimited = 0.0; | |
| 204 | 10508 | LinkStats[j].timeCourantCritical = 0.0; | |
| 205 |
2/2✓ Branch 0 taken 73556 times.
✓ Branch 1 taken 10508 times.
|
84064 | for (k=0; k<MAX_FLOW_CLASSES; k++) |
| 206 | 73556 | LinkStats[j].timeInFlowClass[k] = 0.0; | |
| 207 | 10508 | LinkStats[j].flowTurns = 0; | |
| 208 | 10508 | LinkStats[j].flowTurnSign = 0; | |
| 209 | } | ||
| 210 | |||
| 211 | // --- allocate memory for & initialize storage unit statistics | ||
| 212 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 39 times.
|
58 | if ( Nnodes[STORAGE] > 0 ) |
| 213 | { | ||
| 214 | 19 | StorageStats = (TStorageStats *) calloc(Nnodes[STORAGE], | |
| 215 | sizeof(TStorageStats)); | ||
| 216 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
|
19 | if ( !StorageStats ) |
| 217 | { | ||
| 218 | ✗ | report_writeErrorMsg(ERR_MEMORY, ""); | |
| 219 | ✗ | return ErrorCode; | |
| 220 | } | ||
| 221 |
2/2✓ Branch 0 taken 6555 times.
✓ Branch 1 taken 19 times.
|
6574 | else for ( k = 0; k < Nobjects[NODE]; k++ ) |
| 222 | { | ||
| 223 |
2/2✓ Branch 0 taken 6438 times.
✓ Branch 1 taken 117 times.
|
6555 | if ( Node[k].type != STORAGE ) continue; |
| 224 | 117 | j = Node[k].subIndex; | |
| 225 | 117 | StorageStats[j].initVol = Node[k].newVolume; | |
| 226 | 117 | StorageStats[j].avgVol = 0.0; | |
| 227 | 117 | StorageStats[j].maxVol = 0.0; | |
| 228 | 117 | StorageStats[j].maxFlow = 0.0; | |
| 229 | 117 | StorageStats[j].evapLosses = 0.0; | |
| 230 | 117 | StorageStats[j].exfilLosses = 0.0; | |
| 231 | 117 | StorageStats[j].maxVolDate = StartDateTime; | |
| 232 | } | ||
| 233 | } | ||
| 234 | |||
| 235 | // --- allocate memory for & initialize outfall statistics | ||
| 236 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | if ( Nnodes[OUTFALL] > 0 ) |
| 237 | { | ||
| 238 | 58 | OutfallStats = (TOutfallStats *) calloc(Nnodes[OUTFALL], | |
| 239 | sizeof(TOutfallStats)); | ||
| 240 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
|
58 | if ( !OutfallStats ) |
| 241 | { | ||
| 242 | ✗ | report_writeErrorMsg(ERR_MEMORY, ""); | |
| 243 | ✗ | return ErrorCode; | |
| 244 | } | ||
| 245 |
2/2✓ Branch 0 taken 348 times.
✓ Branch 1 taken 58 times.
|
406 | else for ( j = 0; j < Nnodes[OUTFALL]; j++ ) |
| 246 | { | ||
| 247 | 348 | OutfallStats[j].avgFlow = 0.0; | |
| 248 | 348 | OutfallStats[j].maxFlow = 0.0; | |
| 249 | 348 | OutfallStats[j].totalPeriods = 0; | |
| 250 |
2/2✓ Branch 0 taken 260 times.
✓ Branch 1 taken 88 times.
|
348 | if ( Nobjects[POLLUT] > 0 ) |
| 251 | { | ||
| 252 | 260 | OutfallStats[j].totalLoad = | |
| 253 | 260 | (double *) calloc(Nobjects[POLLUT], sizeof(double)); | |
| 254 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 260 times.
|
260 | if ( !OutfallStats[j].totalLoad ) |
| 255 | { | ||
| 256 | ✗ | report_writeErrorMsg(ERR_MEMORY, ""); | |
| 257 | ✗ | return ErrorCode; | |
| 258 | } | ||
| 259 |
2/2✓ Branch 0 taken 1027 times.
✓ Branch 1 taken 260 times.
|
1287 | for (k=0; k<Nobjects[POLLUT]; k++) |
| 260 | 1027 | OutfallStats[j].totalLoad[k] = 0.0; | |
| 261 | } | ||
| 262 | 88 | else OutfallStats[j].totalLoad = NULL; | |
| 263 | } | ||
| 264 | } | ||
| 265 | |||
| 266 | // --- allocate memory & initialize pumping statistics | ||
| 267 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 46 times.
|
58 | if ( Nlinks[PUMP] > 0 ) |
| 268 | { | ||
| 269 | 12 | PumpStats = (TPumpStats *) calloc(Nlinks[PUMP], sizeof(TPumpStats)); | |
| 270 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if ( !PumpStats ) |
| 271 | { | ||
| 272 | ✗ | report_writeErrorMsg(ERR_MEMORY, ""); | |
| 273 | ✗ | return ErrorCode; | |
| 274 | } | ||
| 275 |
2/2✓ Branch 0 taken 106 times.
✓ Branch 1 taken 12 times.
|
118 | else for ( j = 0; j < Nlinks[PUMP]; j++ ) |
| 276 | { | ||
| 277 | 106 | PumpStats[j].utilized = 0.0; | |
| 278 | 106 | PumpStats[j].minFlow = 0.0; | |
| 279 | 106 | PumpStats[j].avgFlow = 0.0; | |
| 280 | 106 | PumpStats[j].maxFlow = 0.0; | |
| 281 | 106 | PumpStats[j].volume = 0.0; | |
| 282 | 106 | PumpStats[j].energy = 0.0; | |
| 283 | 106 | PumpStats[j].startUps = 0; | |
| 284 | 106 | PumpStats[j].offCurveLow = 0.0; | |
| 285 | 106 | PumpStats[j].offCurveHigh = 0.0; | |
| 286 | } | ||
| 287 | } | ||
| 288 | |||
| 289 | // --- initialize system stats | ||
| 290 | 58 | MaxRunoffFlow = 0.0; | |
| 291 | 58 | MaxOutfallFlow = 0.0; | |
| 292 | 58 | TimeStepStats.maxTimeStep = 0.0; | |
| 293 | 58 | TimeStepStats.minTimeStep = RouteStep; | |
| 294 | 58 | TimeStepStats.routingTime = 0.0; | |
| 295 | 58 | TimeStepStats.trialsCount = 0.0; | |
| 296 | 58 | TimeStepStats.steadyStateTime = 0.0; | |
| 297 | 58 | TimeStepStats.timeStepCount = 0; | |
| 298 | |||
| 299 | // --- divide range between min and max routing time steps into | ||
| 300 | // equal intervals using a logarithmic scale | ||
| 301 | 58 | logMaxTimeStep = log10(RouteStep); | |
| 302 | 58 | logMinTimeStep = log10(MinRouteStep); | |
| 303 | 58 | timeStepDelta = (logMaxTimeStep - logMinTimeStep) / (double)(TIMELEVELS-1); | |
| 304 | 58 | TimeStepStats.timeStepIntervals[0] = RouteStep; | |
| 305 |
2/2✓ Branch 0 taken 290 times.
✓ Branch 1 taken 58 times.
|
348 | for (j = 1; j < TIMELEVELS; j++) |
| 306 | { | ||
| 307 | 290 | TimeStepStats.timeStepIntervals[j] = | |
| 308 | 290 | pow(10., logMaxTimeStep - j * timeStepDelta); | |
| 309 | 290 | TimeStepStats.timeStepCounts[j] = 0; | |
| 310 | } | ||
| 311 | 58 | TimeStepStats.timeStepIntervals[TIMELEVELS - 1] = MinRouteStep; | |
| 312 | 58 | RoutingTimeSpan = 0.0; | |
| 313 | 58 | return 0; | |
| 314 | } | ||
| 315 | |||
| 316 | //============================================================================= | ||
| 317 | |||
| 318 | 58 | void stats_close() | |
| 319 | // | ||
| 320 | // Input: none | ||
| 321 | // Output: | ||
| 322 | // Purpose: closes the simulation statistics system. | ||
| 323 | // | ||
| 324 | { | ||
| 325 | int j; | ||
| 326 | |||
| 327 |
2/2✓ Branch 0 taken 37 times.
✓ Branch 1 taken 21 times.
|
58 | FREE(SubcatchStats); |
| 328 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 10 times.
|
58 | FREE(NodeStats); |
| 329 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 10 times.
|
58 | FREE(LinkStats); |
| 330 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 39 times.
|
58 | FREE(StorageStats); |
| 331 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | if ( OutfallStats ) |
| 332 | { | ||
| 333 |
2/2✓ Branch 0 taken 348 times.
✓ Branch 1 taken 58 times.
|
406 | for ( j=0; j<Nnodes[OUTFALL]; j++ ) |
| 334 |
2/2✓ Branch 0 taken 260 times.
✓ Branch 1 taken 88 times.
|
348 | FREE(OutfallStats[j].totalLoad); |
| 335 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | FREE(OutfallStats); |
| 336 | } | ||
| 337 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 46 times.
|
58 | FREE(PumpStats); |
| 338 | 58 | } | |
| 339 | |||
| 340 | //============================================================================= | ||
| 341 | |||
| 342 | 58 | void stats_report() | |
| 343 | // | ||
| 344 | // Input: none | ||
| 345 | // Output: none | ||
| 346 | // Purpose: reports simulation statistics. | ||
| 347 | // | ||
| 348 | { | ||
| 349 | // --- report flow routing accuracy statistics | ||
| 350 |
3/4✓ Branch 0 taken 48 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
|
58 | if ( Nobjects[LINK] > 0 && RouteModel != NO_ROUTING ) |
| 351 | { | ||
| 352 | 48 | stats_findMaxStats(); | |
| 353 |
2/4✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
|
48 | if (!RptFlags.disabled && RptFlags.flowStats) |
| 354 | { | ||
| 355 | 48 | report_writeMaxStats(MaxMassBalErrs, MaxCourantCrit, MAX_STATS); | |
| 356 | 48 | report_writeMaxFlowTurns(MaxFlowTurns, MAX_STATS); | |
| 357 | 48 | report_writeNonconvergedStats(MaxNonConverged, MAX_STATS); | |
| 358 | 48 | report_writeTimeStepStats(&TimeStepStats); | |
| 359 | } | ||
| 360 | } | ||
| 361 | |||
| 362 | // --- report summary statistics | ||
| 363 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | if (!RptFlags.disabled) |
| 364 | 58 | statsrpt_writeReport(); | |
| 365 | 58 | } | |
| 366 | |||
| 367 | //============================================================================= | ||
| 368 | |||
| 369 | 3229694 | void stats_updateSubcatchStats(int j, double rainVol, double runonVol, | |
| 370 | double evapVol, double infilVol, | ||
| 371 | double impervVol, double pervVol, | ||
| 372 | double runoffVol, double runoff) | ||
| 373 | // | ||
| 374 | // Input: j = subcatchment index | ||
| 375 | // rainVol = rainfall + snowfall volume (ft3) | ||
| 376 | // runonVol = runon volume from other subcatchments (ft3) | ||
| 377 | // evapVol = evaporation volume (ft3) | ||
| 378 | // infilVol = infiltration volume (ft3) | ||
| 379 | // impervVol = impervious runoff volume (ft3) | ||
| 380 | // pervVol = pervious runoff volume (ft3) | ||
| 381 | // runoffVol = runoff volume (ft3) | ||
| 382 | // runoff = runoff rate (cfs) | ||
| 383 | // Output: none | ||
| 384 | // Purpose: updates totals of runoff components for a specific subcatchment. | ||
| 385 | // | ||
| 386 | { | ||
| 387 | 3229694 | SubcatchStats[j].precip += rainVol; | |
| 388 | 3229694 | SubcatchStats[j].runon += runonVol; | |
| 389 | 3229694 | SubcatchStats[j].evap += evapVol; | |
| 390 | 3229694 | SubcatchStats[j].infil += infilVol; | |
| 391 | 3229694 | SubcatchStats[j].runoff += runoffVol; | |
| 392 |
2/2✓ Branch 0 taken 3179641 times.
✓ Branch 1 taken 50053 times.
|
3229694 | SubcatchStats[j].maxFlow = MAX(SubcatchStats[j].maxFlow, runoff); |
| 393 | 3229694 | SubcatchStats[j].impervRunoff += impervVol; | |
| 394 | 3229694 | SubcatchStats[j].pervRunoff += pervVol; | |
| 395 | 3229694 | } | |
| 396 | |||
| 397 | //============================================================================= | ||
| 398 | |||
| 399 | 3033546 | void stats_updateGwaterStats(int j, double infil, double evap, double latFlow, | |
| 400 | double deepFlow, double theta, double waterTable, | ||
| 401 | double tStep) | ||
| 402 | { | ||
| 403 | 3033546 | Subcatch[j].groundwater->stats.infil += infil * tStep; | |
| 404 | 3033546 | Subcatch[j].groundwater->stats.evap += evap * tStep; | |
| 405 | 3033546 | Subcatch[j].groundwater->stats.latFlow += latFlow * tStep; | |
| 406 | 3033546 | Subcatch[j].groundwater->stats.deepFlow += deepFlow * tStep; | |
| 407 | 3033546 | Subcatch[j].groundwater->stats.avgUpperMoist += theta * tStep; | |
| 408 | 3033546 | Subcatch[j].groundwater->stats.avgWaterTable += waterTable * tStep; | |
| 409 | 3033546 | Subcatch[j].groundwater->stats.finalUpperMoist = theta; | |
| 410 | 3033546 | Subcatch[j].groundwater->stats.finalWaterTable = waterTable; | |
| 411 |
2/2✓ Branch 0 taken 114227 times.
✓ Branch 1 taken 2919319 times.
|
3033546 | if ( fabs(latFlow) > fabs(Subcatch[j].groundwater->stats.maxFlow) ) |
| 412 | { | ||
| 413 | 114227 | Subcatch[j].groundwater->stats.maxFlow = latFlow; | |
| 414 | } | ||
| 415 | 3033546 | } | |
| 416 | |||
| 417 | //============================================================================= | ||
| 418 | |||
| 419 | 33090 | void stats_updateMaxRunoff() | |
| 420 | // | ||
| 421 | // Input: none | ||
| 422 | // Output: updates global variable MaxRunoffFlow | ||
| 423 | // Purpose: updates value of maximum system runoff rate. | ||
| 424 | // | ||
| 425 | { | ||
| 426 | int j; | ||
| 427 | 33090 | double sysRunoff = 0.0; | |
| 428 | |||
| 429 |
2/2✓ Branch 0 taken 3229694 times.
✓ Branch 1 taken 33090 times.
|
3262784 | for (j=0; j<Nobjects[SUBCATCH]; j++) sysRunoff += Subcatch[j].newRunoff; |
| 430 |
2/2✓ Branch 0 taken 31744 times.
✓ Branch 1 taken 1346 times.
|
33090 | MaxRunoffFlow = MAX(MaxRunoffFlow, sysRunoff); |
| 431 | 33090 | } | |
| 432 | |||
| 433 | //============================================================================= | ||
| 434 | |||
| 435 | 1930386 | void stats_updateMaxNodeDepth(int j, double depth) | |
| 436 | // | ||
| 437 | // Input: j = node index | ||
| 438 | // depth = water depth at node at current reporting time (ft) | ||
| 439 | // Output: none | ||
| 440 | // Purpose: updates a node's maximum depth recorded at reporting times. | ||
| 441 | // | ||
| 442 | { | ||
| 443 |
2/2✓ Branch 0 taken 1927674 times.
✓ Branch 1 taken 2712 times.
|
1930386 | if ( NodeStats != NULL ) |
| 444 |
2/2✓ Branch 0 taken 1818867 times.
✓ Branch 1 taken 108807 times.
|
1927674 | NodeStats[j].maxRptDepth = MAX(NodeStats[j].maxRptDepth, depth); |
| 445 | 1930386 | } | |
| 446 | |||
| 447 | //============================================================================= | ||
| 448 | |||
| 449 | 988013 | void stats_updateFlowStats(double tStep, DateTime aDate) | |
| 450 | // | ||
| 451 | // Input: tStep = routing time step (sec) | ||
| 452 | // aDate = current date/time | ||
| 453 | // Output: none | ||
| 454 | // Purpose: updates various flow routing statistics at current time period. | ||
| 455 | // | ||
| 456 | { | ||
| 457 | int j; | ||
| 458 | |||
| 459 | // --- update stats only after reporting period begins | ||
| 460 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 988013 times.
|
988013 | if ( aDate < ReportStart ) return; |
| 461 | 988013 | SysOutfallFlow = 0.0; | |
| 462 | |||
| 463 | // --- update node & link stats | ||
| 464 | //#pragma omp parallel num_threads(NumThreads) | ||
| 465 | { | ||
| 466 | // #pragma omp for | ||
| 467 |
2/2✓ Branch 0 taken 37851987 times.
✓ Branch 1 taken 988013 times.
|
38840000 | for ( j=0; j<Nobjects[NODE]; j++ ) |
| 468 | 37851987 | stats_updateNodeStats(j, tStep, aDate); | |
| 469 | // #pragma omp for | ||
| 470 |
2/2✓ Branch 0 taken 37208897 times.
✓ Branch 1 taken 988013 times.
|
38196910 | for ( j=0; j<Nobjects[LINK]; j++ ) |
| 471 | 37208897 | stats_updateLinkStats(j, tStep, aDate); | |
| 472 | } | ||
| 473 | |||
| 474 | // --- update count of time steps taken after reporting begins | ||
| 475 | 988013 | ReportStepCount++; | |
| 476 | 988013 | RoutingTimeSpan += tStep; | |
| 477 | |||
| 478 | // --- update max. system outfall flow | ||
| 479 |
2/2✓ Branch 0 taken 921386 times.
✓ Branch 1 taken 66627 times.
|
988013 | MaxOutfallFlow = MAX(MaxOutfallFlow, SysOutfallFlow); |
| 480 | } | ||
| 481 | |||
| 482 | //============================================================================= | ||
| 483 | |||
| 484 | 988013 | void stats_updateTimeStepStats(double tStep, int trialsCount, int steadyState) | |
| 485 | // | ||
| 486 | // Input: tStep = current flow routing time step (sec) | ||
| 487 | // trialsCount = number of trials used to solve routing | ||
| 488 | // steadyState = TRUE if steady flow conditions exist | ||
| 489 | // Output: none | ||
| 490 | // Purpose: updates flow routing time step statistics. | ||
| 491 | // | ||
| 492 | { | ||
| 493 | int j; | ||
| 494 | |||
| 495 | // --- update time step stats if not in steady state | ||
| 496 | 988013 | TimeStepStats.steadyStateTime += steadyState * tStep; | |
| 497 |
1/2✓ Branch 0 taken 988013 times.
✗ Branch 1 not taken.
|
988013 | if (steadyState == FALSE) |
| 498 | { | ||
| 499 | // --- skip initial time step for min. value) | ||
| 500 |
2/2✓ Branch 0 taken 987974 times.
✓ Branch 1 taken 39 times.
|
988013 | if (OldRoutingTime > 0) |
| 501 | { | ||
| 502 |
2/2✓ Branch 0 taken 987739 times.
✓ Branch 1 taken 235 times.
|
987974 | TimeStepStats.minTimeStep = MIN(TimeStepStats.minTimeStep, tStep); |
| 503 | |||
| 504 | // --- locate interval that logged time step falls in | ||
| 505 | // and update its count | ||
| 506 |
1/2✓ Branch 0 taken 991301 times.
✗ Branch 1 not taken.
|
991301 | for (j = 1; j < TIMELEVELS; j++) |
| 507 |
2/2✓ Branch 0 taken 987974 times.
✓ Branch 1 taken 3327 times.
|
991301 | if (tStep >= TimeStepStats.timeStepIntervals[j]) |
| 508 | { | ||
| 509 | 987974 | TimeStepStats.timeStepCounts[j]++; | |
| 510 | 987974 | break; | |
| 511 | } | ||
| 512 | } | ||
| 513 |
2/2✓ Branch 0 taken 987948 times.
✓ Branch 1 taken 65 times.
|
988013 | TimeStepStats.maxTimeStep = MAX(TimeStepStats.maxTimeStep, tStep); |
| 514 | 988013 | TimeStepStats.routingTime += tStep; | |
| 515 | 988013 | TimeStepStats.timeStepCount++; | |
| 516 | 988013 | TimeStepStats.trialsCount += trialsCount; | |
| 517 | } | ||
| 518 | 988013 | } | |
| 519 | |||
| 520 | //============================================================================= | ||
| 521 | |||
| 522 | 189152 | void stats_updateCriticalTimeCount(int node, int link) | |
| 523 | // | ||
| 524 | // Input: node = node index | ||
| 525 | // link = link index | ||
| 526 | // Output: none | ||
| 527 | // Purpose: updates count of times a node or link was time step-critical. | ||
| 528 | // | ||
| 529 | { | ||
| 530 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 189152 times.
|
189152 | if ( node >= 0 ) NodeStats[node].timeCourantCritical += 1.0; |
| 531 |
2/2✓ Branch 0 taken 20361 times.
✓ Branch 1 taken 168791 times.
|
189152 | else if ( link >= 0 ) LinkStats[link].timeCourantCritical += 1.0; |
| 532 | 189152 | } | |
| 533 | |||
| 534 | //============================================================================= | ||
| 535 | |||
| 536 | 1824857 | void stats_updateConvergenceStats(int node, int converged) | |
| 537 | { | ||
| 538 |
2/2✓ Branch 0 taken 127716 times.
✓ Branch 1 taken 1697141 times.
|
1824857 | if (converged == FALSE) NodeStats[node].nonConvergedCount++; |
| 539 | 1824857 | } | |
| 540 | |||
| 541 | //============================================================================= | ||
| 542 | |||
| 543 | 37851987 | void stats_updateNodeStats(int j, double tStep, DateTime aDate) | |
| 544 | // | ||
| 545 | // Input: j = node index | ||
| 546 | // tStep = routing time step (sec) | ||
| 547 | // aDate = current date/time | ||
| 548 | // Output: none | ||
| 549 | // Purpose: updates flow statistics for a node. | ||
| 550 | // | ||
| 551 | { | ||
| 552 | int k, p; | ||
| 553 | 37851987 | double newVolume = Node[j].newVolume; | |
| 554 | 37851987 | double newDepth = Node[j].newDepth; | |
| 555 |
4/4✓ Branch 0 taken 1078120 times.
✓ Branch 1 taken 36773867 times.
✓ Branch 2 taken 749574 times.
✓ Branch 3 taken 328546 times.
|
37851987 | int canPond = (AllowPonding && Node[j].pondedArea > 0.0); |
| 556 | |||
| 557 | // --- update depth statistics | ||
| 558 | 37851987 | NodeStats[j].avgDepth += newDepth; | |
| 559 |
2/2✓ Branch 0 taken 6591284 times.
✓ Branch 1 taken 31260703 times.
|
37851987 | if ( newDepth > NodeStats[j].maxDepth ) |
| 560 | { | ||
| 561 | 6591284 | NodeStats[j].maxDepth = newDepth; | |
| 562 | 6591284 | NodeStats[j].maxDepthDate = aDate; | |
| 563 | } | ||
| 564 | |||
| 565 | // --- update flooding, ponding, and surcharge statistics | ||
| 566 |
2/2✓ Branch 0 taken 36585373 times.
✓ Branch 1 taken 1266614 times.
|
37851987 | if ( Node[j].type != OUTFALL ) |
| 567 | { | ||
| 568 |
4/4✓ Branch 0 taken 36497100 times.
✓ Branch 1 taken 88273 times.
✓ Branch 2 taken 37764 times.
✓ Branch 3 taken 36459336 times.
|
36585373 | if ( newVolume > Node[j].fullVolume || Node[j].overflow > 0.0 ) |
| 569 | { | ||
| 570 | 126037 | NodeStats[j].timeFlooded += tStep; | |
| 571 | 126037 | NodeStats[j].volFlooded += Node[j].overflow * tStep; | |
| 572 |
2/2✓ Branch 0 taken 88273 times.
✓ Branch 1 taken 37764 times.
|
214310 | if ( canPond ) NodeStats[j].maxPondedVol = |
| 573 |
2/2✓ Branch 0 taken 61258 times.
✓ Branch 1 taken 27015 times.
|
88273 | MAX(NodeStats[j].maxPondedVol, |
| 574 | (newVolume - Node[j].fullVolume)); | ||
| 575 | } | ||
| 576 | |||
| 577 | // --- for dynamic wave routing, classify a node as | ||
| 578 | // surcharged if its water level exceeds its crown elev. | ||
| 579 |
2/2✓ Branch 0 taken 24591034 times.
✓ Branch 1 taken 11994339 times.
|
36585373 | if (RouteModel == DW) |
| 580 | { | ||
| 581 |
3/4✓ Branch 0 taken 129090 times.
✓ Branch 1 taken 24461944 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 129090 times.
|
24591034 | if ((Node[j].type != STORAGE || Node[j].surDepth > 0.0) && |
| 582 |
2/2✓ Branch 0 taken 595484 times.
✓ Branch 1 taken 23866460 times.
|
24461944 | newDepth + Node[j].invertElev + FUDGE >= Node[j].crownElev) |
| 583 | { | ||
| 584 | 595484 | NodeStats[j].timeSurcharged += tStep; | |
| 585 | } | ||
| 586 | } | ||
| 587 | } | ||
| 588 | |||
| 589 | // --- update storage statistics | ||
| 590 |
2/2✓ Branch 0 taken 143130 times.
✓ Branch 1 taken 37708857 times.
|
37851987 | if ( Node[j].type == STORAGE ) |
| 591 | { | ||
| 592 | 143130 | k = Node[j].subIndex; | |
| 593 | 143130 | StorageStats[k].avgVol += newVolume; | |
| 594 | 143130 | StorageStats[k].evapLosses += | |
| 595 | 143130 | Storage[Node[j].subIndex].evapLoss; | |
| 596 | 143130 | StorageStats[k].exfilLosses += | |
| 597 | 143130 | Storage[Node[j].subIndex].exfilLoss; | |
| 598 | |||
| 599 |
1/2✓ Branch 0 taken 143130 times.
✗ Branch 1 not taken.
|
143130 | newVolume = MIN(newVolume, Node[j].fullVolume); |
| 600 |
2/2✓ Branch 0 taken 35858 times.
✓ Branch 1 taken 107272 times.
|
143130 | if ( newVolume > StorageStats[k].maxVol ) |
| 601 | { | ||
| 602 | 35858 | StorageStats[k].maxVol = newVolume; | |
| 603 | 35858 | StorageStats[k].maxVolDate = aDate; | |
| 604 | } | ||
| 605 |
2/2✓ Branch 0 taken 114851 times.
✓ Branch 1 taken 28279 times.
|
143130 | StorageStats[k].maxFlow = MAX(StorageStats[k].maxFlow, Node[j].outflow); |
| 606 | } | ||
| 607 | |||
| 608 | // --- update outfall statistics | ||
| 609 |
2/2✓ Branch 0 taken 1266614 times.
✓ Branch 1 taken 36585373 times.
|
37851987 | if ( Node[j].type == OUTFALL ) |
| 610 | { | ||
| 611 | 1266614 | k = Node[j].subIndex; | |
| 612 |
2/2✓ Branch 0 taken 548361 times.
✓ Branch 1 taken 718253 times.
|
1266614 | if ( Node[j].inflow >= MIN_RUNOFF_FLOW ) |
| 613 | { | ||
| 614 | 548361 | OutfallStats[k].avgFlow += Node[j].inflow; | |
| 615 |
2/2✓ Branch 0 taken 406281 times.
✓ Branch 1 taken 142080 times.
|
548361 | OutfallStats[k].maxFlow = MAX(OutfallStats[k].maxFlow, Node[j].inflow); |
| 616 | 548361 | OutfallStats[k].totalPeriods++; | |
| 617 | } | ||
| 618 |
2/2✓ Branch 0 taken 436529 times.
✓ Branch 1 taken 1266614 times.
|
1703143 | for (p=0; p<Nobjects[POLLUT]; p++) |
| 619 | { | ||
| 620 | 436529 | OutfallStats[k].totalLoad[p] += | |
| 621 | 436529 | Node[j].inflow * Node[j].newQual[p] * tStep; | |
| 622 | } | ||
| 623 | 1266614 | SysOutfallFlow += Node[j].inflow; | |
| 624 | } | ||
| 625 | |||
| 626 | // --- update inflow statistics | ||
| 627 | 37851987 | NodeStats[j].totLatFlow += | |
| 628 | 37851987 | ((Node[j].oldLatFlow + Node[j].newLatFlow) * 0.5 * tStep ); | |
| 629 |
2/2✓ Branch 0 taken 286715 times.
✓ Branch 1 taken 37565272 times.
|
37851987 | if ( fabs(Node[j].newLatFlow) > fabs(NodeStats[j].maxLatFlow) ) |
| 630 | 286715 | NodeStats[j].maxLatFlow = Node[j].newLatFlow; | |
| 631 |
2/2✓ Branch 0 taken 5834738 times.
✓ Branch 1 taken 32017249 times.
|
37851987 | if ( Node[j].inflow > NodeStats[j].maxInflow ) |
| 632 | { | ||
| 633 | 5834738 | NodeStats[j].maxInflow = Node[j].inflow; | |
| 634 | 5834738 | NodeStats[j].maxInflowDate = aDate; | |
| 635 | } | ||
| 636 | |||
| 637 | // --- update overflow statistics | ||
| 638 |
2/2✓ Branch 0 taken 11718 times.
✓ Branch 1 taken 37840269 times.
|
37851987 | if ( Node[j].overflow > NodeStats[j].maxOverflow ) |
| 639 | { | ||
| 640 | 11718 | NodeStats[j].maxOverflow = Node[j].overflow; | |
| 641 | 11718 | NodeStats[j].maxOverflowDate = aDate; | |
| 642 | } | ||
| 643 | 37851987 | } | |
| 644 | |||
| 645 | //============================================================================= | ||
| 646 | |||
| 647 | 37208897 | void stats_updateLinkStats(int j, double tStep, DateTime aDate) | |
| 648 | // | ||
| 649 | // Input: j = link index | ||
| 650 | // tStep = routing time step (sec) | ||
| 651 | // aDate = current date/time | ||
| 652 | // Output: none | ||
| 653 | // Purpose: updates flow statistics for a link. | ||
| 654 | // | ||
| 655 | { | ||
| 656 | int k; | ||
| 657 | double q, v; | ||
| 658 | double dq; | ||
| 659 | |||
| 660 | // --- update max. flow | ||
| 661 | 37208897 | dq = Link[j].newFlow - Link[j].oldFlow; | |
| 662 | 37208897 | q = fabs(Link[j].newFlow); | |
| 663 |
2/2✓ Branch 0 taken 6043513 times.
✓ Branch 1 taken 31165384 times.
|
37208897 | if ( q > LinkStats[j].maxFlow ) |
| 664 | { | ||
| 665 | 6043513 | LinkStats[j].maxFlow = q; | |
| 666 | 6043513 | LinkStats[j].maxFlowDate = aDate; | |
| 667 | } | ||
| 668 | |||
| 669 | // --- update max. velocity | ||
| 670 | 37208897 | v = link_getVelocity(j, q, Link[j].newDepth); | |
| 671 |
2/2✓ Branch 0 taken 4558286 times.
✓ Branch 1 taken 32650611 times.
|
37208897 | if ( v > LinkStats[j].maxVeloc ) |
| 672 | { | ||
| 673 | 4558286 | LinkStats[j].maxVeloc = v; | |
| 674 | } | ||
| 675 | |||
| 676 | // --- update max. depth | ||
| 677 |
2/2✓ Branch 0 taken 6937265 times.
✓ Branch 1 taken 30271632 times.
|
37208897 | if ( Link[j].newDepth > LinkStats[j].maxDepth ) |
| 678 | { | ||
| 679 | 6937265 | LinkStats[j].maxDepth = Link[j].newDepth; | |
| 680 | } | ||
| 681 | |||
| 682 |
2/2✓ Branch 0 taken 84753 times.
✓ Branch 1 taken 37124144 times.
|
37208897 | if ( Link[j].type == PUMP ) |
| 683 | { | ||
| 684 |
2/2✓ Branch 0 taken 54040 times.
✓ Branch 1 taken 30713 times.
|
84753 | if ( q >= Link[j].qFull ) |
| 685 | 54040 | LinkStats[j].timeFullFlow += tStep; | |
| 686 |
2/2✓ Branch 0 taken 70325 times.
✓ Branch 1 taken 14428 times.
|
84753 | if ( q > MIN_RUNOFF_FLOW ) |
| 687 | { | ||
| 688 | 70325 | k = Link[j].subIndex; | |
| 689 |
1/2✓ Branch 0 taken 70325 times.
✗ Branch 1 not taken.
|
70325 | PumpStats[k].minFlow = MIN(PumpStats[k].minFlow, q); |
| 690 | 70325 | PumpStats[k].maxFlow = LinkStats[j].maxFlow; | |
| 691 | 70325 | PumpStats[k].avgFlow += q; | |
| 692 | 70325 | PumpStats[k].volume += q*tStep; | |
| 693 | 70325 | PumpStats[k].utilized += tStep; | |
| 694 | 70325 | PumpStats[k].energy += link_getPower(j)*tStep/3600.0; | |
| 695 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 70325 times.
|
70325 | if ( Link[j].flowClass == DN_DRY ) |
| 696 | ✗ | PumpStats[k].offCurveLow += tStep; | |
| 697 |
2/2✓ Branch 0 taken 11374 times.
✓ Branch 1 taken 58951 times.
|
70325 | if ( Link[j].flowClass == UP_DRY ) |
| 698 | 11374 | PumpStats[k].offCurveHigh += tStep; | |
| 699 |
2/2✓ Branch 0 taken 26 times.
✓ Branch 1 taken 70299 times.
|
70325 | if ( Link[j].oldFlow < MIN_RUNOFF_FLOW ) |
| 700 | 26 | PumpStats[k].startUps++; | |
| 701 | 70325 | PumpStats[k].totalPeriods++; | |
| 702 | 70325 | LinkStats[j].timeSurcharged += tStep; | |
| 703 | 70325 | LinkStats[j].timeFullUpstream += tStep; | |
| 704 | 70325 | LinkStats[j].timeFullDnstream += tStep; | |
| 705 | } | ||
| 706 | } | ||
| 707 |
2/2✓ Branch 0 taken 36789022 times.
✓ Branch 1 taken 335122 times.
|
37124144 | else if ( Link[j].type == CONDUIT ) |
| 708 | { | ||
| 709 | // --- update time under normal flow & inlet control | ||
| 710 |
2/2✓ Branch 0 taken 11125323 times.
✓ Branch 1 taken 25663699 times.
|
36789022 | if ( Link[j].normalFlow ) LinkStats[j].timeNormalFlow += tStep; |
| 711 |
2/2✓ Branch 0 taken 16941 times.
✓ Branch 1 taken 36772081 times.
|
36789022 | if ( Link[j].inletControl ) LinkStats[j].timeInletControl += tStep; |
| 712 | |||
| 713 | // --- update flow classification distribution | ||
| 714 | 36789022 | k = Link[j].flowClass; | |
| 715 |
2/4✓ Branch 0 taken 36789022 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36789022 times.
✗ Branch 3 not taken.
|
36789022 | if ( k >= 0 && k < MAX_FLOW_CLASSES ) |
| 716 | { | ||
| 717 | 36789022 | LinkStats[j].timeInFlowClass[k] += tStep; | |
| 718 | } | ||
| 719 | |||
| 720 | // --- update time conduit is full | ||
| 721 | 36789022 | k = Link[j].subIndex; | |
| 722 |
2/2✓ Branch 0 taken 233377 times.
✓ Branch 1 taken 36555645 times.
|
36789022 | if ( q >= Link[j].qFull * (double)Conduit[k].barrels ) |
| 723 | 233377 | LinkStats[j].timeFullFlow += tStep; | |
| 724 |
2/2✓ Branch 0 taken 76504 times.
✓ Branch 1 taken 36712518 times.
|
36789022 | if ( Conduit[k].capacityLimited ) |
| 725 | 76504 | LinkStats[j].timeCapacityLimited += tStep; | |
| 726 | |||
| 727 |
4/4✓ Branch 0 taken 345988 times.
✓ Branch 1 taken 119649 times.
✓ Branch 2 taken 864493 times.
✓ Branch 3 taken 35458892 times.
|
36789022 | switch (Conduit[k].fullState) |
| 728 | { | ||
| 729 | 345988 | case ALL_FULL: | |
| 730 | 345988 | LinkStats[j].timeSurcharged += tStep; | |
| 731 | 345988 | LinkStats[j].timeFullUpstream += tStep; | |
| 732 | 345988 | LinkStats[j].timeFullDnstream += tStep; | |
| 733 | 345988 | break; | |
| 734 | 119649 | case UP_FULL: | |
| 735 | 119649 | LinkStats[j].timeFullUpstream += tStep; | |
| 736 | 119649 | break; | |
| 737 | 864493 | case DN_FULL: | |
| 738 | 864493 | LinkStats[j].timeFullDnstream += tStep; | |
| 739 | } | ||
| 740 | |||
| 741 | // --- update max. degree filled for streets | ||
| 742 |
2/2✓ Branch 0 taken 6328 times.
✓ Branch 1 taken 36782694 times.
|
36789022 | if (Link[j].xsect.type == STREET_XSECT) |
| 743 | 6328 | LinkStats[j].maxStreetFilled = | |
| 744 |
2/2✓ Branch 1 taken 1692 times.
✓ Branch 2 taken 4636 times.
|
6328 | MAX(LinkStats[j].maxStreetFilled, street_getExtentFilled(j)); |
| 745 | } | ||
| 746 | |||
| 747 | // --- update flow turn count | ||
| 748 | 37208897 | k = LinkStats[j].flowTurnSign; | |
| 749 |
2/2✓ Branch 0 taken 12628995 times.
✓ Branch 1 taken 24579902 times.
|
37208897 | LinkStats[j].flowTurnSign = SGN(dq); |
| 750 |
4/4✓ Branch 0 taken 3241688 times.
✓ Branch 1 taken 33967209 times.
✓ Branch 2 taken 85125 times.
✓ Branch 3 taken 3156563 times.
|
37208897 | if ( fabs(dq) > 0.001 && k * LinkStats[j].flowTurnSign < 0 ) |
| 751 | 85125 | LinkStats[j].flowTurns++; | |
| 752 | 37208897 | } | |
| 753 | |||
| 754 | //============================================================================= | ||
| 755 | |||
| 756 | 48 | void stats_findMaxStats() | |
| 757 | // | ||
| 758 | // Input: none | ||
| 759 | // Output: none | ||
| 760 | // Purpose: finds nodes & links with highest mass balance errors | ||
| 761 | // & highest times Courant time-step critical. | ||
| 762 | // | ||
| 763 | { | ||
| 764 | int j; | ||
| 765 | double x, z; | ||
| 766 | double stepCount; | ||
| 767 | |||
| 768 | // --- initialize max. stats arrays | ||
| 769 |
2/2✓ Branch 0 taken 240 times.
✓ Branch 1 taken 48 times.
|
288 | for (j=0; j<MAX_STATS; j++) |
| 770 | { | ||
| 771 | 240 | MaxMassBalErrs[j].objType = NODE; | |
| 772 | 240 | MaxMassBalErrs[j].index = -1; | |
| 773 | 240 | MaxMassBalErrs[j].value = -1.0; | |
| 774 | 240 | MaxCourantCrit[j].index = -1; | |
| 775 | 240 | MaxCourantCrit[j].value = -1.0; | |
| 776 | 240 | MaxFlowTurns[j].index = -1; | |
| 777 | 240 | MaxFlowTurns[j].value = -1.0; | |
| 778 | 240 | MaxNonConverged[j].index = -1; | |
| 779 | 240 | MaxNonConverged[j].value = 0.0; | |
| 780 | } | ||
| 781 | |||
| 782 | // --- find links with most flow turns during reporting period | ||
| 783 |
2/2✓ Branch 0 taken 42 times.
✓ Branch 1 taken 6 times.
|
48 | if ( ReportStepCount > 2 ) |
| 784 | { | ||
| 785 | 42 | stepCount = ReportStepCount; | |
| 786 | 42 | z = 100.0 / (2./3. * (stepCount - 2.)); | |
| 787 |
2/2✓ Branch 0 taken 4706 times.
✓ Branch 1 taken 42 times.
|
4748 | for (j=0; j<Nobjects[LINK]; j++) |
| 788 | { | ||
| 789 | 4706 | x = LinkStats[j].flowTurns * z; | |
| 790 | 4706 | stats_updateMaxStats(MaxFlowTurns, LINK, j, x); | |
| 791 | } | ||
| 792 | } | ||
| 793 | |||
| 794 | // --- find nodes with largest mass balance errors | ||
| 795 |
2/2✓ Branch 0 taken 10173 times.
✓ Branch 1 taken 48 times.
|
10221 | for (j=0; j<Nobjects[NODE]; j++) |
| 796 | { | ||
| 797 | // --- skip terminal nodes and nodes with negligible inflow | ||
| 798 |
2/2✓ Branch 0 taken 1734 times.
✓ Branch 1 taken 8439 times.
|
10173 | if ( Node[j].degree <= 0 ) continue; |
| 799 |
2/2✓ Branch 0 taken 4624 times.
✓ Branch 1 taken 3815 times.
|
8439 | if ( NodeInflow[j] <= 0.1 ) continue; |
| 800 | |||
| 801 | // --- evaluate mass balance error | ||
| 802 | // (Note: NodeInflow & NodeOutflow include any initial and final | ||
| 803 | // stored volumes, respectively). | ||
| 804 |
1/2✓ Branch 0 taken 3815 times.
✗ Branch 1 not taken.
|
3815 | if ( NodeInflow[j] > 0.0 ) |
| 805 | 3815 | x = 1.0 - NodeOutflow[j] / NodeInflow[j]; | |
| 806 | ✗ | else if ( NodeOutflow[j] > 0.0 ) x = -1.0; | |
| 807 | ✗ | else x = 0.0; | |
| 808 | 3815 | stats_updateMaxStats(MaxMassBalErrs, NODE, j, 100.0*x); | |
| 809 | } | ||
| 810 | |||
| 811 | // --- following stats apply to all (startup + reporting) time periods | ||
| 812 | 48 | stepCount = TimeStepStats.timeStepCount; | |
| 813 | |||
| 814 | // --- find nodes with highest nonconvergence frequency | ||
| 815 |
2/2✓ Branch 0 taken 35 times.
✓ Branch 1 taken 13 times.
|
48 | if ( RouteModel == DW ) |
| 816 |
2/2✓ Branch 0 taken 10088 times.
✓ Branch 1 taken 35 times.
|
10123 | for (j = 0; j < Nobjects[NODE]; j++) |
| 817 | 10088 | stats_updateMaxStats(MaxNonConverged, NODE, j, | |
| 818 | 10088 | NodeStats[j].nonConvergedCount / stepCount); | |
| 819 | |||
| 820 | // --- stop if not using a variable time step | ||
| 821 |
4/4✓ Branch 0 taken 35 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 30 times.
|
48 | if ( RouteModel != DW || CourantFactor == 0.0 ) return; |
| 822 | |||
| 823 | // --- find nodes most frequently Courant critical | ||
| 824 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 24 times.
|
30 | if ( stepCount == 0 ) return; |
| 825 |
2/2✓ Branch 0 taken 4548 times.
✓ Branch 1 taken 24 times.
|
4572 | for (j=0; j<Nobjects[NODE]; j++) |
| 826 | { | ||
| 827 | 4548 | x = NodeStats[j].timeCourantCritical / stepCount; | |
| 828 | 4548 | stats_updateMaxStats(MaxCourantCrit, NODE, j, 100.0*x); | |
| 829 | } | ||
| 830 | |||
| 831 | // --- find links most frequently Courant critical | ||
| 832 |
2/2✓ Branch 0 taken 4608 times.
✓ Branch 1 taken 24 times.
|
4632 | for (j=0; j<Nobjects[LINK]; j++) |
| 833 | { | ||
| 834 | 4608 | x = LinkStats[j].timeCourantCritical / stepCount; | |
| 835 | 4608 | stats_updateMaxStats(MaxCourantCrit, LINK, j, 100.0*x); | |
| 836 | } | ||
| 837 | } | ||
| 838 | |||
| 839 | //============================================================================= | ||
| 840 | |||
| 841 | 27765 | void stats_updateMaxStats(TMaxStats maxStats[], int i, int j, double x) | |
| 842 | // | ||
| 843 | // Input: maxStats[] = array of critical statistics values | ||
| 844 | // i = object category (NODE or LINK) | ||
| 845 | // j = object index | ||
| 846 | // x = value of statistic for the object | ||
| 847 | // Output: none | ||
| 848 | // Purpose: updates the collection of most critical statistics | ||
| 849 | // | ||
| 850 | { | ||
| 851 | int k; | ||
| 852 | TMaxStats maxStats1, maxStats2; | ||
| 853 | 27765 | maxStats1.objType = i; | |
| 854 | 27765 | maxStats1.index = j; | |
| 855 | 27765 | maxStats1.value = x; | |
| 856 |
2/2✓ Branch 0 taken 138825 times.
✓ Branch 1 taken 27765 times.
|
166590 | for (k=0; k<MAX_STATS; k++) |
| 857 | { | ||
| 858 |
2/2✓ Branch 0 taken 836 times.
✓ Branch 1 taken 137989 times.
|
138825 | if ( fabs(maxStats1.value) > fabs(maxStats[k].value) ) |
| 859 | { | ||
| 860 | 836 | maxStats2 = maxStats[k]; | |
| 861 | 836 | maxStats[k] = maxStats1; | |
| 862 | 836 | maxStats1 = maxStats2; | |
| 863 | } | ||
| 864 | } | ||
| 865 | 27765 | } | |
| 866 |