GCC Code Coverage Report


Directory: src/solver/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 87.5% 349 / 0 / 399
Functions: 77.8% 14 / 0 / 18
Branches: 83.7% 164 / 0 / 196

output.c
Line Branch Exec Source
1 //-----------------------------------------------------------------------------
2 // output.c
3 //
4 // Project: EPA SWMM5
5 // Version: 5.2
6 // Date: 06/01/22 (Build 5.2.1)
7 // Author: L. Rossman
8 //
9 // Binary output file access functions.
10 //
11 // Update History
12 // ==============
13 // Build 5.1.008:
14 // - Possible divide by zero for reported system wide variables avoided.
15 // - Updating of maximum node depth at reporting times added.
16 // Build 5.1.010:
17 // - Potentional ET added to list of system-wide variables saved to file.
18 // Build 5.1.013:
19 // - Names NsubcatchVars, NnodeVars & NlinkVars replaced with
20 // NumSubcatchVars, NumNodeVars & NumLinkVars
21 // - Support added for saving average node & link routing results to
22 // binary file in each reporting period.
23 // Build 5.1.014:
24 // - Incorrect loop limit fixed in function output_saveAvgResults.
25 // Build 5.2.0:
26 // - Changed how time step averaged flow is computed.
27 // - Object's rptFlag changed to record its index in output file.
28 // - Large file support added.
29 // Build5.2.1:
30 // - Corrects the definition of F_OFF for non-Microsoft C/C++ compilers.
31 //-----------------------------------------------------------------------------
32 #define _CRT_SECURE_NO_DEPRECATE
33
34 // Large File Support
35 #ifdef _MSC_VER // Windows (32-bit and 64-bit)
36 #define F_OFF __int64
37 #define F_SEEK _fseeki64
38 #else // Other platforms
39 #define F_OFF off_t
40 #define F_SEEK fseeko
41 #endif
42
43 #include <stdlib.h>
44 #include <string.h>
45 #include <math.h>
46 #include "headers.h"
47
48 // Definition of 4-byte integer, 4-byte real and 8-byte real types
49 #define INT4 int
50 #define REAL4 float
51 #define REAL8 double
52
53 enum InputDataType {INPUT_TYPE_CODE, INPUT_AREA, INPUT_INVERT, INPUT_MAX_DEPTH,
54 INPUT_OFFSET, INPUT_LENGTH};
55
56 typedef struct
57 {
58 REAL4* xAvg;
59 } TAvgResults;
60
61 //-----------------------------------------------------------------------------
62 // Shared variables
63 //-----------------------------------------------------------------------------
64 static F_OFF IDStartPos; // starting file position of ID names
65 static F_OFF InputStartPos; // starting file position of input data
66 static F_OFF OutputStartPos; // starting file position of output data
67 static F_OFF BytesPerPeriod; // bytes saved per simulation time period
68 static INT4 NumSubcatchVars; // number of subcatchment output variables
69 static INT4 NumNodeVars; // number of node output variables
70 static INT4 NumLinkVars; // number of link output variables
71 static INT4 NumSubcatch; // number of subcatchments reported on
72 static INT4 NumNodes; // number of nodes reported on
73 static INT4 NumLinks; // number of links reported on
74 static INT4 NumPolluts; // number of pollutants reported on
75
76 static REAL4 SysResults[MAX_SYS_RESULTS]; // values of system output vars.
77
78 static TAvgResults* AvgLinkResults;
79 static TAvgResults* AvgNodeResults;
80 static int Nsteps;
81
82 //-----------------------------------------------------------------------------
83 // Exportable variables (shared with report.c)
84 //-----------------------------------------------------------------------------
85 REAL4* SubcatchResults;
86 REAL4* NodeResults;
87 REAL4* LinkResults;
88
89
90 //-----------------------------------------------------------------------------
91 // Local functions
92 //-----------------------------------------------------------------------------
93 static void output_openOutFile(void);
94 static void output_saveID(char* id, FILE* file);
95 static void output_saveSubcatchResults(double reportTime, FILE* file);
96 static void output_saveNodeResults(double reportTime, FILE* file);
97 static void output_saveLinkResults(double reportTime, FILE* file);
98
99 static int output_openAvgResults(void);
100 static void output_closeAvgResults(void);
101 static void output_initAvgResults(void);
102 static void output_saveAvgResults(FILE* file);
103
104 //-----------------------------------------------------------------------------
105 // External functions (declared in funcs.h)
106 //-----------------------------------------------------------------------------
107 // output_open (called by swmm_start in swmm5.c)
108 // output_end (called by swmm_end in swmm5.c)
109 // output_close (called by swmm_close in swmm5.c)
110 // output_updateAvgResults (called by swmm_step in swmm5.c)
111 // output_saveResults (called by swmm_step in swmm5.c)
112 // output_checkFileSize (called by swmm_report)
113 // output_readDateTime (called by routines in report.c)
114 // output_readSubcatchResults (called by report_Subcatchments)
115 // output_readNodeResults (called by report_Nodes)
116 // output_readLinkResults (called by report_Links)
117
118
119 //=============================================================================
120
121 58 int output_open()
122 //
123 // Input: none
124 // Output: returns an error code
125 // Purpose: writes basic project data to binary output file.
126 //
127 {
128 int j;
129 int m;
130 INT4 k;
131 REAL4 x;
132 REAL8 z;
133 F_OFF numResults;
134
135 // --- open binary output file
136 58 output_openOutFile();
137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if ( ErrorCode ) return ErrorCode;
138
139 // --- ignore pollutants if no water quality analsis performed
140
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 56 times.
58 if ( IgnoreQuality ) NumPolluts = 0;
141 56 else NumPolluts = Nobjects[POLLUT];
142
143 // --- subcatchment results consist of Rainfall, Snowdepth, Evap,
144 // Infil, Runoff, GW Flow, GW Elev, GW Sat, and Washoff
145 58 NumSubcatchVars = MAX_SUBCATCH_RESULTS - 1 + NumPolluts;
146
147 // --- node results consist of Depth, Head, Volume, Lateral Inflow,
148 // Total Inflow, Overflow and Quality
149 58 NumNodeVars = MAX_NODE_RESULTS - 1 + NumPolluts;
150
151 // --- link results consist of Depth, Flow, Velocity, Volume,
152 // Capacity and Quality
153 58 NumLinkVars = MAX_LINK_RESULTS - 1 + NumPolluts;
154
155 // --- get number of objects reported on
156 58 NumSubcatch = 0;
157 58 NumNodes = 0;
158 58 NumLinks = 0;
159
3/4
✓ Branch 0 taken 2393 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2393 times.
✓ Branch 3 taken 58 times.
2451 for (j=0; j<Nobjects[SUBCATCH]; j++) if (Subcatch[j].rptFlag) NumSubcatch++;
160
4/4
✓ Branch 0 taken 817 times.
✓ Branch 1 taken 9366 times.
✓ Branch 2 taken 10183 times.
✓ Branch 3 taken 58 times.
10241 for (j=0; j<Nobjects[NODE]; j++) if (Node[j].rptFlag) NumNodes++;
161
4/4
✓ Branch 0 taken 1220 times.
✓ Branch 1 taken 9288 times.
✓ Branch 2 taken 10508 times.
✓ Branch 3 taken 58 times.
10566 for (j=0; j<Nobjects[LINK]; j++) if (Link[j].rptFlag) NumLinks++;
162
163 // --- find size of results saved in each time period
164 58 numResults = ((F_OFF)NumSubcatch * (F_OFF)NumSubcatchVars)
165 58 + ((F_OFF)NumNodes * (F_OFF)NumNodeVars)
166 58 + ((F_OFF)NumLinks * (F_OFF)NumLinkVars) + MAX_SYS_RESULTS;
167 58 BytesPerPeriod = sizeof(REAL8) + (numResults * sizeof(REAL4));
168 58 Nperiods = 0;
169
170 58 SubcatchResults = NULL;
171 58 NodeResults = NULL;
172 58 LinkResults = NULL;
173 58 SubcatchResults = (REAL4 *) calloc(NumSubcatchVars, sizeof(REAL4));
174 58 NodeResults = (REAL4 *) calloc(NumNodeVars, sizeof(REAL4));
175 58 LinkResults = (REAL4 *) calloc(NumLinkVars, sizeof(REAL4));
176
3/6
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 58 times.
58 if ( !SubcatchResults || !NodeResults || !LinkResults )
177 {
178 report_writeErrorMsg(ERR_MEMORY, "");
179 return ErrorCode;
180 }
181
182 // --- allocate memory to store average node & link results per period
183 58 AvgNodeResults = NULL;
184 58 AvgLinkResults = NULL;
185
3/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 57 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
58 if ( RptFlags.averages && !output_openAvgResults() )
186 {
187 report_writeErrorMsg(ERR_MEMORY, "");
188 return ErrorCode;
189 }
190
191 58 F_SEEK(Fout.file, 0, SEEK_SET);
192 58 k = MAGICNUMBER;
193 58 fwrite(&k, sizeof(INT4), 1, Fout.file); // Magic number
194 58 k = VERSION;
195 58 fwrite(&k, sizeof(INT4), 1, Fout.file); // Version number
196 58 k = FlowUnits;
197 58 fwrite(&k, sizeof(INT4), 1, Fout.file); // Flow units
198 58 k = NumSubcatch;
199 58 fwrite(&k, sizeof(INT4), 1, Fout.file); // # subcatchments
200 58 k = NumNodes;
201 58 fwrite(&k, sizeof(INT4), 1, Fout.file); // # nodes
202 58 k = NumLinks;
203 58 fwrite(&k, sizeof(INT4), 1, Fout.file); // # links
204 58 k = NumPolluts;
205 58 fwrite(&k, sizeof(INT4), 1, Fout.file); // # pollutants
206
207 // --- save ID names of subcatchments, nodes, links, & pollutants
208 58 IDStartPos = ftell(Fout.file);
209
2/2
✓ Branch 0 taken 2393 times.
✓ Branch 1 taken 58 times.
2451 for (j=0; j<Nobjects[SUBCATCH]; j++)
210 {
211
1/2
✓ Branch 0 taken 2393 times.
✗ Branch 1 not taken.
2393 if ( Subcatch[j].rptFlag ) output_saveID(Subcatch[j].ID, Fout.file);
212 }
213
2/2
✓ Branch 0 taken 10183 times.
✓ Branch 1 taken 58 times.
10241 for (j=0; j<Nobjects[NODE]; j++)
214 {
215
2/2
✓ Branch 0 taken 817 times.
✓ Branch 1 taken 9366 times.
10183 if ( Node[j].rptFlag ) output_saveID(Node[j].ID, Fout.file);
216 }
217
2/2
✓ Branch 0 taken 10508 times.
✓ Branch 1 taken 58 times.
10566 for (j=0; j<Nobjects[LINK]; j++)
218 {
219
2/2
✓ Branch 0 taken 1220 times.
✓ Branch 1 taken 9288 times.
10508 if ( Link[j].rptFlag ) output_saveID(Link[j].ID, Fout.file);
220 }
221
2/2
✓ Branch 1 taken 47 times.
✓ Branch 2 taken 58 times.
105 for (j=0; j<NumPolluts; j++) output_saveID(Pollut[j].ID, Fout.file);
222
223 // --- save codes of pollutant concentration units
224
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 58 times.
105 for (j=0; j<NumPolluts; j++)
225 {
226 47 k = Pollut[j].units;
227 47 fwrite(&k, sizeof(INT4), 1, Fout.file);
228 }
229
230 58 InputStartPos = ftell(Fout.file);
231
232 // --- save subcatchment area
233 58 k = 1;
234 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
235 58 k = INPUT_AREA;
236 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
237
2/2
✓ Branch 0 taken 2393 times.
✓ Branch 1 taken 58 times.
2451 for (j=0; j<Nobjects[SUBCATCH]; j++)
238 {
239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2393 times.
2393 if ( !Subcatch[j].rptFlag ) continue;
240 2393 SubcatchResults[0] = (REAL4)(Subcatch[j].area * UCF(LANDAREA));
241 2393 fwrite(&SubcatchResults[0], sizeof(REAL4), 1, Fout.file);
242 }
243
244 // --- save node type, invert, & max. depth
245 58 k = 3;
246 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
247 58 k = INPUT_TYPE_CODE;
248 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
249 58 k = INPUT_INVERT;
250 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
251 58 k = INPUT_MAX_DEPTH;
252 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
253
2/2
✓ Branch 0 taken 10183 times.
✓ Branch 1 taken 58 times.
10241 for (j=0; j<Nobjects[NODE]; j++)
254 {
255
2/2
✓ Branch 0 taken 9366 times.
✓ Branch 1 taken 817 times.
10183 if ( !Node[j].rptFlag ) continue;
256 817 k = Node[j].type;
257 817 NodeResults[0] = (REAL4)(Node[j].invertElev * UCF(LENGTH));
258 817 NodeResults[1] = (REAL4)(Node[j].fullDepth * UCF(LENGTH));
259 817 fwrite(&k, sizeof(INT4), 1, Fout.file);
260 817 fwrite(NodeResults, sizeof(REAL4), 2, Fout.file);
261 }
262
263 // --- save link type, offsets, max. depth, & length
264 58 k = 5;
265 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
266 58 k = INPUT_TYPE_CODE;
267 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
268 58 k = INPUT_OFFSET;
269 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
270 58 k = INPUT_OFFSET;
271 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
272 58 k = INPUT_MAX_DEPTH;
273 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
274 58 k = INPUT_LENGTH;
275 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
276
277
2/2
✓ Branch 0 taken 10508 times.
✓ Branch 1 taken 58 times.
10566 for (j=0; j<Nobjects[LINK]; j++)
278 {
279
2/2
✓ Branch 0 taken 9288 times.
✓ Branch 1 taken 1220 times.
10508 if ( !Link[j].rptFlag ) continue;
280 1220 k = Link[j].type;
281
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1214 times.
1220 if ( k == PUMP )
282 {
283
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 6 times.
30 for (m=0; m<4; m++) LinkResults[m] = 0.0f;
284 }
285 else
286 {
287 1214 LinkResults[0] = (REAL4)(Link[j].offset1 * UCF(LENGTH));
288 1214 LinkResults[1] = (REAL4)(Link[j].offset2 * UCF(LENGTH));
289
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 1185 times.
1214 if ( Link[j].direction < 0 )
290 {
291 29 x = LinkResults[0];
292 29 LinkResults[0] = LinkResults[1];
293 29 LinkResults[1] = x;
294 }
295
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1212 times.
1214 if ( k == OUTLET ) LinkResults[2] = 0.0f;
296 1212 else LinkResults[2] = (REAL4)(Link[j].xsect.yFull * UCF(LENGTH));
297
2/2
✓ Branch 0 taken 759 times.
✓ Branch 1 taken 455 times.
1214 if ( k == CONDUIT )
298 {
299 759 m = Link[j].subIndex;
300 759 LinkResults[3] = (REAL4)(Conduit[m].length * UCF(LENGTH));
301 }
302 455 else LinkResults[3] = 0.0f;
303 }
304 1220 fwrite(&k, sizeof(INT4), 1, Fout.file);
305 1220 fwrite(LinkResults, sizeof(REAL4), 4, Fout.file);
306 }
307
308 // --- save number & codes of subcatchment result variables
309 58 k = NumSubcatchVars;
310 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
311 58 k = SUBCATCH_RAINFALL;
312 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
313 58 k = SUBCATCH_SNOWDEPTH;
314 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
315 58 k = SUBCATCH_EVAP;
316 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
317 58 k = SUBCATCH_INFIL;
318 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
319 58 k = SUBCATCH_RUNOFF;
320 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
321 58 k = SUBCATCH_GW_FLOW;
322 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
323 58 k = SUBCATCH_GW_ELEV;
324 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
325 58 k = SUBCATCH_SOIL_MOIST;
326 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
327
328
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 58 times.
105 for (j=0; j<NumPolluts; j++)
329 {
330 47 k = SUBCATCH_WASHOFF + j;
331 47 fwrite(&k, sizeof(INT4), 1, Fout.file);
332 }
333
334 // --- save number & codes of node result variables
335 58 k = NumNodeVars;
336 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
337 58 k = NODE_DEPTH;
338 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
339 58 k = NODE_HEAD;
340 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
341 58 k = NODE_VOLUME;
342 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
343 58 k = NODE_LATFLOW;
344 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
345 58 k = NODE_INFLOW;
346 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
347 58 k = NODE_OVERFLOW;
348 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
349
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 58 times.
105 for (j=0; j<NumPolluts; j++)
350 {
351 47 k = NODE_QUAL + j;
352 47 fwrite(&k, sizeof(INT4), 1, Fout.file);
353 }
354
355 // --- save number & codes of link result variables
356 58 k = NumLinkVars;
357 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
358 58 k = LINK_FLOW;
359 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
360 58 k = LINK_DEPTH;
361 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
362 58 k = LINK_VELOCITY;
363 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
364 58 k = LINK_VOLUME;
365 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
366 58 k = LINK_CAPACITY;
367 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
368
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 58 times.
105 for (j=0; j<NumPolluts; j++)
369 {
370 47 k = LINK_QUAL + j;
371 47 fwrite(&k, sizeof(INT4), 1, Fout.file);
372 }
373
374 // --- save number & codes of system result variables
375 58 k = MAX_SYS_RESULTS;
376 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
377
2/2
✓ Branch 1 taken 870 times.
✓ Branch 2 taken 58 times.
928 for (k=0; k<MAX_SYS_RESULTS; k++) fwrite(&k, sizeof(INT4), 1, Fout.file);
378
379 // --- save starting report date & report step
380 // (if reporting start date > simulation start date then
381 // make saved starting report date one reporting period
382 // prior to the date of the first reported result)
383 58 z = (double)ReportStep/86400.0;
384
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 1 time.
58 if ( StartDateTime + z > ReportStart ) z = StartDateTime;
385 else
386 {
387 1 z = floor((ReportStart - StartDateTime)/z) - 1.0;
388 1 z = StartDateTime + z*(double)ReportStep/86400.0;
389 }
390 58 fwrite(&z, sizeof(REAL8), 1, Fout.file);
391 58 k = ReportStep;
392
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
58 if ( fwrite(&k, sizeof(INT4), 1, Fout.file) < 1)
393 {
394 report_writeErrorMsg(ERR_OUT_WRITE, "");
395 return ErrorCode;
396 }
397 58 OutputStartPos = ftell(Fout.file);
398 58 return ErrorCode;
399 }
400
401 //=============================================================================
402 /* DEPRECATED
403 void output_checkFileSize()
404 //
405 // Input: none
406 // Output: none
407 // Purpose: checks if the size of the binary output file will be too big
408 // to access using a file pointer variable for a 32-bit compile.
409 //
410 {
411 if ( RptFlags.subcatchments != NONE ||
412 RptFlags.nodes != NONE ||
413 RptFlags.links != NONE )
414 {
415 if (sizeof(void*) == 4 &&
416 (double)OutputStartPos + (double)BytesPerPeriod * TotalDuration
417 / 1000.0 / (double)ReportStep >= (double)MAXFILESIZE )
418 {
419 report_writeErrorMsg(ERR_OUT_SIZE, "");
420 }
421 }
422 }
423 */
424
425 //=============================================================================
426
427 58 void output_openOutFile()
428 //
429 // Input: none
430 // Output: none
431 // Purpose: opens a project's binary output file.
432 //
433 {
434 // --- close output file if already opened
435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (Fout.file != NULL) fclose(Fout.file);
436
437 // --- else if file name supplied then set file mode to SAVE
438
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 else if (strlen(Fout.name) != 0) Fout.mode = SAVE_FILE;
439
440 // --- otherwise set file mode to SCRATCH & generate a name
441 else
442 {
443 Fout.mode = SCRATCH_FILE;
444 getTempFileName(Fout.name);
445 }
446
447 // --- try to open the file
448
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
58 if ( (Fout.file = fopen(Fout.name, "w+b")) == NULL)
449 {
450 writecon(FMT14);
451 ErrorCode = ERR_OUT_FILE;
452 }
453 58 }
454
455 //=============================================================================
456
457 76552 void output_saveResults(double reportTime)
458 //
459 // Input: reportTime = elapsed simulation time (millisec)
460 // Output: none
461 // Purpose: writes computed results for current report time to binary file.
462 //
463 {
464 int i;
465 extern TRoutingTotals StepFlowTotals; // defined in massbal.c
466 76552 DateTime reportDate = getDateTime(reportTime);
467 REAL8 date;
468
469 // --- initialize system-wide results
470
2/2
✓ Branch 0 taken 743 times.
✓ Branch 1 taken 75809 times.
76552 if ( reportDate < ReportStart ) return;
471
2/2
✓ Branch 0 taken 1137135 times.
✓ Branch 1 taken 75809 times.
1212944 for (i=0; i<MAX_SYS_RESULTS; i++) SysResults[i] = 0.0f;
472
473 // --- save date corresponding to this elapsed reporting time
474 75809 date = reportDate;
475 75809 fwrite(&date, sizeof(REAL8), 1, Fout.file);
476
477 // --- save subcatchment results
478
2/2
✓ Branch 0 taken 15372 times.
✓ Branch 1 taken 60437 times.
75809 if (Nobjects[SUBCATCH] > 0)
479 15372 output_saveSubcatchResults(reportTime, Fout.file);
480
481 // --- save average routing results over reporting period if called for
482
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 75762 times.
75809 if ( RptFlags.averages ) output_saveAvgResults(Fout.file);
483
484 // --- otherwise save interpolated point routing results
485 else
486 {
487
1/2
✓ Branch 0 taken 75762 times.
✗ Branch 1 not taken.
75762 if (Nobjects[NODE] > 0)
488 75762 output_saveNodeResults(reportTime, Fout.file);
489
2/2
✓ Branch 0 taken 73050 times.
✓ Branch 1 taken 2712 times.
75762 if (Nobjects[LINK] > 0)
490 73050 output_saveLinkResults(reportTime, Fout.file);
491 }
492
493 // --- update & save system-wide flows
494 75809 SysResults[SYS_FLOODING] = (REAL4)(StepFlowTotals.flooding * UCF(FLOW));
495 75809 SysResults[SYS_OUTFLOW] = (REAL4)(StepFlowTotals.outflow * UCF(FLOW));
496 75809 SysResults[SYS_DWFLOW] = (REAL4)(StepFlowTotals.dwInflow * UCF(FLOW));
497 75809 SysResults[SYS_GWFLOW] = (REAL4)(StepFlowTotals.gwInflow * UCF(FLOW));
498 75809 SysResults[SYS_IIFLOW] = (REAL4)(StepFlowTotals.iiInflow * UCF(FLOW));
499 75809 SysResults[SYS_EXFLOW] = (REAL4)(StepFlowTotals.exInflow * UCF(FLOW));
500 75809 SysResults[SYS_INFLOW] = SysResults[SYS_RUNOFF] +
501 75809 SysResults[SYS_DWFLOW] +
502 75809 SysResults[SYS_GWFLOW] +
503 75809 SysResults[SYS_IIFLOW] +
504 75809 SysResults[SYS_EXFLOW];
505 75809 fwrite(SysResults, sizeof(REAL4), MAX_SYS_RESULTS, Fout.file);
506
507 // --- save outfall flows to interface file if called for
508
3/4
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 75737 times.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
75809 if ( Foutflows.mode == SAVE_FILE && !IgnoreRouting )
509 72 iface_saveOutletResults(reportDate, Foutflows.file);
510 75809 Nperiods++;
511 }
512
513 //=============================================================================
514
515 58 void output_end()
516 //
517 // Input: none
518 // Output: none
519 // Purpose: writes closing records to binary file.
520 //
521 {
522 INT4 k;
523 58 fwrite(&IDStartPos, sizeof(INT4), 1, Fout.file);
524 58 fwrite(&InputStartPos, sizeof(INT4), 1, Fout.file);
525 58 fwrite(&OutputStartPos, sizeof(INT4), 1, Fout.file);
526 58 k = Nperiods;
527 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
528 58 k = (INT4)ErrorCode;
529 58 fwrite(&k, sizeof(INT4), 1, Fout.file);
530 58 k = MAGICNUMBER;
531
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
58 if (fwrite(&k, sizeof(INT4), 1, Fout.file) < 1)
532 {
533 report_writeErrorMsg(ERR_OUT_WRITE, "");
534 }
535 58 }
536
537 //=============================================================================
538
539 58 void output_close()
540 //
541 // Input: none
542 // Output: none
543 // Purpose: frees memory used for accessing the binary file.
544 //
545 {
546
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(SubcatchResults);
547
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(NodeResults);
548
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(LinkResults);
549 58 output_closeAvgResults();
550 58 }
551
552 //=============================================================================
553
554 4477 void output_saveID(char* id, FILE* file)
555 //
556 // Input: id = name of an object
557 // file = ptr. to binary output file
558 // Output: none
559 // Purpose: writes an object's name to the binary output file.
560 //
561 {
562 4477 INT4 n = (INT4)strlen(id);
563 4477 fwrite(&n, sizeof(INT4), 1, file);
564 4477 fwrite(id, sizeof(char), n, file);
565 4477 }
566
567 //=============================================================================
568
569 15372 void output_saveSubcatchResults(double reportTime, FILE* file)
570 //
571 // Input: reportTime = elapsed simulation time (millisec)
572 // file = ptr. to binary output file
573 // Output: none
574 // Purpose: writes computed subcatchment results to binary file.
575 //
576 {
577 int j;
578 double f;
579 double area;
580 15372 REAL4 totalArea = 0.0f;
581 15372 DateTime reportDate = getDateTime(reportTime);
582
583 // --- update reported rainfall at each rain gage
584
2/2
✓ Branch 0 taken 15515 times.
✓ Branch 1 taken 15372 times.
30887 for ( j=0; j<Nobjects[GAGE]; j++ )
585 {
586 15515 gage_setReportRainfall(j, reportDate);
587 }
588
589 // --- find where current reporting time lies between latest runoff times
590 15372 f = (reportTime - OldRunoffTime) / (NewRunoffTime - OldRunoffTime);
591
592 // --- write subcatchment results to file
593
2/2
✓ Branch 0 taken 151584 times.
✓ Branch 1 taken 15372 times.
166956 for ( j=0; j<Nobjects[SUBCATCH]; j++)
594 {
595 // --- retrieve interpolated results for reporting time & write to file
596 151584 subcatch_getResults(j, f, SubcatchResults);
597
1/2
✓ Branch 0 taken 151584 times.
✗ Branch 1 not taken.
151584 if ( Subcatch[j].rptFlag )
598 151584 fwrite(SubcatchResults, sizeof(REAL4), NumSubcatchVars, file);
599
600 // --- update system-wide results
601 151584 area = Subcatch[j].area * UCF(LANDAREA);
602 151584 totalArea += (REAL4)area;
603 151584 SysResults[SYS_RAINFALL] +=
604 151584 (REAL4)(SubcatchResults[SUBCATCH_RAINFALL] * area);
605 151584 SysResults[SYS_SNOWDEPTH] +=
606 151584 (REAL4)(SubcatchResults[SUBCATCH_SNOWDEPTH] * area);
607 151584 SysResults[SYS_EVAP] +=
608 151584 (REAL4)(SubcatchResults[SUBCATCH_EVAP] * area);
609
2/2
✓ Branch 0 taken 48878 times.
✓ Branch 1 taken 102706 times.
151584 if ( Subcatch[j].groundwater ) SysResults[SYS_EVAP] +=
610 48878 (REAL4)(Subcatch[j].groundwater->evapLoss * UCF(EVAPRATE) * area);
611 151584 SysResults[SYS_INFIL] +=
612 151584 (REAL4)(SubcatchResults[SUBCATCH_INFIL] * area);
613 151584 SysResults[SYS_RUNOFF] += (REAL4)SubcatchResults[SUBCATCH_RUNOFF];
614 }
615
616 // --- normalize system-wide results to catchment area
617
1/2
✓ Branch 0 taken 15372 times.
✗ Branch 1 not taken.
15372 if ( totalArea > 0.0 )
618 {
619 15372 SysResults[SYS_EVAP] /= totalArea;
620 15372 SysResults[SYS_RAINFALL] /= totalArea;
621 15372 SysResults[SYS_SNOWDEPTH] /= totalArea;
622 15372 SysResults[SYS_INFIL] /= totalArea;
623 }
624
625 // --- update system temperature and PET
626
2/2
✓ Branch 0 taken 576 times.
✓ Branch 1 taken 14796 times.
15372 if ( UnitSystem == SI ) f = (5./9.) * (Temp.ta - 32.0);
627 14796 else f = Temp.ta;
628 15372 SysResults[SYS_TEMPERATURE] = (REAL4)f;
629 15372 f = Evap.rate * UCF(EVAPRATE);
630 15372 SysResults[SYS_PET] = (REAL4)f;
631
632 15372 }
633
634 //=============================================================================
635
636 75762 void output_saveNodeResults(double reportTime, FILE* file)
637 //
638 // Input: reportTime = elapsed simulation time (millisec)
639 // file = ptr. to binary output file
640 // Output: none
641 // Purpose: writes computed node results to binary file.
642 //
643 {
644 int j;
645
646 // --- find where current reporting time lies between latest routing times
647 75762 double f = (reportTime - OldRoutingTime) /
648 75762 (NewRoutingTime - OldRoutingTime);
649
650 // --- write node results to file
651
2/2
✓ Branch 0 taken 1930292 times.
✓ Branch 1 taken 75762 times.
2006054 for (j=0; j<Nobjects[NODE]; j++)
652 {
653 // --- retrieve interpolated results for reporting time & write to file
654 1930292 node_getResults(j, f, NodeResults);
655
2/2
✓ Branch 0 taken 1568474 times.
✓ Branch 1 taken 361818 times.
1930292 if ( Node[j].rptFlag )
656 1568474 fwrite(NodeResults, sizeof(REAL4), NumNodeVars, file);
657 1930292 stats_updateMaxNodeDepth(j, NodeResults[NODE_DEPTH]);
658
659 // --- update system-wide storage volume
660 1930292 SysResults[SYS_STORAGE] += NodeResults[NODE_VOLUME];
661 }
662 75762 }
663
664 //=============================================================================
665
666 73050 void output_saveLinkResults(double reportTime, FILE* file)
667 //
668 // Input: reportTime = elapsed simulation time (millisec)
669 // file = ptr. to binary output file
670 // Output: none
671 // Purpose: writes computed link results to binary file.
672 //
673 {
674 int j;
675 double f;
676 double z;
677
678 // --- find where current reporting time lies between latest routing times
679 73050 f = (reportTime - OldRoutingTime) / (NewRoutingTime - OldRoutingTime);
680
681 // --- write link results to file
682
2/2
✓ Branch 0 taken 1860467 times.
✓ Branch 1 taken 73050 times.
1933517 for (j=0; j<Nobjects[LINK]; j++)
683 {
684 // --- retrieve interpolated results for reporting time & write to file
685
2/2
✓ Branch 0 taken 1497821 times.
✓ Branch 1 taken 362646 times.
1860467 if (Link[j].rptFlag )
686 {
687 1497821 link_getResults(j, f, LinkResults);
688 1497821 fwrite(LinkResults, sizeof(REAL4), NumLinkVars, file);
689 }
690
691 // --- update system-wide results
692 1860467 z = ((1.0-f)*Link[j].oldVolume + f*Link[j].newVolume) * UCF(VOLUME);
693 1860467 SysResults[SYS_STORAGE] += (REAL4)z;
694 }
695 73050 }
696
697 //=============================================================================
698
699 void output_readDateTime(long period, DateTime* days)
700 //
701 // Input: period = index of reporting time period
702 // Output: days = date/time value
703 // Purpose: retrieves the date/time for a specific reporting period
704 // from the binary output file.
705 //
706 {
707 F_OFF p = period;
708 F_OFF bytePos = OutputStartPos + (p-1)*BytesPerPeriod;
709 F_SEEK(Fout.file, bytePos, SEEK_SET);
710 *days = NO_DATE;
711 fread(days, sizeof(REAL8), 1, Fout.file);
712 }
713
714 //=============================================================================
715
716 void output_readSubcatchResults(long period, int index)
717 //
718 // Input: period = index of reporting time period
719 // index = subcatchment index in binary output file
720 // Output: none
721 // Purpose: reads computed results for a subcatchment at a specific time
722 // period.
723 //
724 {
725 long offset = index*NumSubcatchVars;
726 F_OFF p = period;
727 F_OFF bytePos = OutputStartPos + (p-1)*BytesPerPeriod +
728 sizeof(REAL8) + (F_OFF)offset * sizeof(REAL4);
729 F_SEEK(Fout.file, bytePos, SEEK_SET);
730 fread(SubcatchResults, sizeof(REAL4), NumSubcatchVars, Fout.file);
731 }
732
733 //=============================================================================
734
735 void output_readNodeResults(long period, int index)
736 //
737 // Input: period = index of reporting time period
738 // index = node index in binary output file
739 // Output: none
740 // Purpose: reads computed results for a node at a specific time period.
741 //
742 {
743 long offset = NumSubcatch*NumSubcatchVars + index*NumNodeVars;
744 F_OFF p = period;
745 F_OFF bytePos = OutputStartPos + (p-1)*BytesPerPeriod +
746 sizeof(REAL8) + (F_OFF)offset * sizeof(REAL4);
747 F_SEEK(Fout.file, bytePos, SEEK_SET);
748 fread(NodeResults, sizeof(REAL4), NumNodeVars, Fout.file);
749 }
750
751 //=============================================================================
752
753 void output_readLinkResults(long period, int index)
754 //
755 // Input: period = index of reporting time period
756 // index = link index in binary output file
757 // Output: none
758 // Purpose: reads computed results for a link at a specific time period.
759 //
760 {
761 long offset = (NumSubcatch*NumSubcatchVars + NumNodes*NumNodeVars + index*NumLinkVars);
762 F_OFF p = period;
763 F_OFF bytePos = OutputStartPos + (p-1)*BytesPerPeriod +
764 sizeof(REAL8) + (F_OFF)offset * sizeof(REAL4);
765 F_SEEK(Fout.file, bytePos, SEEK_SET);
766 fread(LinkResults, sizeof(REAL4), NumLinkVars, Fout.file);
767 fread(SysResults, sizeof(REAL4), MAX_SYS_RESULTS, Fout.file);
768 }
769
770 //=============================================================================
771 // Functions for saving average results within a reporting period to file.
772 //=============================================================================
773
774 1 int output_openAvgResults()
775 //
776 // Allocates memory for storing average results for nodes and links.
777 {
778 int i;
779
780 // --- allocate memory for averages at reportable nodes
781 1 AvgNodeResults = (TAvgResults *)calloc(NumNodes, sizeof(TAvgResults));
782
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if ( AvgNodeResults == NULL ) return FALSE;
783
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
3 for (i = 0; i < NumNodes; i++ ) AvgNodeResults[i].xAvg = NULL;
784
785 // --- allocate memory for averages at reportable links
786 1 AvgLinkResults = (TAvgResults *)calloc(NumLinks, sizeof(TAvgResults));
787
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (AvgLinkResults == NULL)
788 {
789 output_closeAvgResults();
790 return FALSE;
791 }
792
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 for (i = 0; i < NumLinks; i++) AvgLinkResults[i].xAvg = NULL;
793
794 // --- allocate memory for each reportable variable for each reportable node
795
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
3 for (i = 0; i < NumNodes; i++)
796 {
797 2 AvgNodeResults[i].xAvg = (REAL4*) calloc(NumNodeVars, sizeof(REAL4));
798
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (AvgNodeResults[i].xAvg == NULL)
799 {
800 output_closeAvgResults();
801 return FALSE;
802 }
803 }
804
805 // --- allocate memory for each reportable variable for each reportable link
806
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 for (i = 0; i < NumLinks; i++)
807 {
808 1 AvgLinkResults[i].xAvg = (REAL4*)calloc(NumLinkVars, sizeof(REAL4));
809
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (AvgLinkResults[i].xAvg == NULL)
810 {
811 output_closeAvgResults();
812 return FALSE;
813 }
814 }
815 1 return TRUE;
816 }
817
818 //=============================================================================
819
820 58 void output_closeAvgResults()
821 //
822 // Frees memory used for storing average results for nodes and links.
823 {
824 int i;
825
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 57 times.
58 if (AvgNodeResults)
826 {
827
3/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 time.
3 for (i = 0; i < NumNodes; i++) FREE(AvgNodeResults[i].xAvg);
828
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 FREE(AvgNodeResults);
829 }
830
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 57 times.
58 if (AvgLinkResults)
831 {
832
3/4
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
2 for (i = 0; i < NumLinks; i++) FREE(AvgLinkResults[i].xAvg);
833
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 FREE(AvgLinkResults);
834 }
835 58 }
836
837 //=============================================================================
838
839 47 void output_initAvgResults()
840 //
841 // Initializes average node & link results.
842 {
843 int i, j;
844 47 Nsteps = 0;
845
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 47 times.
141 for (i = 0; i < NumNodes; i++)
846 {
847
2/2
✓ Branch 0 taken 564 times.
✓ Branch 1 taken 94 times.
658 for (j = 0; j < NumNodeVars; j++) AvgNodeResults[i].xAvg[j] = 0.0;
848 }
849
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 47 times.
94 for (i = 0; i < NumLinks; i++)
850 {
851
2/2
✓ Branch 0 taken 235 times.
✓ Branch 1 taken 47 times.
282 for (j = 0; j < NumLinkVars; j++) AvgLinkResults[i].xAvg[j] = 0.0;
852 }
853 47 }
854
855 //=============================================================================
856
857 481 void output_updateAvgResults()
858 {
859 int i, j, k, sign;
860
861 // --- update average accumulations for nodes
862 481 k = 0;
863
2/2
✓ Branch 0 taken 962 times.
✓ Branch 1 taken 481 times.
1443 for (i = 0; i < Nobjects[NODE]; i++)
864 {
865
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 962 times.
962 if ( !Node[i].rptFlag ) continue;
866 962 node_getResults(i, 1.0, NodeResults);
867
2/2
✓ Branch 0 taken 5772 times.
✓ Branch 1 taken 962 times.
6734 for (j = 0; j < NumNodeVars; j++)
868 {
869 5772 AvgNodeResults[k].xAvg[j] += NodeResults[j];
870 }
871 962 k++;
872 }
873
874 // --- update average accumulations for links
875 481 k = 0;
876
2/2
✓ Branch 0 taken 481 times.
✓ Branch 1 taken 481 times.
962 for (i = 0; i < Nobjects[LINK]; i++)
877 {
878
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 481 times.
481 if ( !Link[i].rptFlag ) continue;
879 481 link_getResults(i, 1.0, LinkResults);
880
881 // --- save sign of current flow rate
882
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 481 times.
481 sign = SGN(LinkResults[LINK_FLOW]);
883
884 // --- add current results to average accumulation
885
2/2
✓ Branch 0 taken 2405 times.
✓ Branch 1 taken 481 times.
2886 for (j = 0; j < NumLinkVars; j++)
886 {
887
2/2
✓ Branch 0 taken 481 times.
✓ Branch 1 taken 1924 times.
2405 if (j == LINK_CAPACITY)
888 {
889 // --- accumulate capacity (fraction full) for conduits
890
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 481 times.
481 if ( Link[i].type == CONDUIT )
891 AvgLinkResults[k].xAvg[j] += LinkResults[j];
892
893 // --- for other links capacity is pump speed or regulator
894 // opening fraction which shouldn't be averaged
895 // (multiplying by Nsteps+1 will preserve last value
896 // when average results are taken in saveAvgResults())
897 else
898 481 AvgLinkResults[k].xAvg[j] = LinkResults[j] * (Nsteps+1);
899 }
900
901 // --- accumulation for all other reported results
902 1924 else AvgLinkResults[k].xAvg[j] += LinkResults[j];
903 }
904 481 k++;
905 }
906 481 Nsteps++;
907 481 }
908
909 //=============================================================================
910
911 47 void output_saveAvgResults(FILE* file)
912 {
913 int i, j;
914
915 // --- examine each reportable node
916
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 47 times.
141 for (i = 0; i < NumNodes; i++)
917 {
918 // --- determine the node's average results
919
2/2
✓ Branch 0 taken 564 times.
✓ Branch 1 taken 94 times.
658 for (j = 0; j < NumNodeVars; j++)
920 {
921 564 NodeResults[j] = AvgNodeResults[i].xAvg[j] / Nsteps;
922 }
923
924 // --- save average results to file
925 94 fwrite(NodeResults, sizeof(REAL4), NumNodeVars, file);
926 }
927
928 // --- update each node's max depth and contribution to system storage
929
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 47 times.
141 for (i = 0; i < Nobjects[NODE]; i++)
930 {
931 94 stats_updateMaxNodeDepth(i, Node[i].newDepth * UCF(LENGTH));
932 94 SysResults[SYS_STORAGE] += (REAL4)(Node[i].newVolume * UCF(VOLUME));
933 }
934
935 // --- examine each reportable link
936
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 47 times.
94 for (i = 0; i < NumLinks; i++)
937 {
938 // --- determine the link's average results
939
2/2
✓ Branch 0 taken 235 times.
✓ Branch 1 taken 47 times.
282 for (j = 0; j < NumLinkVars; j++)
940 {
941 235 LinkResults[j] = AvgLinkResults[i].xAvg[j] / Nsteps;
942 }
943
944 // --- save average results to file
945 47 fwrite(LinkResults, sizeof(REAL4), NumLinkVars, file);
946 }
947
948 // --- add each link's volume to total system storage
949
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 47 times.
94 for (i = 0; i < Nobjects[LINK]; i++)
950 {
951 47 SysResults[SYS_STORAGE] += (REAL4)(Link[i].newVolume * UCF(VOLUME));
952 }
953
954 // --- re-initialize average results for all nodes and links
955 47 output_initAvgResults();
956 47 }
957