GCC Code Coverage Report


Directory: src/solver/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 91.1% 592 / 0 / 650
Functions: 100.0% 18 / 0 / 18
Branches: 69.4% 322 / 0 / 464

project.c
Line Branch Exec Source
1 //-----------------------------------------------------------------------------
2 // project.c
3 //
4 // Project: EPA SWMM5
5 // Version: 5.2
6 // Date: 07/17/23 (Build 5.2.4)
7 // Author: L. Rossman
8 //
9 // Project management functions.
10 //
11 // This module provides project-related services such as:
12 // o opening a new project and reading its input data
13 // o allocating and freeing memory for project objects
14 // o setting default values for object properties and options
15 // o initializing the internal state of all objects
16 // o managing hash tables for identifying objects by ID name
17 //
18 // Update History
19 // ==============
20 // Build 5.1.004:
21 // - Ignore RDII option added.
22 // Build 5.1.007:
23 // - Default monthly adjustments for climate variables included.
24 // - User-supplied GW flow equations initialized to NULL.
25 // - Storage node exfiltration object initialized to NULL.
26 // - Freeing of memory used for storage node exfiltration included.
27 // Build 5.1.008:
28 // - Constants used for dynamic wave routing moved to dynwave.c.
29 // - Input processing of minimum time step & number of
30 // parallel threads for dynamic wave routing added.
31 // - Default values of hyd. conductivity adjustments added.
32 // - Freeing of memory used for outfall pollutant load added.
33 // Build 5.1.009:
34 // - Fixed bug in computing total duration introduced in 5.1.008.
35 // Build 5.1.011:
36 // - Memory management of hydraulic event dates array added.
37 // Build 5.1.012:
38 // - Minimum conduit slope option initialized to 0 (none).
39 // - NO/YES no longer accepted as options for NORMAL_FLOW_LIMITED.
40 // Build 5.1.013:
41 // - omp_get_num_threads function protected against lack of compiler
42 // support for OpenMP.
43 // - Rain gage validation now performed after subcatchment validation.
44 // - More robust parsing of MinSurfarea option provided.
45 // - Support added for new RuleStep analysis option.
46 // Build 5.1.015:
47 // - Support added for multiple infiltration methods within a project.
48 // Build 5.2.0:
49 // - Support added for Streets and Inlets.
50 // - Support added for RptFlags.disabled option.
51 // - Object's rptFlag changed to record its index in output file.
52 // Build 5.2.2:
53 // - Default number of threads changed from OMP max. number to 1
54 // to be consistent with User Manual.
55 // Build 5.2.4:
56 // - Default Inertial Damping changed from SOME to PARTIAL_DAMPING.
57 // - Default CourantFactor changed from 0 (fixed routing time step)
58 // - to 0.75 (variable time step)
59 //-----------------------------------------------------------------------------
60 #define _CRT_SECURE_NO_DEPRECATE
61
62 #include <stdlib.h>
63 #include <string.h>
64 #include <math.h>
65
66 // Protect against lack of compiler support for OpenMP
67 #if defined(_OPENMP)
68 #include <omp.h>
69 #else
70 int omp_get_max_threads(void) { return 1;}
71 #endif
72
73 #include "headers.h"
74 #include "lid.h"
75 #include "hash.h"
76 #include "mempool.h"
77
78 //-----------------------------------------------------------------------------
79 // Shared variables
80 //-----------------------------------------------------------------------------
81 static HTtable* Htable[MAX_OBJ_TYPES]; // Hash tables for object ID names
82 static char MemPoolAllocated; // TRUE if memory pool allocated
83
84 //-----------------------------------------------------------------------------
85 // External Functions (declared in funcs.h)
86 //-----------------------------------------------------------------------------
87 // project_open (called from swmm_open in swmm5.c)
88 // project_close (called from swmm_close in swmm5.c)
89 // project_readInput (called from swmm_open in swmm5.c)
90 // project_readOption (called from readOption in input.c)
91 // project_validate (called from swmm_open in swmm5.c)
92 // project_init (called from swmm_start in swmm5.c)
93 // project_addObject (called from addObject in input.c)
94 // project_createMatrix (called from openFileForInput in iface.c)
95 // project_freeMatrix (called from iface_closeRoutingFiles)
96 // project_findObject
97 // project_findID
98
99 //-----------------------------------------------------------------------------
100 // Function declarations
101 //-----------------------------------------------------------------------------
102 static void initPointers(void);
103 static void setDefaults(void);
104 static void openFiles(const char *f1, const char *f2, const char *f3);
105 static void createObjects(void);
106 static void deleteObjects(void);
107 static void createHashTables(void);
108 static void deleteHashTables(void);
109
110
111 //=============================================================================
112
113 58 void project_open(const char *f1, const char *f2, const char *f3)
114 //
115 // Input: f1 = pointer to name of input file
116 // f2 = pointer to name of report file
117 // f3 = pointer to name of binary output file
118 // Output: none
119 // Purpose: opens a new SWMM project.
120 //
121 {
122 58 initPointers();
123 58 setDefaults();
124 58 openFiles(f1, f2, f3);
125 58 }
126
127 //=============================================================================
128
129 58 void project_readInput()
130 //
131 // Input: none
132 // Output: none
133 // Purpose: retrieves project data from input file.
134 //
135 {
136 // --- create hash tables for fast retrieval of objects by ID names
137 58 createHashTables();
138
139 // --- count number of objects in input file and create them
140 58 input_countObjects();
141 58 createObjects();
142
143 // --- read project data from input file
144 58 input_readData();
145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if ( ErrorCode ) return;
146
147 // --- establish starting & ending date/time
148 58 StartDateTime = StartDate + StartTime;
149 58 EndDateTime = EndDate + EndTime;
150 58 ReportStart = ReportStartDate + ReportStartTime;
151
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 ReportStart = MAX(ReportStart, StartDateTime);
152
153 // --- check for valid starting & ending date/times
154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if ( EndDateTime <= StartDateTime )
155 {
156 report_writeErrorMsg(ERR_START_DATE, "");
157 }
158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 else if ( EndDateTime <= ReportStart )
159 {
160 report_writeErrorMsg(ERR_REPORT_DATE, "");
161 }
162 else
163 {
164 // --- compute total duration of simulation in seconds
165 58 TotalDuration = floor((EndDateTime - StartDateTime) * SECperDAY);
166
167 // --- reporting step must be <= total duration
168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if ( (double)ReportStep > TotalDuration )
169 {
170 ReportStep = (int)(TotalDuration);
171 }
172
173 // --- reporting step can't be < routing step
174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if ( (double)ReportStep < RouteStep )
175 {
176 report_writeErrorMsg(ERR_REPORT_STEP, "");
177 }
178
179 // --- convert total duration to milliseconds
180 58 TotalDuration *= 1000.0;
181 }
182 }
183
184 //=============================================================================
185
186 58 void project_validate()
187 //
188 // Input: none
189 // Output: none
190 // Purpose: checks validity of project data.
191 //
192 {
193 int i;
194 int j;
195 int err;
196
197 // --- validate Curves and TimeSeries
198
2/2
✓ Branch 0 taken 221 times.
✓ Branch 1 taken 58 times.
279 for ( i=0; i<Nobjects[CURVE]; i++ )
199 {
200 221 err = table_validate(&Curve[i]);
201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 221 times.
221 if ( err ) report_writeErrorMsg(ERR_CURVE_SEQUENCE, Curve[i].ID);
202 }
203
2/2
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 58 times.
160 for ( i=0; i<Nobjects[TSERIES]; i++ )
204 {
205 102 err = table_validate(&Tseries[i]);
206
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 102 times.
102 if ( err ) report_writeTseriesErrorMsg(err, &Tseries[i]);
207 }
208
209 // --- validate hydrology objects
210 // (NOTE: order is important !!!!)
211 58 climate_validate();
212 58 lid_validate();
213
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 8 times.
58 if ( Nobjects[SNOWMELT] == 0 ) IgnoreSnowmelt = TRUE;
214
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 9 times.
58 if ( Nobjects[AQUIFER] == 0 ) IgnoreGwater = TRUE;
215
2/2
✓ Branch 1 taken 2186 times.
✓ Branch 2 taken 58 times.
2244 for ( i=0; i<Nobjects[AQUIFER]; i++ ) gwater_validateAquifer(i);
216
2/2
✓ Branch 1 taken 2393 times.
✓ Branch 2 taken 58 times.
2451 for ( i=0; i<Nobjects[SUBCATCH]; i++ ) subcatch_validate(i);
217
2/2
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 58 times.
110 for ( i=0; i<Nobjects[GAGE]; i++ ) gage_validate(i);
218
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 58 times.
66 for ( i=0; i<Nobjects[SNOWMELT]; i++ ) snow_validateSnowmelt(i);
219
220 // --- compute geometry tables for each shape curve
221 58 j = 0;
222
2/2
✓ Branch 0 taken 221 times.
✓ Branch 1 taken 58 times.
279 for ( i=0; i<Nobjects[CURVE]; i++ )
223 {
224
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 190 times.
221 if ( Curve[i].curveType == SHAPE_CURVE )
225 {
226 31 Curve[i].refersTo = j;
227 31 Shape[j].curve = i;
228
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
31 if ( !shape_validate(&Shape[j], &Curve[i]) )
229 report_writeErrorMsg(ERR_CURVE_SEQUENCE, Curve[i].ID);
230 31 j++;
231 }
232 }
233
234 // --- validate links before nodes, since the latter can
235 // result in adjustment of node depths
236
2/2
✓ Branch 0 taken 10183 times.
✓ Branch 1 taken 58 times.
10241 for ( i=0; i<Nobjects[NODE]; i++) Node[i].oldDepth = Node[i].fullDepth;
237
2/2
✓ Branch 1 taken 10508 times.
✓ Branch 2 taken 58 times.
10566 for ( i=0; i<Nobjects[LINK]; i++) link_validate(i);
238
2/2
✓ Branch 1 taken 10183 times.
✓ Branch 2 taken 58 times.
10241 for ( i=0; i<Nobjects[NODE]; i++) node_validate(i);
239
240 // --- adjust time steps if necessary
241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if ( DryStep < WetStep )
242 {
243 report_writeWarningMsg(WARN06, "");
244 DryStep = WetStep;
245 }
246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if ( RouteStep > (double)WetStep )
247 {
248 report_writeWarningMsg(WARN07, "");
249 RouteStep = WetStep;
250 }
251
252 // --- adjust individual reporting flags to match global reporting flag
253
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 12 times.
58 if ( RptFlags.subcatchments == ALL )
254
2/2
✓ Branch 0 taken 2393 times.
✓ Branch 1 taken 46 times.
2439 for (i=0; i<Nobjects[SUBCATCH]; i++) Subcatch[i].rptFlag = 1;
255
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 10 times.
58 if (RptFlags.nodes == ALL)
256
2/2
✓ Branch 0 taken 318 times.
✓ Branch 1 taken 48 times.
366 for (i = 0; i < Nobjects[NODE]; i++) Node[i].rptFlag = 1;
257
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 11 times.
58 if ( RptFlags.links == ALL )
258
2/2
✓ Branch 0 taken 238 times.
✓ Branch 1 taken 47 times.
285 for (i=0; i<Nobjects[LINK]; i++) Link[i].rptFlag = 1;
259
260 // --- validate dynamic wave options
261
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 17 times.
58 if ( RouteModel == DW ) dynwave_validate();
262
263 // --- validate street/channel inlets
264 58 inlet_validate();
265
266 // --- adjust number of parallel threads to be used
267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if ( NumThreads == 0 ) NumThreads = omp_get_max_threads();
268
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
58 else NumThreads = MIN(NumThreads, omp_get_max_threads());
269
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 32 times.
58 if ( Nobjects[LINK] < 4 * NumThreads ) NumThreads = 1;
270 58 }
271
272 //=============================================================================
273
274 58 void project_close()
275 //
276 // Input: none
277 // Output: none
278 // Purpose: closes a SWMM project.
279 //
280 {
281 58 deleteObjects();
282 58 deleteHashTables();
283 58 }
284
285 //=============================================================================
286
287 58 int project_init(void)
288 //
289 // Input: none
290 // Output: returns an error code
291 // Purpose: initializes the internal state of all objects.
292 //
293 {
294 int j, k;
295 58 climate_initState();
296 58 lid_initState();
297
2/2
✓ Branch 1 taken 102 times.
✓ Branch 2 taken 58 times.
160 for (j=0; j<Nobjects[TSERIES]; j++) table_tseriesInit(&Tseries[j]);
298
2/2
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 58 times.
110 for (j=0; j<Nobjects[GAGE]; j++) gage_initState(j);
299 58 k = 1;
300
2/2
✓ Branch 0 taken 2393 times.
✓ Branch 1 taken 58 times.
2451 for (j=0; j<Nobjects[SUBCATCH]; j++)
301 {
302 2393 subcatch_initState(j);
303
1/2
✓ Branch 0 taken 2393 times.
✗ Branch 1 not taken.
2393 if (Subcatch[j].rptFlag > 0)
304 {
305 2393 Subcatch[j].rptFlag = k;
306 2393 k++;
307 }
308 }
309 58 k = 1;
310
2/2
✓ Branch 0 taken 10183 times.
✓ Branch 1 taken 58 times.
10241 for (j=0; j<Nobjects[NODE]; j++)
311 {
312 10183 node_initState(j);
313
2/2
✓ Branch 0 taken 817 times.
✓ Branch 1 taken 9366 times.
10183 if (Node[j].rptFlag > 0)
314 {
315 817 Node[j].rptFlag = k;
316 817 k++;
317 }
318 }
319 58 k = 1;
320
2/2
✓ Branch 0 taken 10508 times.
✓ Branch 1 taken 58 times.
10566 for (j=0; j<Nobjects[LINK]; j++)
321 {
322 10508 link_initState(j);
323
2/2
✓ Branch 0 taken 1220 times.
✓ Branch 1 taken 9288 times.
10508 if (Link[j].rptFlag > 0)
324 {
325 1220 Link[j].rptFlag = k;
326 1220 k++;
327 }
328 }
329 58 return ErrorCode;
330 }
331
332 //=============================================================================
333
334 26489 int project_addObject(int type, char *id, int n)
335 //
336 // Input: type = object type
337 // id = object ID string
338 // n = object index
339 // Output: returns 0 if object already added, 1 if not, -1 if hashing fails
340 // Purpose: adds an object ID to a hash table
341 //
342 {
343 int result;
344 long len;
345 char *newID;
346
347 // --- do nothing if object already placed in hash table
348
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 26489 times.
26489 if ( project_findObject(type, id) >= 0 ) return 0;
349
350 // --- use memory from the hash tables' common memory pool to store
351 // a copy of the object's ID string
352 26489 len = (long)strlen(id);
353 26489 newID = (char *) Alloc((len+1)*sizeof(char));
354 26489 sstrncpy(newID, id, len);
355
356 // --- insert object's ID into the hash table for that type of object
357 26489 result = HTinsert(Htable[type], newID, n);
358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26489 times.
26489 if ( result == 0 ) result = -1;
359 26489 return result;
360 }
361
362 //=============================================================================
363
364 208645 int project_findObject(int type, const char *id)
365 //
366 // Input: type = object type
367 // id = object ID
368 // Output: returns index of object with given ID, or -1 if ID not found
369 // Purpose: uses hash table to find index of an object with a given ID.
370 //
371 {
372 208645 return HTfind(Htable[type], id);
373 }
374
375 //=============================================================================
376
377 26490 char *project_findID(int type, char *id)
378 //
379 // Input: type = object type
380 // id = ID name being sought
381 // Output: returns pointer to location where object's ID string is stored
382 // Purpose: uses hash table to find address of given string entry.
383 //
384 {
385 26490 return HTfindKey(Htable[type], id);
386 }
387
388 //=============================================================================
389
390 2 double ** project_createMatrix(int nrows, int ncols)
391 //
392 // Input: nrows = number of rows (0-based)
393 // ncols = number of columns (0-based)
394 // Output: returns a pointer to a matrix
395 // Purpose: allocates memory for a matrix of doubles.
396 //
397 {
398 int i;
399 double **a;
400
401 2 size_t size = (size_t)nrows * (size_t)ncols;
402
403 // --- allocate pointers to rows
404
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (nrows < 1 || ncols < 1)
405 return NULL;
406 2 a = (double **) malloc(nrows * sizeof(double *));
407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if ( !a )
408 return NULL;
409
410 // --- allocate rows and set pointers to them
411 2 a[0] = (double *) malloc (size * sizeof(double));
412
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if ( !a[0] )
413 {
414 free(a);
415 return NULL;
416 }
417
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 for ( i = 1; i < nrows; i++ )
418 a[i] = a[i-1] + ncols;
419
420 // --- fill matrix with zeroes
421 2 memset(a[0], 0, size);
422
423 // --- return pointer to array of pointers to rows
424 2 return a;
425 }
426
427 //=============================================================================
428
429 2 void project_freeMatrix(double **a)
430 //
431 // Input: a = matrix of floats
432 // Output: none
433 // Purpose: frees memory allocated for a matrix of doubles.
434 //
435 {
436
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if ( a != NULL )
437 {
438
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if ( a[0] != NULL ) free( a[0] );
439 2 free( a );
440 }
441 2 }
442
443 //=============================================================================
444
445 1588 int project_readOption(char* s1, char* s2)
446 //
447 // Input: s1 = option keyword
448 // s2 = string representation of option's value
449 // Output: returns error code
450 // Purpose: reads a project option from a pair of string tokens.
451 //
452 // NOTE: all project options have default values assigned in setDefaults().
453 //
454 {
455 int k, m, h, s;
456 double tStep;
457 char strDate[25];
458 DateTime aTime;
459 DateTime aDate;
460
461 // --- determine which option is being read
462 1588 k = findmatch(s1, OptionWords);
463
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1588 times.
1588 if ( k < 0 ) return error_setInpError(ERR_KEYWORD, s1);
464
28/31
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 58 times.
✓ Branch 2 taken 58 times.
✓ Branch 3 taken 58 times.
✓ Branch 4 taken 58 times.
✓ Branch 5 taken 58 times.
✓ Branch 6 taken 58 times.
✓ Branch 7 taken 58 times.
✓ Branch 8 taken 58 times.
✓ Branch 9 taken 78 times.
✓ Branch 10 taken 52 times.
✓ Branch 11 taken 194 times.
✓ Branch 12 taken 39 times.
✓ Branch 13 taken 110 times.
✓ Branch 14 taken 40 times.
✓ Branch 15 taken 39 times.
✓ Branch 16 taken 56 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 96 times.
✓ Branch 19 taken 40 times.
✓ Branch 20 taken 58 times.
✓ Branch 21 taken 44 times.
✓ Branch 22 taken 41 times.
✓ Branch 23 taken 38 times.
✓ Branch 24 taken 37 times.
✓ Branch 25 taken 37 times.
✓ Branch 26 taken 33 times.
✓ Branch 27 taken 33 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 1 time.
✗ Branch 30 not taken.
1588 switch ( k )
465 {
466 // --- choice of flow units
467 58 case FLOW_UNITS:
468 58 m = findmatch(s2, FlowUnitWords);
469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if ( m < 0 ) return error_setInpError(ERR_KEYWORD, s2);
470 58 FlowUnits = m;
471
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 3 times.
58 if ( FlowUnits <= MGD ) UnitSystem = US;
472 3 else UnitSystem = SI;
473 58 break;
474
475 // --- choice of infiltration modeling method
476 58 case INFIL_MODEL:
477 58 m = findmatch(s2, InfilModelWords);
478
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if ( m < 0 ) return error_setInpError(ERR_KEYWORD, s2);
479 58 InfilModel = m;
480 58 break;
481
482 // --- choice of flow routing method
483 58 case ROUTE_MODEL:
484 58 m = findmatch(s2, RouteModelWords);
485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if ( m < 0 ) m = findmatch(s2, OldRouteModelWords);
486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if ( m < 0 ) return error_setInpError(ERR_KEYWORD, s2);
487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if ( m == NO_ROUTING ) IgnoreRouting = TRUE;
488 58 else RouteModel = m;
489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if ( RouteModel == EKW ) RouteModel = KW;
490 58 break;
491
492 // --- simulation start date
493 58 case START_DATE:
494
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
58 if ( !datetime_strToDate(s2, &StartDate) )
495 {
496 return error_setInpError(ERR_DATETIME, s2);
497 }
498 58 break;
499
500 // --- simulation start time of day
501 58 case START_TIME:
502
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
58 if ( !datetime_strToTime(s2, &StartTime) )
503 {
504 return error_setInpError(ERR_DATETIME, s2);
505 }
506 58 break;
507
508 // --- simulation ending date
509 58 case END_DATE:
510
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
58 if ( !datetime_strToDate(s2, &EndDate) )
511 {
512 return error_setInpError(ERR_DATETIME, s2);
513 }
514 58 break;
515
516 // --- simulation ending time of day
517 58 case END_TIME:
518
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
58 if ( !datetime_strToTime(s2, &EndTime) )
519 {
520 return error_setInpError(ERR_DATETIME, s2);
521 }
522 58 break;
523
524 // --- reporting start date
525 58 case REPORT_START_DATE:
526
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
58 if ( !datetime_strToDate(s2, &ReportStartDate) )
527 {
528 return error_setInpError(ERR_DATETIME, s2);
529 }
530 58 break;
531
532 // --- reporting start time of day
533 58 case REPORT_START_TIME:
534
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
58 if ( !datetime_strToTime(s2, &ReportStartTime) )
535 {
536 return error_setInpError(ERR_DATETIME, s2);
537 }
538 58 break;
539
540 // --- day of year when street sweeping begins or when it ends
541 // (year is arbitrarily set to 1947 so that the dayOfYear
542 // function can be applied)
543 78 case SWEEP_START:
544 case SWEEP_END:
545 78 sstrncpy(strDate, s2, 24);
546 78 sstrcat(strDate, "/1947", 25);
547
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 78 times.
78 if ( !datetime_strToDate(strDate, &aDate) )
548 {
549 return error_setInpError(ERR_DATETIME, s2);
550 }
551 78 m = datetime_dayOfYear(aDate);
552
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 39 times.
78 if ( k == SWEEP_START ) SweepStart = m;
553 39 else SweepEnd = m;
554 78 break;
555
556 // --- number of antecedent dry days
557 52 case START_DRY_DAYS:
558 52 StartDryDays = atof(s2);
559
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if ( StartDryDays < 0.0 )
560 {
561 return error_setInpError(ERR_NUMBER, s2);
562 }
563 52 break;
564
565 // --- runoff or reporting time steps
566 // (input is in hrs:min:sec format, time step saved as seconds)
567 194 case WET_STEP:
568 case DRY_STEP:
569 case REPORT_STEP:
570 case RULE_STEP:
571
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 194 times.
194 if ( !datetime_strToTime(s2, &aTime) )
572 {
573 return error_setInpError(ERR_DATETIME, s2);
574 }
575 194 datetime_decodeTime(aTime, &h, &m, &s);
576 194 h += 24*(int)aTime;
577 194 s = s + 60*m + 3600*h;
578
579 // --- RuleStep allowed to be 0 while other time steps must be > 0
580
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 174 times.
194 if (k == RULE_STEP)
581 {
582
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (s < 0) return error_setInpError(ERR_NUMBER, s2);
583 }
584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 174 times.
174 else if ( s <= 0 ) return error_setInpError(ERR_NUMBER, s2);
585
586
4/5
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 58 times.
✓ Branch 2 taken 58 times.
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
194 switch ( k )
587 {
588 58 case WET_STEP: WetStep = s; break;
589 58 case DRY_STEP: DryStep = s; break;
590 58 case REPORT_STEP: ReportStep = s; break;
591 20 case RULE_STEP: RuleStep = s; break;
592 }
593 194 break;
594
595 // --- type of damping applied to inertial terms of dynamic wave routing
596 39 case INERT_DAMPING:
597 39 m = findmatch(s2, InertDampingWords);
598
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if ( m < 0 ) return error_setInpError(ERR_KEYWORD, s2);
599 39 else InertDamping = m;
600 39 break;
601
602 // --- Yes/No options (NO = 0, YES = 1)
603 110 case ALLOW_PONDING:
604 case SLOPE_WEIGHTING:
605 case SKIP_STEADY_STATE:
606 case IGNORE_RAINFALL:
607 case IGNORE_SNOWMELT:
608 case IGNORE_GWATER:
609 case IGNORE_ROUTING:
610 case IGNORE_QUALITY:
611 case IGNORE_RDII:
612 110 m = findmatch(s2, NoYesWords);
613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 110 times.
110 if ( m < 0 ) return error_setInpError(ERR_KEYWORD, s2);
614
6/10
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 41 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 7 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
110 switch ( k )
615 {
616 41 case ALLOW_PONDING: AllowPonding = m; break;
617 case SLOPE_WEIGHTING: SlopeWeighting = m; break;
618 41 case SKIP_STEADY_STATE: SkipSteadyState = m; break;
619 7 case IGNORE_RAINFALL: IgnoreRainfall = m; break;
620 7 case IGNORE_SNOWMELT: IgnoreSnowmelt = m; break;
621 7 case IGNORE_GWATER: IgnoreGwater = m; break;
622 case IGNORE_ROUTING: IgnoreRouting = m; break;
623 7 case IGNORE_QUALITY: IgnoreQuality = m; break;
624 case IGNORE_RDII: IgnoreRDII = m; break;
625 }
626 110 break;
627
628 40 case NORMAL_FLOW_LTD:
629 40 m = findmatch(s2, NormalFlowWords);
630
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if ( m < 0 ) return error_setInpError(ERR_KEYWORD, s2);
631 40 NormalFlowLtd = m;
632 40 break;
633
634 39 case FORCE_MAIN_EQN:
635 39 m = findmatch(s2, ForceMainEqnWords);
636
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if ( m < 0 ) return error_setInpError(ERR_KEYWORD, s2);
637 39 ForceMainEqn = m;
638 39 break;
639
640 56 case LINK_OFFSETS:
641 56 m = findmatch(s2, LinkOffsetWords);
642
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
56 if ( m < 0 ) return error_setInpError(ERR_KEYWORD, s2);
643 56 LinkOffsets = m;
644 56 break;
645
646 // --- compatibility option for selecting solution method for
647 // dynamic wave flow routing (NOT CURRENTLY USED)
648 case COMPATIBILITY:
649 if ( strcomp(s2, "3") ) Compatibility = SWMM3;
650 else if ( strcomp(s2, "4") ) Compatibility = SWMM4;
651 else if ( strcomp(s2, "5") ) Compatibility = SWMM5;
652 else return error_setInpError(ERR_KEYWORD, s2);
653 break;
654
655 // --- routing or lengthening time step (in decimal seconds)
656 // (lengthening time step is used in Courant stability formula
657 // to artificially lengthen conduits for dynamic wave flow routing
658 // (a value of 0 means that no lengthening is used))
659 96 case ROUTE_STEP:
660 case LENGTHENING_STEP:
661
2/2
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 57 times.
96 if ( !getDouble(s2, &tStep) )
662 {
663
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 39 times.
39 if ( !datetime_strToTime(s2, &aTime) )
664 {
665 return error_setInpError(ERR_NUMBER, s2);
666 }
667 else
668 {
669 39 datetime_decodeTime(aTime, &h, &m, &s);
670 39 h += 24*(int)aTime;
671 39 s = s + 60*m + 3600*h;
672 39 tStep = s;
673 }
674 }
675
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 38 times.
96 if ( k == ROUTE_STEP )
676 {
677
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if ( tStep <= 0.0 ) return error_setInpError(ERR_NUMBER, s2);
678 58 RouteStep = tStep;
679 }
680
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 12 times.
38 else LengtheningStep = MAX(0.0, tStep);
681 96 break;
682
683 // --- minimum variable time step for dynamic wave routing
684 40 case MIN_ROUTE_STEP:
685
2/4
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 40 times.
40 if ( !getDouble(s2, &MinRouteStep) || MinRouteStep < 0.0 )
686 return error_setInpError(ERR_NUMBER, s2);
687 40 break;
688
689 58 case NUM_THREADS:
690 58 m = atoi(s2);
691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if ( m < 0 ) return error_setInpError(ERR_NUMBER, s2);
692 58 NumThreads = m;
693 58 break;
694
695 // --- safety factor applied to variable time step estimates under
696 // dynamic wave flow routing (value of 0 indicates that variable
697 // time step option not used)
698 44 case VARIABLE_STEP:
699
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 44 times.
44 if ( !getDouble(s2, &CourantFactor) )
700 return error_setInpError(ERR_NUMBER, s2);
701
2/4
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 44 times.
44 if ( CourantFactor < 0.0 || CourantFactor > 2.0 )
702 return error_setInpError(ERR_NUMBER, s2);
703 44 break;
704
705 // --- minimum surface area (ft2 or sq. meters) associated with nodes
706 // under dynamic wave flow routing
707 41 case MIN_SURFAREA:
708
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 41 times.
41 if (!getDouble(s2, &MinSurfArea))
709 return error_setInpError(ERR_NUMBER, s2);
710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (MinSurfArea < 0.0)
711 return error_setInpError(ERR_NUMBER, s2);
712 41 break;
713
714 // --- minimum conduit slope (%)
715 38 case MIN_SLOPE:
716
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
38 if ( !getDouble(s2, &MinSlope) )
717 return error_setInpError(ERR_NUMBER, s2);
718
2/4
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 38 times.
38 if ( MinSlope < 0.0 || MinSlope >= 100 )
719 return error_setInpError(ERR_NUMBER, s2);
720 38 MinSlope /= 100.0;
721 38 break;
722
723 // --- maximum trials / time step for dynamic wave routing
724 37 case MAX_TRIALS:
725 37 m = atoi(s2);
726
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 if ( m < 0 ) return error_setInpError(ERR_NUMBER, s2);
727 37 MaxTrials = m;
728 37 break;
729
730 // --- head convergence tolerance for dynamic wave routing
731 37 case HEAD_TOL:
732
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
37 if ( !getDouble(s2, &HeadTol) )
733 {
734 return error_setInpError(ERR_NUMBER, s2);
735 }
736 37 break;
737
738 // --- steady state tolerance on system inflow - outflow
739 33 case SYS_FLOW_TOL:
740
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
33 if ( !getDouble(s2, &SysFlowTol) )
741 {
742 return error_setInpError(ERR_NUMBER, s2);
743 }
744 33 SysFlowTol /= 100.0;
745 33 break;
746
747 // --- steady state tolerance on nodal lateral inflow
748 33 case LAT_FLOW_TOL:
749
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
33 if ( !getDouble(s2, &LatFlowTol) )
750 {
751 return error_setInpError(ERR_NUMBER, s2);
752 }
753 33 LatFlowTol /= 100.0;
754 33 break;
755
756 // --- method used for surcharging in dynamic wave flow routing
757 case SURCHARGE_METHOD:
758 m = findmatch(s2, SurchargeWords);
759 if (m < 0) return error_setInpError(ERR_KEYWORD, s2);
760 SurchargeMethod = m;
761 break;
762
763 1 case TEMPDIR: // Temporary Directory
764 1 sstrncpy(TempDir, s2, MAXFNAME);
765 1 break;
766
767 }
768 1588 return 0;
769 }
770
771 //=============================================================================
772
773 58 void initPointers()
774 //
775 // Input: none
776 // Output: none
777 // Purpose: assigns NULL to all dynamic arrays for a new project.
778 //
779 {
780 58 Gage = NULL;
781 58 Subcatch = NULL;
782 58 Node = NULL;
783 58 Outfall = NULL;
784 58 Divider = NULL;
785 58 Storage = NULL;
786 58 Link = NULL;
787 58 Conduit = NULL;
788 58 Pump = NULL;
789 58 Orifice = NULL;
790 58 Weir = NULL;
791 58 Outlet = NULL;
792 58 Pollut = NULL;
793 58 Landuse = NULL;
794 58 Pattern = NULL;
795 58 Curve = NULL;
796 58 Tseries = NULL;
797 58 Transect = NULL;
798 58 Shape = NULL;
799 58 Aquifer = NULL;
800 58 UnitHyd = NULL;
801 58 Snowmelt = NULL;
802 58 Event = NULL;
803 58 MemPoolAllocated = FALSE;
804 58 }
805
806 //=============================================================================
807
808 58 void setDefaults()
809 //
810 // Input: none
811 // Output: none
812 // Purpose: assigns default values to project variables.
813 //
814 {
815 int i, j;
816
817 // Project title & temp. file path
818
2/2
✓ Branch 1 taken 174 times.
✓ Branch 2 taken 58 times.
232 for (i = 0; i < MAXTITLE; i++) sstrncpy(Title[i], "", 0);
819 58 sstrncpy(TempDir, "", 0);
820
821 // Interface files
822 58 Frain.mode = SCRATCH_FILE; // Use scratch rainfall file
823 58 Fclimate.mode = NO_FILE;
824 58 Frunoff.mode = NO_FILE;
825 58 Frdii.mode = NO_FILE;
826 58 Fhotstart1.mode = NO_FILE;
827 58 Fhotstart2.mode = NO_FILE;
828 58 Finflows.mode = NO_FILE;
829 58 Foutflows.mode = NO_FILE;
830 58 Frain.file = NULL;
831 58 Fclimate.file = NULL;
832 58 Frunoff.file = NULL;
833 58 Frdii.file = NULL;
834 58 Fhotstart1.file = NULL;
835 58 Fhotstart2.file = NULL;
836 58 Finflows.file = NULL;
837 58 Foutflows.file = NULL;
838 58 Fout.file = NULL;
839 58 Fout.mode = NO_FILE;
840
841 // Analysis options
842 58 UnitSystem = US; // US unit system
843 58 FlowUnits = CFS; // CFS flow units
844 58 InfilModel = HORTON; // Horton infiltration method
845 58 RouteModel = DW; // Dynamic wave flow routing method
846 58 SurchargeMethod = EXTRAN; // Use EXTRAN method for surcharging
847 58 CrownCutoff = 0.96; // Fractional pipe crown cutoff
848 58 AllowPonding = FALSE; // No ponding at nodes
849 58 InertDamping = PARTIAL_DAMPING; // Partial inertial damping
850 58 NormalFlowLtd = BOTH; // Default normal flow limitation
851 58 ForceMainEqn = H_W; // Hazen-Williams eqn. for force mains
852 58 LinkOffsets = DEPTH_OFFSET; // Use depth for link offsets
853 58 LengtheningStep = 0; // No lengthening of conduits
854 58 CourantFactor = 0.75; // Variable time step reduced to 75%
855 58 MinSurfArea = 0.0; // Force use of default min. surface area
856 58 MinSlope = 0.0; // No user supplied minimum conduit slope
857 58 SkipSteadyState = FALSE; // Do flow routing in steady state periods
858 58 IgnoreRainfall = FALSE; // Analyze rainfall/runoff
859 58 IgnoreRDII = FALSE; // Analyze RDII
860 58 IgnoreSnowmelt = FALSE; // Analyze snowmelt
861 58 IgnoreGwater = FALSE; // Analyze groundwater
862 58 IgnoreRouting = FALSE; // Analyze flow routing
863 58 IgnoreQuality = FALSE; // Analyze water quality
864 58 WetStep = 300; // Runoff wet time step (secs)
865 58 DryStep = 3600; // Runoff dry time step (secs)
866 58 RuleStep = 0; // Rules evaluated at each routing step
867 58 RouteStep = 20; // Routing time step (secs)
868 58 MinRouteStep = 0.5; // Minimum variable time step (sec)
869 58 ReportStep = 900; // Reporting time step (secs)
870 58 StartDryDays = 0.0; // Antecedent dry days
871 58 MaxTrials = 0; // Force use of default max. trials
872 58 HeadTol = 0.0; // Force use of default head tolerance
873 58 SysFlowTol = 0.05; // System flow tolerance for steady state
874 58 LatFlowTol = 0.05; // Lateral flow tolerance for steady state
875 58 NumThreads = 1; // Number of parallel threads to use
876 58 NumEvents = 0; // Number of detailed routing events
877
878 // Deprecated options
879 58 SlopeWeighting = TRUE; // Use slope weighting
880 58 Compatibility = SWMM4; // Use SWMM 4 up/dn weighting method
881
882 // Starting & ending date/time
883 58 StartDate = datetime_encodeDate(2004, 1, 1);
884 58 StartTime = datetime_encodeTime(0,0,0);
885 58 StartDateTime = StartDate + StartTime;
886 58 EndDate = StartDate;
887 58 EndTime = 0.0;
888 58 ReportStartDate = NO_DATE;
889 58 ReportStartTime = NO_DATE;
890 58 SweepStart = 1;
891 58 SweepEnd = 365;
892
893 // Reporting options
894 58 RptFlags.disabled = FALSE;
895 58 RptFlags.input = FALSE;
896 58 RptFlags.continuity = TRUE;
897 58 RptFlags.flowStats = TRUE;
898 58 RptFlags.controls = FALSE;
899 58 RptFlags.subcatchments = FALSE;
900 58 RptFlags.nodes = FALSE;
901 58 RptFlags.links = FALSE;
902 58 RptFlags.averages = FALSE;
903
904 // Temperature data
905 58 Temp.dataSource = NO_TEMP;
906 58 Temp.tSeries = -1;
907 58 Temp.ta = 70.0;
908 58 Temp.elev = 0.0;
909 58 Temp.anglat = 40.0;
910 58 Temp.dtlong = 0.0;
911 58 Temp.tmax = MISSING;
912
913 // Wind speed data
914 58 Wind.type = MONTHLY_WIND;
915
2/2
✓ Branch 0 taken 696 times.
✓ Branch 1 taken 58 times.
754 for ( i=0; i<12; i++ ) Wind.aws[i] = 0.0;
916
917 // Snowmelt parameters
918 58 Snow.snotmp = 34.0;
919 58 Snow.tipm = 0.5;
920 58 Snow.rnm = 0.6;
921
922 // Snow areal depletion curves for pervious and impervious surfaces
923
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 58 times.
174 for ( i=0; i<2; i++ )
924 {
925
2/2
✓ Branch 0 taken 1160 times.
✓ Branch 1 taken 116 times.
1276 for ( j=0; j<10; j++) Snow.adc[i][j] = 1.0;
926 }
927
928 // Evaporation rates
929 58 Evap.type = CONSTANT_EVAP;
930
2/2
✓ Branch 0 taken 696 times.
✓ Branch 1 taken 58 times.
754 for (i=0; i<12; i++)
931 {
932 696 Evap.monthlyEvap[i] = 0.0;
933 696 Evap.panCoeff[i] = 1.0;
934 }
935 58 Evap.recoveryPattern = -1;
936 58 Evap.recoveryFactor = 1.0;
937 58 Evap.tSeries = -1;
938 58 Evap.dryOnly = FALSE;
939
940 // Climate adjustments
941
2/2
✓ Branch 0 taken 696 times.
✓ Branch 1 taken 58 times.
754 for (i = 0; i < 12; i++)
942 {
943 696 Adjust.temp[i] = 0.0; // additive adjustments
944 696 Adjust.evap[i] = 0.0; // additive adjustments
945 696 Adjust.rain[i] = 1.0; // multiplicative adjustments
946 696 Adjust.hydcon[i] = 1.0; // hyd. conductivity adjustments
947 }
948 58 Adjust.rainFactor = 1.0;
949 58 Adjust.hydconFactor = 1.0;
950 58 }
951
952 //=============================================================================
953
954 58 void openFiles(const char *f1, const char *f2, const char *f3)
955 //
956 // Input: f1 = name of input file
957 // f2 = name of report file
958 // f3 = name of binary output file
959 // Output: none
960 // Purpose: opens a project's input and report files.
961 //
962 {
963 // --- initialize file pointers to NULL
964 58 Finp.file = NULL;
965 58 Frpt.file = NULL;
966 58 Fout.file = NULL;
967
968 // --- save file names
969 58 sstrncpy(Finp.name, f1, MAXFNAME);
970 58 sstrncpy(Frpt.name, f2, MAXFNAME);
971 58 sstrncpy(Fout.name, f3, MAXFNAME);
972
973 // --- check that file names are not identical
974
3/6
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 58 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 58 times.
58 if (strcomp(f1, f2) || strcomp(f1, f3) || strcomp(f2, f3))
975 {
976 writecon(FMT11);
977 ErrorCode = ERR_FILE_NAME;
978 return;
979 }
980
981 // --- open input and report files
982
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
58 if ((Finp.file = fopen(f1,"rt")) == NULL)
983 {
984 writecon(FMT12);
985 writecon(f1);
986 ErrorCode = ERR_INP_FILE;
987 return;
988 }
989
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
58 if ((Frpt.file = fopen(f2,"wt")) == NULL)
990 {
991 writecon(FMT13);
992 ErrorCode = ERR_RPT_FILE;
993 return;
994 }
995 }
996
997 //=============================================================================
998
999 58 void createObjects()
1000 //
1001 // Input: none
1002 // Output: none
1003 // Purpose: allocates memory for project's objects.
1004 //
1005 // NOTE: number of each type of object has already been determined in
1006 // project_readInput().
1007 //
1008 {
1009 int j, k;
1010
1011 // --- allocate memory for each category of object
1012
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if ( ErrorCode ) return;
1013 58 Gage = (TGage *) calloc(Nobjects[GAGE], sizeof(TGage));
1014 58 Subcatch = (TSubcatch *) calloc(Nobjects[SUBCATCH], sizeof(TSubcatch));
1015 58 Node = (TNode *) calloc(Nobjects[NODE], sizeof(TNode));
1016 58 Outfall = (TOutfall *) calloc(Nnodes[OUTFALL], sizeof(TOutfall));
1017 58 Divider = (TDivider *) calloc(Nnodes[DIVIDER], sizeof(TDivider));
1018 58 Storage = (TStorage *) calloc(Nnodes[STORAGE], sizeof(TStorage));
1019 58 Link = (TLink *) calloc(Nobjects[LINK], sizeof(TLink));
1020 58 Conduit = (TConduit *) calloc(Nlinks[CONDUIT], sizeof(TConduit));
1021 58 Pump = (TPump *) calloc(Nlinks[PUMP], sizeof(TPump));
1022 58 Orifice = (TOrifice *) calloc(Nlinks[ORIFICE], sizeof(TOrifice));
1023 58 Weir = (TWeir *) calloc(Nlinks[WEIR], sizeof(TWeir));
1024 58 Outlet = (TOutlet *) calloc(Nlinks[OUTLET], sizeof(TOutlet));
1025 58 Pollut = (TPollut *) calloc(Nobjects[POLLUT], sizeof(TPollut));
1026 58 Landuse = (TLanduse *) calloc(Nobjects[LANDUSE], sizeof(TLanduse));
1027 58 Pattern = (TPattern *) calloc(Nobjects[TIMEPATTERN], sizeof(TPattern));
1028 58 Curve = (TTable *) calloc(Nobjects[CURVE], sizeof(TTable));
1029 58 Tseries = (TTable *) calloc(Nobjects[TSERIES], sizeof(TTable));
1030 58 Aquifer = (TAquifer *) calloc(Nobjects[AQUIFER], sizeof(TAquifer));
1031 58 UnitHyd = (TUnitHyd *) calloc(Nobjects[UNITHYD], sizeof(TUnitHyd));
1032 58 Snowmelt = (TSnowmelt *) calloc(Nobjects[SNOWMELT], sizeof(TSnowmelt));
1033 58 Shape = (TShape *) calloc(Nobjects[SHAPE], sizeof(TShape));
1034
1035 // --- create array of detailed routing event periods
1036 58 Event = (TEvent *) calloc((size_t)NumEvents+1, sizeof(TEvent));
1037 58 Event[NumEvents].start = BIG;
1038 58 Event[NumEvents].end = BIG + 1.0;
1039
1040 // --- create LID objects
1041 58 lid_create(Nobjects[LID], Nobjects[SUBCATCH]);
1042
1043 // --- create control rules
1044 58 ErrorCode = controls_create(Nobjects[CONTROL]);
1045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if ( ErrorCode ) return;
1046
1047 // --- create cross section transects
1048 58 ErrorCode = transect_create(Nobjects[TRANSECT]);
1049
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if ( ErrorCode ) return;
1050
1051 // --- create street cross sections & inlet designs
1052 58 ErrorCode = street_create(Nobjects[STREET]);
1053
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if ( ErrorCode ) return;
1054 58 ErrorCode = inlet_create(Nobjects[INLET]);
1055
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if ( ErrorCode ) return;
1056
1057 // --- allocate memory for infiltration data
1058 58 infil_create(Nobjects[SUBCATCH]);
1059
1060 // --- allocate memory for water quality state variables
1061
2/2
✓ Branch 0 taken 2393 times.
✓ Branch 1 taken 58 times.
2451 for (j = 0; j < Nobjects[SUBCATCH]; j++)
1062 {
1063 2393 Subcatch[j].initBuildup =
1064 2393 (double *) calloc(Nobjects[POLLUT], sizeof(double));
1065 2393 Subcatch[j].oldQual = (double *) calloc(Nobjects[POLLUT], sizeof(double));
1066 2393 Subcatch[j].newQual = (double *) calloc(Nobjects[POLLUT], sizeof(double));
1067 2393 Subcatch[j].pondedQual = (double *) calloc(Nobjects[POLLUT], sizeof(double));
1068 2393 Subcatch[j].totalLoad = (double *) calloc(Nobjects[POLLUT], sizeof(double));
1069 }
1070
2/2
✓ Branch 0 taken 10183 times.
✓ Branch 1 taken 58 times.
10241 for (j = 0; j < Nobjects[NODE]; j++)
1071 {
1072 10183 Node[j].oldQual = (double *) calloc(Nobjects[POLLUT], sizeof(double));
1073 10183 Node[j].newQual = (double *) calloc(Nobjects[POLLUT], sizeof(double));
1074 10183 Node[j].extInflow = NULL;
1075 10183 Node[j].dwfInflow = NULL;
1076 10183 Node[j].rdiiInflow = NULL;
1077 10183 Node[j].treatment = NULL;
1078 }
1079
2/2
✓ Branch 0 taken 10508 times.
✓ Branch 1 taken 58 times.
10566 for (j = 0; j < Nobjects[LINK]; j++)
1080 {
1081 10508 Link[j].inlet = NULL;
1082 10508 Link[j].oldQual = (double *) calloc(Nobjects[POLLUT], sizeof(double));
1083 10508 Link[j].newQual = (double *) calloc(Nobjects[POLLUT], sizeof(double));
1084 10508 Link[j].totalLoad = (double *) calloc(Nobjects[POLLUT], sizeof(double));
1085 }
1086
1087 // --- allocate memory for land use buildup/washoff functions
1088
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 58 times.
68 for (j = 0; j < Nobjects[LANDUSE]; j++)
1089 {
1090 10 Landuse[j].buildupFunc =
1091 10 (TBuildup *) calloc(Nobjects[POLLUT], sizeof(TBuildup));
1092 10 Landuse[j].washoffFunc =
1093 10 (TWashoff *) calloc(Nobjects[POLLUT], sizeof(TWashoff));
1094 }
1095
1096 // --- allocate memory for subcatchment landuse factors
1097
2/2
✓ Branch 0 taken 2393 times.
✓ Branch 1 taken 58 times.
2451 for (j = 0; j < Nobjects[SUBCATCH]; j++)
1098 {
1099 2393 Subcatch[j].landFactor =
1100 2393 (TLandFactor *) calloc(Nobjects[LANDUSE], sizeof(TLandFactor));
1101
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 2393 times.
2444 for (k = 0; k < Nobjects[LANDUSE]; k++)
1102 {
1103 51 Subcatch[j].landFactor[k].buildup =
1104 51 (double *) calloc(Nobjects[POLLUT], sizeof(double));
1105 }
1106 }
1107
1108 // --- initialize buildup & washoff functions
1109
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 58 times.
68 for (j = 0; j < Nobjects[LANDUSE]; j++)
1110 {
1111
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 10 times.
35 for (k = 0; k < Nobjects[POLLUT]; k++)
1112 {
1113 25 Landuse[j].buildupFunc[k].funcType = NO_BUILDUP;
1114 25 Landuse[j].buildupFunc[k].normalizer = PER_AREA;
1115 25 Landuse[j].washoffFunc[k].funcType = NO_WASHOFF;
1116 }
1117 }
1118
1119 // --- initialize rain gage properties
1120
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 58 times.
110 for (j = 0; j < Nobjects[GAGE]; j++)
1121 {
1122 52 Gage[j].tSeries = -1;
1123 52 sstrncpy(Gage[j].fname, "", 0);
1124 }
1125
1126 // --- initialize subcatchment properties
1127
2/2
✓ Branch 0 taken 2393 times.
✓ Branch 1 taken 58 times.
2451 for (j = 0; j < Nobjects[SUBCATCH]; j++)
1128 {
1129 2393 Subcatch[j].outSubcatch = -1;
1130 2393 Subcatch[j].outNode = -1;
1131 2393 Subcatch[j].infil = -1;
1132 2393 Subcatch[j].groundwater = NULL;
1133 2393 Subcatch[j].gwLatFlowExpr = NULL;
1134 2393 Subcatch[j].gwDeepFlowExpr = NULL;
1135 2393 Subcatch[j].snowpack = NULL;
1136 2393 Subcatch[j].lidArea = 0.0;
1137
2/2
✓ Branch 0 taken 9294 times.
✓ Branch 1 taken 2393 times.
11687 for (k = 0; k < Nobjects[POLLUT]; k++)
1138 {
1139 9294 Subcatch[j].initBuildup[k] = 0.0;
1140 }
1141 }
1142
1143 // --- initialize RDII unit hydrograph properties
1144
2/2
✓ Branch 1 taken 220 times.
✓ Branch 2 taken 58 times.
278 for ( j = 0; j < Nobjects[UNITHYD]; j++ ) rdii_initUnitHyd(j);
1145
1146 // --- initialize snowmelt properties
1147
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 58 times.
66 for ( j = 0; j < Nobjects[SNOWMELT]; j++ ) snow_initSnowmelt(j);
1148
1149 // --- initialize storage node exfiltration
1150
2/2
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 58 times.
175 for (j = 0; j < Nnodes[STORAGE]; j++) Storage[j].exfil = NULL;
1151
1152 // --- initialize link properties
1153
2/2
✓ Branch 0 taken 10508 times.
✓ Branch 1 taken 58 times.
10566 for (j = 0; j < Nobjects[LINK]; j++)
1154 {
1155 10508 Link[j].xsect.type = -1;
1156 10508 Link[j].cLossInlet = 0.0;
1157 10508 Link[j].cLossOutlet = 0.0;
1158 10508 Link[j].cLossAvg = 0.0;
1159 10508 Link[j].hasFlapGate = FALSE;
1160 }
1161
2/2
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 58 times.
164 for (j = 0; j < Nlinks[PUMP]; j++) Pump[j].pumpCurve = -1;
1162
1163 // --- initialize reporting flags
1164
2/2
✓ Branch 0 taken 2393 times.
✓ Branch 1 taken 58 times.
2451 for (j = 0; j < Nobjects[SUBCATCH]; j++) Subcatch[j].rptFlag = FALSE;
1165
2/2
✓ Branch 0 taken 10183 times.
✓ Branch 1 taken 58 times.
10241 for (j = 0; j < Nobjects[NODE]; j++) Node[j].rptFlag = FALSE;
1166
2/2
✓ Branch 0 taken 10508 times.
✓ Branch 1 taken 58 times.
10566 for (j = 0; j < Nobjects[LINK]; j++) Link[j].rptFlag = FALSE;
1167
1168 // --- initialize curves, time series, and time patterns
1169
2/2
✓ Branch 1 taken 221 times.
✓ Branch 2 taken 58 times.
279 for (j = 0; j < Nobjects[CURVE]; j++) table_init(&Curve[j]);
1170
2/2
✓ Branch 1 taken 102 times.
✓ Branch 2 taken 58 times.
160 for (j = 0; j < Nobjects[TSERIES]; j++) table_init(&Tseries[j]);
1171
2/2
✓ Branch 1 taken 452 times.
✓ Branch 2 taken 58 times.
510 for (j = 0; j < Nobjects[TIMEPATTERN]; j++) inflow_initDwfPattern(j);
1172 }
1173
1174 //=============================================================================
1175
1176 58 void deleteObjects()
1177 //
1178 // Input: none
1179 // Output: none
1180 // Purpose: frees memory allocated for a project's objects.
1181 //
1182 // NOTE: care is taken to first free objects that are properties of another
1183 // object before the latter is freed (e.g., we must free a
1184 // subcatchment's land use factors before freeing the subcatchment).
1185 //
1186 {
1187 int j, k;
1188
1189 // --- free memory for landuse factors & groundwater
1190
3/4
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2393 times.
✓ Branch 3 taken 58 times.
2451 if ( Subcatch ) for (j = 0; j < Nobjects[SUBCATCH]; j++)
1191 {
1192
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 2393 times.
2444 for (k = 0; k < Nobjects[LANDUSE]; k++)
1193 {
1194
1/2
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
51 FREE(Subcatch[j].landFactor[k].buildup);
1195 }
1196
1/2
✓ Branch 0 taken 2393 times.
✗ Branch 1 not taken.
2393 FREE(Subcatch[j].landFactor);
1197
2/2
✓ Branch 0 taken 2241 times.
✓ Branch 1 taken 152 times.
2393 FREE(Subcatch[j].groundwater);
1198 2393 gwater_deleteFlowExpression(j);
1199
2/2
✓ Branch 0 taken 2304 times.
✓ Branch 1 taken 89 times.
2393 FREE(Subcatch[j].snowpack);
1200 }
1201
1202 // --- free memory for buildup/washoff functions
1203
3/4
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 58 times.
68 if ( Landuse ) for (j = 0; j < Nobjects[LANDUSE]; j++)
1204 {
1205
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 FREE(Landuse[j].buildupFunc);
1206
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 FREE(Landuse[j].washoffFunc)
1207 }
1208
1209 // --- free memory for water quality state variables
1210
3/4
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2393 times.
✓ Branch 3 taken 58 times.
2451 if ( Subcatch ) for (j = 0; j < Nobjects[SUBCATCH]; j++)
1211 {
1212
1/2
✓ Branch 0 taken 2393 times.
✗ Branch 1 not taken.
2393 FREE(Subcatch[j].initBuildup);
1213
1/2
✓ Branch 0 taken 2393 times.
✗ Branch 1 not taken.
2393 FREE(Subcatch[j].oldQual);
1214
1/2
✓ Branch 0 taken 2393 times.
✗ Branch 1 not taken.
2393 FREE(Subcatch[j].newQual);
1215
1/2
✓ Branch 0 taken 2393 times.
✗ Branch 1 not taken.
2393 FREE(Subcatch[j].pondedQual);
1216
1/2
✓ Branch 0 taken 2393 times.
✗ Branch 1 not taken.
2393 FREE(Subcatch[j].totalLoad);
1217 }
1218
3/4
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10183 times.
✓ Branch 3 taken 58 times.
10241 if ( Node ) for (j = 0; j < Nobjects[NODE]; j++)
1219 {
1220
1/2
✓ Branch 0 taken 10183 times.
✗ Branch 1 not taken.
10183 FREE(Node[j].oldQual);
1221
1/2
✓ Branch 0 taken 10183 times.
✗ Branch 1 not taken.
10183 FREE(Node[j].newQual);
1222 }
1223
3/4
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10508 times.
✓ Branch 3 taken 58 times.
10566 if ( Link ) for (j = 0; j < Nobjects[LINK]; j++)
1224 {
1225
1/2
✓ Branch 0 taken 10508 times.
✗ Branch 1 not taken.
10508 FREE(Link[j].oldQual);
1226
1/2
✓ Branch 0 taken 10508 times.
✗ Branch 1 not taken.
10508 FREE(Link[j].newQual);
1227
1/2
✓ Branch 0 taken 10508 times.
✗ Branch 1 not taken.
10508 FREE(Link[j].totalLoad);
1228 // Any inlet assigned to Link[j].inlet is freed in inlet_delete().
1229 }
1230
1231 // --- free memory used for rainfall infiltration
1232 58 infil_delete();
1233
1234 // --- free memory used for storage exfiltration
1235
3/4
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 117 times.
✓ Branch 3 taken 58 times.
175 if ( Node ) for (j = 0; j < Nnodes[STORAGE]; j++)
1236 {
1237
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 114 times.
117 if ( Storage[j].exfil )
1238 {
1239
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 FREE(Storage[j].exfil->btmExfil);
1240
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 FREE(Storage[j].exfil->bankExfil);
1241
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 FREE(Storage[j].exfil);
1242 }
1243 }
1244
1245 // --- free memory used for outfall pollutants loads
1246
3/4
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 348 times.
✓ Branch 3 taken 58 times.
406 if ( Node ) for (j = 0; j < Nnodes[OUTFALL]; j++)
1247
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 347 times.
348 FREE(Outfall[j].wRouted);
1248
1249 // --- free memory used for nodal inflows & treatment functions
1250
3/4
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10183 times.
✓ Branch 3 taken 58 times.
10241 if ( Node ) for (j = 0; j < Nobjects[NODE]; j++)
1251 {
1252 10183 inflow_deleteExtInflows(j);
1253 10183 inflow_deleteDwfInflows(j);
1254 10183 rdii_deleteRdiiInflow(j);
1255 10183 treatmnt_delete(j);
1256 }
1257
1258 // --- delete table entries for curves and time series
1259
3/4
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 102 times.
✓ Branch 3 taken 58 times.
160 if ( Tseries ) for (j = 0; j < Nobjects[TSERIES]; j++)
1260 102 table_deleteEntries(&Tseries[j]);
1261
3/4
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 221 times.
✓ Branch 3 taken 58 times.
279 if ( Curve ) for (j = 0; j < Nobjects[CURVE]; j++)
1262 221 table_deleteEntries(&Curve[j]);
1263
1264 // --- delete cross section transects
1265 58 transect_delete();
1266
1267 // --- delete street and inlet design objects
1268 58 street_delete();
1269 58 inlet_delete();
1270
1271 // --- delete control rules
1272 58 controls_delete();
1273
1274 // --- delete LIDs
1275 58 lid_delete();
1276
1277 // --- now free each major category of object
1278
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(Gage);
1279
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(Subcatch);
1280
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(Node);
1281
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(Outfall);
1282
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(Divider);
1283
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(Storage);
1284
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(Link);
1285
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(Conduit);
1286
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(Pump);
1287
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(Orifice);
1288
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(Weir);
1289
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(Outlet);
1290
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(Pollut);
1291
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(Landuse);
1292
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(Pattern);
1293
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(Curve);
1294
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(Tseries);
1295
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(Aquifer);
1296
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(UnitHyd);
1297
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(Snowmelt);
1298
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(Shape);
1299
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 FREE(Event);
1300 58 }
1301
1302 //=============================================================================
1303
1304 58 void createHashTables()
1305 //
1306 // Input: none
1307 // Output: returns error code
1308 // Purpose: allocates memory for object ID hash tables
1309 //
1310 { int j;
1311 58 MemPoolAllocated = FALSE;
1312
2/2
✓ Branch 0 taken 1044 times.
✓ Branch 1 taken 58 times.
1102 for (j = 0; j < MAX_OBJ_TYPES ; j++)
1313 {
1314 1044 Htable[j] = HTcreate();
1315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1044 times.
1044 if ( Htable[j] == NULL ) report_writeErrorMsg(ERR_MEMORY, "");
1316 }
1317
1318 // --- initialize memory pool used to store object ID's
1319
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
58 if ( AllocInit() == NULL ) report_writeErrorMsg(ERR_MEMORY, "");
1320 58 else MemPoolAllocated = TRUE;
1321 58 }
1322
1323 //=============================================================================
1324
1325 58 void deleteHashTables()
1326 //
1327 // Input: none
1328 // Output: none
1329 // Purpose: frees memory allocated for object ID hash tables
1330 //
1331 {
1332 int j;
1333
2/2
✓ Branch 0 taken 1044 times.
✓ Branch 1 taken 58 times.
1102 for (j = 0; j < MAX_OBJ_TYPES; j++)
1334 {
1335
1/2
✓ Branch 0 taken 1044 times.
✗ Branch 1 not taken.
1044 if ( Htable[j] != NULL ) HTfree(Htable[j]);
1336 }
1337
1338 // --- free object ID memory pool
1339
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 if ( MemPoolAllocated ) AllocFreePool();
1340 58 }
1341
1342 //=============================================================================
1343