GCC Code Coverage Report


Directory: src/solver/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 86.7% 397 / 0 / 458
Functions: 96.3% 26 / 0 / 27
Branches: 62.5% 168 / 0 / 269

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