GCC Code Coverage Report


Directory: src/solver/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 91.4% 594 / 0 / 650
Functions: 100.0% 18 / 0 / 18
Branches: 69.0% 320 / 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 61 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 61 initPointers();
123 61 setDefaults();
124 61 openFiles(f1, f2, f3);
125 61 }
126
127 //=============================================================================
128
129 61 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 61 createHashTables();
138
139 // --- count number of objects in input file and create them
140 61 input_countObjects();
141 61 createObjects();
142
143 // --- read project data from input file
144 61 input_readData();
145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if ( ErrorCode ) return;
146
147 // --- establish starting & ending date/time
148 61 StartDateTime = StartDate + StartTime;
149 61 EndDateTime = EndDate + EndTime;
150 61 ReportStart = ReportStartDate + ReportStartTime;
151
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 ReportStart = MAX(ReportStart, StartDateTime);
152
153 // --- check for valid starting & ending date/times
154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if ( EndDateTime <= StartDateTime )
155 {
156 report_writeErrorMsg(ERR_START_DATE, "");
157 }
158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 else if ( EndDateTime <= ReportStart )
159 {
160 report_writeErrorMsg(ERR_REPORT_DATE, "");
161 }
162 else
163 {
164 // --- compute total duration of simulation in seconds
165 61 TotalDuration = floor((EndDateTime - StartDateTime) * SECperDAY);
166
167 // --- reporting step must be <= total duration
168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 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 61 times.
61 if ( (double)ReportStep < RouteStep )
175 {
176 report_writeErrorMsg(ERR_REPORT_STEP, "");
177 }
178
179 // --- convert total duration to milliseconds
180 61 TotalDuration *= 1000.0;
181 }
182 }
183
184 //=============================================================================
185
186 61 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 63 times.
✓ Branch 1 taken 61 times.
124 for ( i=0; i<Nobjects[CURVE]; i++ )
199 {
200 63 err = table_validate(&Curve[i]);
201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if ( err ) report_writeErrorMsg(ERR_CURVE_SEQUENCE, Curve[i].ID);
202 }
203
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 61 times.
193 for ( i=0; i<Nobjects[TSERIES]; i++ )
204 {
205 132 err = table_validate(&Tseries[i]);
206
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 132 times.
132 if ( err ) report_writeTseriesErrorMsg(err, &Tseries[i]);
207 }
208
209 // --- validate hydrology objects
210 // (NOTE: order is important !!!!)
211 61 climate_validate();
212 61 lid_validate();
213
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 2 times.
61 if ( Nobjects[SNOWMELT] == 0 ) IgnoreSnowmelt = TRUE;
214
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 3 times.
61 if ( Nobjects[AQUIFER] == 0 ) IgnoreGwater = TRUE;
215
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 61 times.
65 for ( i=0; i<Nobjects[AQUIFER]; i++ ) gwater_validateAquifer(i);
216
2/2
✓ Branch 1 taken 96 times.
✓ Branch 2 taken 61 times.
157 for ( i=0; i<Nobjects[SUBCATCH]; i++ ) subcatch_validate(i);
217
2/2
✓ Branch 1 taken 40 times.
✓ Branch 2 taken 61 times.
101 for ( i=0; i<Nobjects[GAGE]; i++ ) gage_validate(i);
218
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 61 times.
64 for ( i=0; i<Nobjects[SNOWMELT]; i++ ) snow_validateSnowmelt(i);
219
220 // --- compute geometry tables for each shape curve
221 61 j = 0;
222
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 61 times.
124 for ( i=0; i<Nobjects[CURVE]; i++ )
223 {
224
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 59 times.
63 if ( Curve[i].curveType == SHAPE_CURVE )
225 {
226 4 Curve[i].refersTo = j;
227 4 Shape[j].curve = i;
228
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ( !shape_validate(&Shape[j], &Curve[i]) )
229 report_writeErrorMsg(ERR_CURVE_SEQUENCE, Curve[i].ID);
230 4 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 423 times.
✓ Branch 1 taken 61 times.
484 for ( i=0; i<Nobjects[NODE]; i++) Node[i].oldDepth = Node[i].fullDepth;
237
2/2
✓ Branch 1 taken 332 times.
✓ Branch 2 taken 61 times.
393 for ( i=0; i<Nobjects[LINK]; i++) link_validate(i);
238
2/2
✓ Branch 1 taken 423 times.
✓ Branch 2 taken 61 times.
484 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 61 times.
61 if ( DryStep < WetStep )
242 {
243 report_writeWarningMsg(WARN06, "");
244 DryStep = WetStep;
245 }
246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 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 45 times.
✓ Branch 1 taken 16 times.
61 if ( RptFlags.subcatchments == ALL )
254
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 45 times.
141 for (i=0; i<Nobjects[SUBCATCH]; i++) Subcatch[i].rptFlag = 1;
255
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 if (RptFlags.nodes == ALL)
256
2/2
✓ Branch 0 taken 423 times.
✓ Branch 1 taken 61 times.
484 for (i = 0; i < Nobjects[NODE]; i++) Node[i].rptFlag = 1;
257
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 1 time.
61 if ( RptFlags.links == ALL )
258
2/2
✓ Branch 0 taken 332 times.
✓ Branch 1 taken 60 times.
392 for (i=0; i<Nobjects[LINK]; i++) Link[i].rptFlag = 1;
259
260 // --- validate dynamic wave options
261
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 17 times.
61 if ( RouteModel == DW ) dynwave_validate();
262
263 // --- validate street/channel inlets
264 61 inlet_validate();
265
266 // --- adjust number of parallel threads to be used
267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if ( NumThreads == 0 ) NumThreads = omp_get_max_threads();
268
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
61 else NumThreads = MIN(NumThreads, omp_get_max_threads());
269
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 12 times.
61 if ( Nobjects[LINK] < 4 * NumThreads ) NumThreads = 1;
270 61 }
271
272 //=============================================================================
273
274 61 void project_close()
275 //
276 // Input: none
277 // Output: none
278 // Purpose: closes a SWMM project.
279 //
280 {
281 61 deleteObjects();
282 61 deleteHashTables();
283 61 }
284
285 //=============================================================================
286
287 61 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 61 climate_initState();
296 61 lid_initState();
297
2/2
✓ Branch 1 taken 132 times.
✓ Branch 2 taken 61 times.
193 for (j=0; j<Nobjects[TSERIES]; j++) table_tseriesInit(&Tseries[j]);
298
2/2
✓ Branch 1 taken 40 times.
✓ Branch 2 taken 61 times.
101 for (j=0; j<Nobjects[GAGE]; j++) gage_initState(j);
299 61 k = 1;
300
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 61 times.
157 for (j=0; j<Nobjects[SUBCATCH]; j++)
301 {
302 96 subcatch_initState(j);
303
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 if (Subcatch[j].rptFlag > 0)
304 {
305 96 Subcatch[j].rptFlag = k;
306 96 k++;
307 }
308 }
309 61 k = 1;
310
2/2
✓ Branch 0 taken 423 times.
✓ Branch 1 taken 61 times.
484 for (j=0; j<Nobjects[NODE]; j++)
311 {
312 423 node_initState(j);
313
1/2
✓ Branch 0 taken 423 times.
✗ Branch 1 not taken.
423 if (Node[j].rptFlag > 0)
314 {
315 423 Node[j].rptFlag = k;
316 423 k++;
317 }
318 }
319 61 k = 1;
320
2/2
✓ Branch 0 taken 332 times.
✓ Branch 1 taken 61 times.
393 for (j=0; j<Nobjects[LINK]; j++)
321 {
322 332 link_initState(j);
323
1/2
✓ Branch 0 taken 332 times.
✗ Branch 1 not taken.
332 if (Link[j].rptFlag > 0)
324 {
325 332 Link[j].rptFlag = k;
326 332 k++;
327 }
328 }
329 61 return ErrorCode;
330 }
331
332 //=============================================================================
333
334 1250 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 1250 times.
1250 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 1250 len = (long)strlen(id);
353 1250 newID = (char *) Alloc((len+1)*sizeof(char));
354 1250 sstrncpy(newID, id, len);
355
356 // --- insert object's ID into the hash table for that type of object
357 1250 result = HTinsert(Htable[type], newID, n);
358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1250 times.
1250 if ( result == 0 ) result = -1;
359 1250 return result;
360 }
361
362 //=============================================================================
363
364 20085 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 20085 return HTfind(Htable[type], id);
373 }
374
375 //=============================================================================
376
377 1251 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 1251 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 1537 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 1537 k = findmatch(s1, OptionWords);
463
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1537 times.
1537 if ( k < 0 ) return error_setInpError(ERR_KEYWORD, s1);
464
28/31
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 57 times.
✓ Branch 2 taken 61 times.
✓ Branch 3 taken 61 times.
✓ Branch 4 taken 61 times.
✓ Branch 5 taken 61 times.
✓ Branch 6 taken 61 times.
✓ Branch 7 taken 61 times.
✓ Branch 8 taken 61 times.
✓ Branch 9 taken 68 times.
✓ Branch 10 taken 47 times.
✓ Branch 11 taken 199 times.
✓ Branch 12 taken 34 times.
✓ Branch 13 taken 105 times.
✓ Branch 14 taken 35 times.
✓ Branch 15 taken 34 times.
✓ Branch 16 taken 51 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 94 times.
✓ Branch 19 taken 35 times.
✓ Branch 20 taken 61 times.
✓ Branch 21 taken 39 times.
✓ Branch 22 taken 36 times.
✓ Branch 23 taken 33 times.
✓ Branch 24 taken 32 times.
✓ Branch 25 taken 32 times.
✓ Branch 26 taken 28 times.
✓ Branch 27 taken 28 times.
✓ Branch 28 taken 1 time.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
1537 switch ( k )
465 {
466 // --- choice of flow units
467 61 case FLOW_UNITS:
468 61 m = findmatch(s2, FlowUnitWords);
469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if ( m < 0 ) return error_setInpError(ERR_KEYWORD, s2);
470 61 FlowUnits = m;
471
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 3 times.
61 if ( FlowUnits <= MGD ) UnitSystem = US;
472 3 else UnitSystem = SI;
473 61 break;
474
475 // --- choice of infiltration modeling method
476 57 case INFIL_MODEL:
477 57 m = findmatch(s2, InfilModelWords);
478
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if ( m < 0 ) return error_setInpError(ERR_KEYWORD, s2);
479 57 InfilModel = m;
480 57 break;
481
482 // --- choice of flow routing method
483 61 case ROUTE_MODEL:
484 61 m = findmatch(s2, RouteModelWords);
485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if ( m < 0 ) m = findmatch(s2, OldRouteModelWords);
486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if ( m < 0 ) return error_setInpError(ERR_KEYWORD, s2);
487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if ( m == NO_ROUTING ) IgnoreRouting = TRUE;
488 61 else RouteModel = m;
489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if ( RouteModel == EKW ) RouteModel = KW;
490 61 break;
491
492 // --- simulation start date
493 61 case START_DATE:
494
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
61 if ( !datetime_strToDate(s2, &StartDate) )
495 {
496 return error_setInpError(ERR_DATETIME, s2);
497 }
498 61 break;
499
500 // --- simulation start time of day
501 61 case START_TIME:
502
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
61 if ( !datetime_strToTime(s2, &StartTime) )
503 {
504 return error_setInpError(ERR_DATETIME, s2);
505 }
506 61 break;
507
508 // --- simulation ending date
509 61 case END_DATE:
510
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
61 if ( !datetime_strToDate(s2, &EndDate) )
511 {
512 return error_setInpError(ERR_DATETIME, s2);
513 }
514 61 break;
515
516 // --- simulation ending time of day
517 61 case END_TIME:
518
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
61 if ( !datetime_strToTime(s2, &EndTime) )
519 {
520 return error_setInpError(ERR_DATETIME, s2);
521 }
522 61 break;
523
524 // --- reporting start date
525 61 case REPORT_START_DATE:
526
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
61 if ( !datetime_strToDate(s2, &ReportStartDate) )
527 {
528 return error_setInpError(ERR_DATETIME, s2);
529 }
530 61 break;
531
532 // --- reporting start time of day
533 61 case REPORT_START_TIME:
534
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
61 if ( !datetime_strToTime(s2, &ReportStartTime) )
535 {
536 return error_setInpError(ERR_DATETIME, s2);
537 }
538 61 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 68 case SWEEP_START:
544 case SWEEP_END:
545 68 sstrncpy(strDate, s2, 24);
546 68 sstrcat(strDate, "/1947", 25);
547
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
68 if ( !datetime_strToDate(strDate, &aDate) )
548 {
549 return error_setInpError(ERR_DATETIME, s2);
550 }
551 68 m = datetime_dayOfYear(aDate);
552
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 34 times.
68 if ( k == SWEEP_START ) SweepStart = m;
553 34 else SweepEnd = m;
554 68 break;
555
556 // --- number of antecedent dry days
557 47 case START_DRY_DAYS:
558 47 StartDryDays = atof(s2);
559
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 if ( StartDryDays < 0.0 )
560 {
561 return error_setInpError(ERR_NUMBER, s2);
562 }
563 47 break;
564
565 // --- runoff or reporting time steps
566 // (input is in hrs:min:sec format, time step saved as seconds)
567 199 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 199 times.
199 if ( !datetime_strToTime(s2, &aTime) )
572 {
573 return error_setInpError(ERR_DATETIME, s2);
574 }
575 199 datetime_decodeTime(aTime, &h, &m, &s);
576 199 h += 24*(int)aTime;
577 199 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 16 times.
✓ Branch 1 taken 183 times.
199 if (k == RULE_STEP)
581 {
582
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (s < 0) return error_setInpError(ERR_NUMBER, s2);
583 }
584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 183 times.
183 else if ( s <= 0 ) return error_setInpError(ERR_NUMBER, s2);
585
586
4/5
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 61 times.
✓ Branch 2 taken 61 times.
✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
199 switch ( k )
587 {
588 61 case WET_STEP: WetStep = s; break;
589 61 case DRY_STEP: DryStep = s; break;
590 61 case REPORT_STEP: ReportStep = s; break;
591 16 case RULE_STEP: RuleStep = s; break;
592 }
593 199 break;
594
595 // --- type of damping applied to inertial terms of dynamic wave routing
596 34 case INERT_DAMPING:
597 34 m = findmatch(s2, InertDampingWords);
598
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if ( m < 0 ) return error_setInpError(ERR_KEYWORD, s2);
599 34 else InertDamping = m;
600 34 break;
601
602 // --- Yes/No options (NO = 0, YES = 1)
603 105 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 105 m = findmatch(s2, NoYesWords);
613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 105 times.
105 if ( m < 0 ) return error_setInpError(ERR_KEYWORD, s2);
614
6/10
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 9 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
105 switch ( k )
615 {
616 36 case ALLOW_PONDING: AllowPonding = m; break;
617 case SLOPE_WEIGHTING: SlopeWeighting = m; break;
618 36 case SKIP_STEADY_STATE: SkipSteadyState = m; break;
619 8 case IGNORE_RAINFALL: IgnoreRainfall = m; break;
620 8 case IGNORE_SNOWMELT: IgnoreSnowmelt = m; break;
621 8 case IGNORE_GWATER: IgnoreGwater = m; break;
622 case IGNORE_ROUTING: IgnoreRouting = m; break;
623 9 case IGNORE_QUALITY: IgnoreQuality = m; break;
624 case IGNORE_RDII: IgnoreRDII = m; break;
625 }
626 105 break;
627
628 35 case NORMAL_FLOW_LTD:
629 35 m = findmatch(s2, NormalFlowWords);
630
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if ( m < 0 ) return error_setInpError(ERR_KEYWORD, s2);
631 35 NormalFlowLtd = m;
632 35 break;
633
634 34 case FORCE_MAIN_EQN:
635 34 m = findmatch(s2, ForceMainEqnWords);
636
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if ( m < 0 ) return error_setInpError(ERR_KEYWORD, s2);
637 34 ForceMainEqn = m;
638 34 break;
639
640 51 case LINK_OFFSETS:
641 51 m = findmatch(s2, LinkOffsetWords);
642
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if ( m < 0 ) return error_setInpError(ERR_KEYWORD, s2);
643 51 LinkOffsets = m;
644 51 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 94 case ROUTE_STEP:
660 case LENGTHENING_STEP:
661
2/2
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 43 times.
94 if ( !getDouble(s2, &tStep) )
662 {
663
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 51 times.
51 if ( !datetime_strToTime(s2, &aTime) )
664 {
665 return error_setInpError(ERR_NUMBER, s2);
666 }
667 else
668 {
669 51 datetime_decodeTime(aTime, &h, &m, &s);
670 51 h += 24*(int)aTime;
671 51 s = s + 60*m + 3600*h;
672 51 tStep = s;
673 }
674 }
675
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 33 times.
94 if ( k == ROUTE_STEP )
676 {
677
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if ( tStep <= 0.0 ) return error_setInpError(ERR_NUMBER, s2);
678 61 RouteStep = tStep;
679 }
680
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 4 times.
33 else LengtheningStep = MAX(0.0, tStep);
681 94 break;
682
683 // --- minimum variable time step for dynamic wave routing
684 35 case MIN_ROUTE_STEP:
685
2/4
✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 35 times.
35 if ( !getDouble(s2, &MinRouteStep) || MinRouteStep < 0.0 )
686 return error_setInpError(ERR_NUMBER, s2);
687 35 break;
688
689 61 case NUM_THREADS:
690 61 m = atoi(s2);
691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if ( m < 0 ) return error_setInpError(ERR_NUMBER, s2);
692 61 NumThreads = m;
693 61 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 39 case VARIABLE_STEP:
699
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 39 times.
39 if ( !getDouble(s2, &CourantFactor) )
700 return error_setInpError(ERR_NUMBER, s2);
701
2/4
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 39 times.
39 if ( CourantFactor < 0.0 || CourantFactor > 2.0 )
702 return error_setInpError(ERR_NUMBER, s2);
703 39 break;
704
705 // --- minimum surface area (ft2 or sq. meters) associated with nodes
706 // under dynamic wave flow routing
707 36 case MIN_SURFAREA:
708
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
36 if (!getDouble(s2, &MinSurfArea))
709 return error_setInpError(ERR_NUMBER, s2);
710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (MinSurfArea < 0.0)
711 return error_setInpError(ERR_NUMBER, s2);
712 36 break;
713
714 // --- minimum conduit slope (%)
715 33 case MIN_SLOPE:
716
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
33 if ( !getDouble(s2, &MinSlope) )
717 return error_setInpError(ERR_NUMBER, s2);
718
2/4
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 33 times.
33 if ( MinSlope < 0.0 || MinSlope >= 100 )
719 return error_setInpError(ERR_NUMBER, s2);
720 33 MinSlope /= 100.0;
721 33 break;
722
723 // --- maximum trials / time step for dynamic wave routing
724 32 case MAX_TRIALS:
725 32 m = atoi(s2);
726
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if ( m < 0 ) return error_setInpError(ERR_NUMBER, s2);
727 32 MaxTrials = m;
728 32 break;
729
730 // --- head convergence tolerance for dynamic wave routing
731 32 case HEAD_TOL:
732
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 if ( !getDouble(s2, &HeadTol) )
733 {
734 return error_setInpError(ERR_NUMBER, s2);
735 }
736 32 break;
737
738 // --- steady state tolerance on system inflow - outflow
739 28 case SYS_FLOW_TOL:
740
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 if ( !getDouble(s2, &SysFlowTol) )
741 {
742 return error_setInpError(ERR_NUMBER, s2);
743 }
744 28 SysFlowTol /= 100.0;
745 28 break;
746
747 // --- steady state tolerance on nodal lateral inflow
748 28 case LAT_FLOW_TOL:
749
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 if ( !getDouble(s2, &LatFlowTol) )
750 {
751 return error_setInpError(ERR_NUMBER, s2);
752 }
753 28 LatFlowTol /= 100.0;
754 28 break;
755
756 // --- method used for surcharging in dynamic wave flow routing
757 1 case SURCHARGE_METHOD:
758 1 m = findmatch(s2, SurchargeWords);
759
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (m < 0) return error_setInpError(ERR_KEYWORD, s2);
760 1 SurchargeMethod = m;
761 1 break;
762
763 case TEMPDIR: // Temporary Directory
764 sstrncpy(TempDir, s2, MAXFNAME);
765 break;
766
767 }
768 1537 return 0;
769 }
770
771 //=============================================================================
772
773 61 void initPointers()
774 //
775 // Input: none
776 // Output: none
777 // Purpose: assigns NULL to all dynamic arrays for a new project.
778 //
779 {
780 61 Gage = NULL;
781 61 Subcatch = NULL;
782 61 Node = NULL;
783 61 Outfall = NULL;
784 61 Divider = NULL;
785 61 Storage = NULL;
786 61 Link = NULL;
787 61 Conduit = NULL;
788 61 Pump = NULL;
789 61 Orifice = NULL;
790 61 Weir = NULL;
791 61 Outlet = NULL;
792 61 Pollut = NULL;
793 61 Landuse = NULL;
794 61 Pattern = NULL;
795 61 Curve = NULL;
796 61 Tseries = NULL;
797 61 Transect = NULL;
798 61 Shape = NULL;
799 61 Aquifer = NULL;
800 61 UnitHyd = NULL;
801 61 Snowmelt = NULL;
802 61 Event = NULL;
803 61 MemPoolAllocated = FALSE;
804 61 }
805
806 //=============================================================================
807
808 61 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 183 times.
✓ Branch 2 taken 61 times.
244 for (i = 0; i < MAXTITLE; i++) sstrncpy(Title[i], "", 0);
819 61 sstrncpy(TempDir, "", 0);
820
821 // Interface files
822 61 Frain.mode = SCRATCH_FILE; // Use scratch rainfall file
823 61 Fclimate.mode = NO_FILE;
824 61 Frunoff.mode = NO_FILE;
825 61 Frdii.mode = NO_FILE;
826 61 Fhotstart1.mode = NO_FILE;
827 61 Fhotstart2.mode = NO_FILE;
828 61 Finflows.mode = NO_FILE;
829 61 Foutflows.mode = NO_FILE;
830 61 Frain.file = NULL;
831 61 Fclimate.file = NULL;
832 61 Frunoff.file = NULL;
833 61 Frdii.file = NULL;
834 61 Fhotstart1.file = NULL;
835 61 Fhotstart2.file = NULL;
836 61 Finflows.file = NULL;
837 61 Foutflows.file = NULL;
838 61 Fout.file = NULL;
839 61 Fout.mode = NO_FILE;
840
841 // Analysis options
842 61 UnitSystem = US; // US unit system
843 61 FlowUnits = CFS; // CFS flow units
844 61 InfilModel = HORTON; // Horton infiltration method
845 61 RouteModel = DW; // Dynamic wave flow routing method
846 61 SurchargeMethod = EXTRAN; // Use EXTRAN method for surcharging
847 61 CrownCutoff = 0.96; // Fractional pipe crown cutoff
848 61 AllowPonding = FALSE; // No ponding at nodes
849 61 InertDamping = PARTIAL_DAMPING; // Partial inertial damping
850 61 NormalFlowLtd = BOTH; // Default normal flow limitation
851 61 ForceMainEqn = H_W; // Hazen-Williams eqn. for force mains
852 61 LinkOffsets = DEPTH_OFFSET; // Use depth for link offsets
853 61 LengtheningStep = 0; // No lengthening of conduits
854 61 CourantFactor = 0.75; // Variable time step reduced to 75%
855 61 MinSurfArea = 0.0; // Force use of default min. surface area
856 61 MinSlope = 0.0; // No user supplied minimum conduit slope
857 61 SkipSteadyState = FALSE; // Do flow routing in steady state periods
858 61 IgnoreRainfall = FALSE; // Analyze rainfall/runoff
859 61 IgnoreRDII = FALSE; // Analyze RDII
860 61 IgnoreSnowmelt = FALSE; // Analyze snowmelt
861 61 IgnoreGwater = FALSE; // Analyze groundwater
862 61 IgnoreRouting = FALSE; // Analyze flow routing
863 61 IgnoreQuality = FALSE; // Analyze water quality
864 61 WetStep = 300; // Runoff wet time step (secs)
865 61 DryStep = 3600; // Runoff dry time step (secs)
866 61 RuleStep = 0; // Rules evaluated at each routing step
867 61 RouteStep = 20; // Routing time step (secs)
868 61 MinRouteStep = 0.5; // Minimum variable time step (sec)
869 61 ReportStep = 900; // Reporting time step (secs)
870 61 StartDryDays = 0.0; // Antecedent dry days
871 61 MaxTrials = 0; // Force use of default max. trials
872 61 HeadTol = 0.0; // Force use of default head tolerance
873 61 SysFlowTol = 0.05; // System flow tolerance for steady state
874 61 LatFlowTol = 0.05; // Lateral flow tolerance for steady state
875 61 NumThreads = 1; // Number of parallel threads to use
876 61 NumEvents = 0; // Number of detailed routing events
877
878 // Deprecated options
879 61 SlopeWeighting = TRUE; // Use slope weighting
880 61 Compatibility = SWMM4; // Use SWMM 4 up/dn weighting method
881
882 // Starting & ending date/time
883 61 StartDate = datetime_encodeDate(2004, 1, 1);
884 61 StartTime = datetime_encodeTime(0,0,0);
885 61 StartDateTime = StartDate + StartTime;
886 61 EndDate = StartDate;
887 61 EndTime = 0.0;
888 61 ReportStartDate = NO_DATE;
889 61 ReportStartTime = NO_DATE;
890 61 SweepStart = 1;
891 61 SweepEnd = 365;
892
893 // Reporting options
894 61 RptFlags.disabled = FALSE;
895 61 RptFlags.input = FALSE;
896 61 RptFlags.continuity = TRUE;
897 61 RptFlags.flowStats = TRUE;
898 61 RptFlags.controls = FALSE;
899 61 RptFlags.subcatchments = FALSE;
900 61 RptFlags.nodes = FALSE;
901 61 RptFlags.links = FALSE;
902 61 RptFlags.averages = FALSE;
903
904 // Temperature data
905 61 Temp.dataSource = NO_TEMP;
906 61 Temp.tSeries = -1;
907 61 Temp.ta = 70.0;
908 61 Temp.elev = 0.0;
909 61 Temp.anglat = 40.0;
910 61 Temp.dtlong = 0.0;
911 61 Temp.tmax = MISSING;
912
913 // Wind speed data
914 61 Wind.type = MONTHLY_WIND;
915
2/2
✓ Branch 0 taken 732 times.
✓ Branch 1 taken 61 times.
793 for ( i=0; i<12; i++ ) Wind.aws[i] = 0.0;
916
917 // Snowmelt parameters
918 61 Snow.snotmp = 34.0;
919 61 Snow.tipm = 0.5;
920 61 Snow.rnm = 0.6;
921
922 // Snow areal depletion curves for pervious and impervious surfaces
923
2/2
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 61 times.
183 for ( i=0; i<2; i++ )
924 {
925
2/2
✓ Branch 0 taken 1220 times.
✓ Branch 1 taken 122 times.
1342 for ( j=0; j<10; j++) Snow.adc[i][j] = 1.0;
926 }
927
928 // Evaporation rates
929 61 Evap.type = CONSTANT_EVAP;
930
2/2
✓ Branch 0 taken 732 times.
✓ Branch 1 taken 61 times.
793 for (i=0; i<12; i++)
931 {
932 732 Evap.monthlyEvap[i] = 0.0;
933 732 Evap.panCoeff[i] = 1.0;
934 }
935 61 Evap.recoveryPattern = -1;
936 61 Evap.recoveryFactor = 1.0;
937 61 Evap.tSeries = -1;
938 61 Evap.dryOnly = FALSE;
939
940 // Climate adjustments
941
2/2
✓ Branch 0 taken 732 times.
✓ Branch 1 taken 61 times.
793 for (i = 0; i < 12; i++)
942 {
943 732 Adjust.temp[i] = 0.0; // additive adjustments
944 732 Adjust.evap[i] = 0.0; // additive adjustments
945 732 Adjust.rain[i] = 1.0; // multiplicative adjustments
946 732 Adjust.hydcon[i] = 1.0; // hyd. conductivity adjustments
947 }
948 61 Adjust.rainFactor = 1.0;
949 61 Adjust.hydconFactor = 1.0;
950 61 }
951
952 //=============================================================================
953
954 61 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 61 Finp.file = NULL;
965 61 Frpt.file = NULL;
966 61 Fout.file = NULL;
967
968 // --- save file names
969 61 sstrncpy(Finp.name, f1, MAXFNAME);
970 61 sstrncpy(Frpt.name, f2, MAXFNAME);
971 61 sstrncpy(Fout.name, f3, MAXFNAME);
972
973 // --- check that file names are not identical
974
3/6
✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 61 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 61 times.
61 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 61 times.
61 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 61 times.
61 if ((Frpt.file = fopen(f2,"wt")) == NULL)
990 {
991 writecon(FMT13);
992 ErrorCode = ERR_RPT_FILE;
993 return;
994 }
995 }
996
997 //=============================================================================
998
999 61 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 61 times.
61 if ( ErrorCode ) return;
1013 61 Gage = (TGage *) calloc(Nobjects[GAGE], sizeof(TGage));
1014 61 Subcatch = (TSubcatch *) calloc(Nobjects[SUBCATCH], sizeof(TSubcatch));
1015 61 Node = (TNode *) calloc(Nobjects[NODE], sizeof(TNode));
1016 61 Outfall = (TOutfall *) calloc(Nnodes[OUTFALL], sizeof(TOutfall));
1017 61 Divider = (TDivider *) calloc(Nnodes[DIVIDER], sizeof(TDivider));
1018 61 Storage = (TStorage *) calloc(Nnodes[STORAGE], sizeof(TStorage));
1019 61 Link = (TLink *) calloc(Nobjects[LINK], sizeof(TLink));
1020 61 Conduit = (TConduit *) calloc(Nlinks[CONDUIT], sizeof(TConduit));
1021 61 Pump = (TPump *) calloc(Nlinks[PUMP], sizeof(TPump));
1022 61 Orifice = (TOrifice *) calloc(Nlinks[ORIFICE], sizeof(TOrifice));
1023 61 Weir = (TWeir *) calloc(Nlinks[WEIR], sizeof(TWeir));
1024 61 Outlet = (TOutlet *) calloc(Nlinks[OUTLET], sizeof(TOutlet));
1025 61 Pollut = (TPollut *) calloc(Nobjects[POLLUT], sizeof(TPollut));
1026 61 Landuse = (TLanduse *) calloc(Nobjects[LANDUSE], sizeof(TLanduse));
1027 61 Pattern = (TPattern *) calloc(Nobjects[TIMEPATTERN], sizeof(TPattern));
1028 61 Curve = (TTable *) calloc(Nobjects[CURVE], sizeof(TTable));
1029 61 Tseries = (TTable *) calloc(Nobjects[TSERIES], sizeof(TTable));
1030 61 Aquifer = (TAquifer *) calloc(Nobjects[AQUIFER], sizeof(TAquifer));
1031 61 UnitHyd = (TUnitHyd *) calloc(Nobjects[UNITHYD], sizeof(TUnitHyd));
1032 61 Snowmelt = (TSnowmelt *) calloc(Nobjects[SNOWMELT], sizeof(TSnowmelt));
1033 61 Shape = (TShape *) calloc(Nobjects[SHAPE], sizeof(TShape));
1034
1035 // --- create array of detailed routing event periods
1036 61 Event = (TEvent *) calloc((size_t)NumEvents+1, sizeof(TEvent));
1037 61 Event[NumEvents].start = BIG;
1038 61 Event[NumEvents].end = BIG + 1.0;
1039
1040 // --- create LID objects
1041 61 lid_create(Nobjects[LID], Nobjects[SUBCATCH]);
1042
1043 // --- create control rules
1044 61 ErrorCode = controls_create(Nobjects[CONTROL]);
1045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if ( ErrorCode ) return;
1046
1047 // --- create cross section transects
1048 61 ErrorCode = transect_create(Nobjects[TRANSECT]);
1049
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if ( ErrorCode ) return;
1050
1051 // --- create street cross sections & inlet designs
1052 61 ErrorCode = street_create(Nobjects[STREET]);
1053
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if ( ErrorCode ) return;
1054 61 ErrorCode = inlet_create(Nobjects[INLET]);
1055
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if ( ErrorCode ) return;
1056
1057 // --- allocate memory for infiltration data
1058 61 infil_create(Nobjects[SUBCATCH]);
1059
1060 // --- allocate memory for water quality state variables
1061
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 61 times.
157 for (j = 0; j < Nobjects[SUBCATCH]; j++)
1062 {
1063 96 Subcatch[j].initBuildup =
1064 96 (double *) calloc(Nobjects[POLLUT], sizeof(double));
1065 96 Subcatch[j].oldQual = (double *) calloc(Nobjects[POLLUT], sizeof(double));
1066 96 Subcatch[j].newQual = (double *) calloc(Nobjects[POLLUT], sizeof(double));
1067 96 Subcatch[j].pondedQual = (double *) calloc(Nobjects[POLLUT], sizeof(double));
1068 96 Subcatch[j].totalLoad = (double *) calloc(Nobjects[POLLUT], sizeof(double));
1069 }
1070
2/2
✓ Branch 0 taken 423 times.
✓ Branch 1 taken 61 times.
484 for (j = 0; j < Nobjects[NODE]; j++)
1071 {
1072 423 Node[j].oldQual = (double *) calloc(Nobjects[POLLUT], sizeof(double));
1073 423 Node[j].newQual = (double *) calloc(Nobjects[POLLUT], sizeof(double));
1074 423 Node[j].extInflow = NULL;
1075 423 Node[j].dwfInflow = NULL;
1076 423 Node[j].rdiiInflow = NULL;
1077 423 Node[j].treatment = NULL;
1078 }
1079
2/2
✓ Branch 0 taken 332 times.
✓ Branch 1 taken 61 times.
393 for (j = 0; j < Nobjects[LINK]; j++)
1080 {
1081 332 Link[j].inlet = NULL;
1082 332 Link[j].oldQual = (double *) calloc(Nobjects[POLLUT], sizeof(double));
1083 332 Link[j].newQual = (double *) calloc(Nobjects[POLLUT], sizeof(double));
1084 332 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 12 times.
✓ Branch 1 taken 61 times.
73 for (j = 0; j < Nobjects[LANDUSE]; j++)
1089 {
1090 12 Landuse[j].buildupFunc =
1091 12 (TBuildup *) calloc(Nobjects[POLLUT], sizeof(TBuildup));
1092 12 Landuse[j].washoffFunc =
1093 12 (TWashoff *) calloc(Nobjects[POLLUT], sizeof(TWashoff));
1094 }
1095
1096 // --- allocate memory for subcatchment landuse factors
1097
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 61 times.
157 for (j = 0; j < Nobjects[SUBCATCH]; j++)
1098 {
1099 96 Subcatch[j].landFactor =
1100 96 (TLandFactor *) calloc(Nobjects[LANDUSE], sizeof(TLandFactor));
1101
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 96 times.
151 for (k = 0; k < Nobjects[LANDUSE]; k++)
1102 {
1103 55 Subcatch[j].landFactor[k].buildup =
1104 55 (double *) calloc(Nobjects[POLLUT], sizeof(double));
1105 }
1106 }
1107
1108 // --- initialize buildup & washoff functions
1109
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 61 times.
73 for (j = 0; j < Nobjects[LANDUSE]; j++)
1110 {
1111
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 12 times.
49 for (k = 0; k < Nobjects[POLLUT]; k++)
1112 {
1113 37 Landuse[j].buildupFunc[k].funcType = NO_BUILDUP;
1114 37 Landuse[j].buildupFunc[k].normalizer = PER_AREA;
1115 37 Landuse[j].washoffFunc[k].funcType = NO_WASHOFF;
1116 }
1117 }
1118
1119 // --- initialize rain gage properties
1120
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 61 times.
101 for (j = 0; j < Nobjects[GAGE]; j++)
1121 {
1122 40 Gage[j].tSeries = -1;
1123 40 sstrncpy(Gage[j].fname, "", 0);
1124 }
1125
1126 // --- initialize subcatchment properties
1127
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 61 times.
157 for (j = 0; j < Nobjects[SUBCATCH]; j++)
1128 {
1129 96 Subcatch[j].outSubcatch = -1;
1130 96 Subcatch[j].outNode = -1;
1131 96 Subcatch[j].infil = -1;
1132 96 Subcatch[j].groundwater = NULL;
1133 96 Subcatch[j].gwLatFlowExpr = NULL;
1134 96 Subcatch[j].gwDeepFlowExpr = NULL;
1135 96 Subcatch[j].snowpack = NULL;
1136 96 Subcatch[j].lidArea = 0.0;
1137
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 96 times.
190 for (k = 0; k < Nobjects[POLLUT]; k++)
1138 {
1139 94 Subcatch[j].initBuildup[k] = 0.0;
1140 }
1141 }
1142
1143 // --- initialize RDII unit hydrograph properties
1144
2/2
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 61 times.
76 for ( j = 0; j < Nobjects[UNITHYD]; j++ ) rdii_initUnitHyd(j);
1145
1146 // --- initialize snowmelt properties
1147
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 61 times.
64 for ( j = 0; j < Nobjects[SNOWMELT]; j++ ) snow_initSnowmelt(j);
1148
1149 // --- initialize storage node exfiltration
1150
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 61 times.
101 for (j = 0; j < Nnodes[STORAGE]; j++) Storage[j].exfil = NULL;
1151
1152 // --- initialize link properties
1153
2/2
✓ Branch 0 taken 332 times.
✓ Branch 1 taken 61 times.
393 for (j = 0; j < Nobjects[LINK]; j++)
1154 {
1155 332 Link[j].xsect.type = -1;
1156 332 Link[j].cLossInlet = 0.0;
1157 332 Link[j].cLossOutlet = 0.0;
1158 332 Link[j].cLossAvg = 0.0;
1159 332 Link[j].hasFlapGate = FALSE;
1160 }
1161
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 61 times.
70 for (j = 0; j < Nlinks[PUMP]; j++) Pump[j].pumpCurve = -1;
1162
1163 // --- initialize reporting flags
1164
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 61 times.
157 for (j = 0; j < Nobjects[SUBCATCH]; j++) Subcatch[j].rptFlag = FALSE;
1165
2/2
✓ Branch 0 taken 423 times.
✓ Branch 1 taken 61 times.
484 for (j = 0; j < Nobjects[NODE]; j++) Node[j].rptFlag = FALSE;
1166
2/2
✓ Branch 0 taken 332 times.
✓ Branch 1 taken 61 times.
393 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 63 times.
✓ Branch 2 taken 61 times.
124 for (j = 0; j < Nobjects[CURVE]; j++) table_init(&Curve[j]);
1170
2/2
✓ Branch 1 taken 132 times.
✓ Branch 2 taken 61 times.
193 for (j = 0; j < Nobjects[TSERIES]; j++) table_init(&Tseries[j]);
1171
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 61 times.
79 for (j = 0; j < Nobjects[TIMEPATTERN]; j++) inflow_initDwfPattern(j);
1172 }
1173
1174 //=============================================================================
1175
1176 61 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 61 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 96 times.
✓ Branch 3 taken 61 times.
157 if ( Subcatch ) for (j = 0; j < Nobjects[SUBCATCH]; j++)
1191 {
1192
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 96 times.
151 for (k = 0; k < Nobjects[LANDUSE]; k++)
1193 {
1194
1/2
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
55 FREE(Subcatch[j].landFactor[k].buildup);
1195 }
1196
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 FREE(Subcatch[j].landFactor);
1197
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 86 times.
96 FREE(Subcatch[j].groundwater);
1198 96 gwater_deleteFlowExpression(j);
1199
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 93 times.
96 FREE(Subcatch[j].snowpack);
1200 }
1201
1202 // --- free memory for buildup/washoff functions
1203
3/4
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 61 times.
73 if ( Landuse ) for (j = 0; j < Nobjects[LANDUSE]; j++)
1204 {
1205
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 FREE(Landuse[j].buildupFunc);
1206
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 FREE(Landuse[j].washoffFunc)
1207 }
1208
1209 // --- free memory for water quality state variables
1210
3/4
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 96 times.
✓ Branch 3 taken 61 times.
157 if ( Subcatch ) for (j = 0; j < Nobjects[SUBCATCH]; j++)
1211 {
1212
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 FREE(Subcatch[j].initBuildup);
1213
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 FREE(Subcatch[j].oldQual);
1214
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 FREE(Subcatch[j].newQual);
1215
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 FREE(Subcatch[j].pondedQual);
1216
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 FREE(Subcatch[j].totalLoad);
1217 }
1218
3/4
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 423 times.
✓ Branch 3 taken 61 times.
484 if ( Node ) for (j = 0; j < Nobjects[NODE]; j++)
1219 {
1220
1/2
✓ Branch 0 taken 423 times.
✗ Branch 1 not taken.
423 FREE(Node[j].oldQual);
1221
1/2
✓ Branch 0 taken 423 times.
✗ Branch 1 not taken.
423 FREE(Node[j].newQual);
1222 }
1223
3/4
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 332 times.
✓ Branch 3 taken 61 times.
393 if ( Link ) for (j = 0; j < Nobjects[LINK]; j++)
1224 {
1225
1/2
✓ Branch 0 taken 332 times.
✗ Branch 1 not taken.
332 FREE(Link[j].oldQual);
1226
1/2
✓ Branch 0 taken 332 times.
✗ Branch 1 not taken.
332 FREE(Link[j].newQual);
1227
1/2
✓ Branch 0 taken 332 times.
✗ Branch 1 not taken.
332 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 61 infil_delete();
1233
1234 // --- free memory used for storage exfiltration
1235
3/4
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 61 times.
101 if ( Node ) for (j = 0; j < Nnodes[STORAGE]; j++)
1236 {
1237
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 37 times.
40 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 61 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 112 times.
✓ Branch 3 taken 61 times.
173 if ( Node ) for (j = 0; j < Nnodes[OUTFALL]; j++)
1247
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 111 times.
112 FREE(Outfall[j].wRouted);
1248
1249 // --- free memory used for nodal inflows & treatment functions
1250
3/4
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 423 times.
✓ Branch 3 taken 61 times.
484 if ( Node ) for (j = 0; j < Nobjects[NODE]; j++)
1251 {
1252 423 inflow_deleteExtInflows(j);
1253 423 inflow_deleteDwfInflows(j);
1254 423 rdii_deleteRdiiInflow(j);
1255 423 treatmnt_delete(j);
1256 }
1257
1258 // --- delete table entries for curves and time series
1259
3/4
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 132 times.
✓ Branch 3 taken 61 times.
193 if ( Tseries ) for (j = 0; j < Nobjects[TSERIES]; j++)
1260 132 table_deleteEntries(&Tseries[j]);
1261
3/4
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 61 times.
124 if ( Curve ) for (j = 0; j < Nobjects[CURVE]; j++)
1262 63 table_deleteEntries(&Curve[j]);
1263
1264 // --- delete cross section transects
1265 61 transect_delete();
1266
1267 // --- delete street and inlet design objects
1268 61 street_delete();
1269 61 inlet_delete();
1270
1271 // --- delete control rules
1272 61 controls_delete();
1273
1274 // --- delete LIDs
1275 61 lid_delete();
1276
1277 // --- now free each major category of object
1278
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 FREE(Gage);
1279
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 FREE(Subcatch);
1280
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 FREE(Node);
1281
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 FREE(Outfall);
1282
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 FREE(Divider);
1283
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 FREE(Storage);
1284
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 FREE(Link);
1285
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 FREE(Conduit);
1286
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 FREE(Pump);
1287
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 FREE(Orifice);
1288
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 FREE(Weir);
1289
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 FREE(Outlet);
1290
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 FREE(Pollut);
1291
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 FREE(Landuse);
1292
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 FREE(Pattern);
1293
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 FREE(Curve);
1294
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 FREE(Tseries);
1295
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 FREE(Aquifer);
1296
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 FREE(UnitHyd);
1297
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 FREE(Snowmelt);
1298
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 FREE(Shape);
1299
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 FREE(Event);
1300 61 }
1301
1302 //=============================================================================
1303
1304 61 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 61 MemPoolAllocated = FALSE;
1312
2/2
✓ Branch 0 taken 1098 times.
✓ Branch 1 taken 61 times.
1159 for (j = 0; j < MAX_OBJ_TYPES ; j++)
1313 {
1314 1098 Htable[j] = HTcreate();
1315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1098 times.
1098 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 61 times.
61 if ( AllocInit() == NULL ) report_writeErrorMsg(ERR_MEMORY, "");
1320 61 else MemPoolAllocated = TRUE;
1321 61 }
1322
1323 //=============================================================================
1324
1325 61 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 1098 times.
✓ Branch 1 taken 61 times.
1159 for (j = 0; j < MAX_OBJ_TYPES; j++)
1334 {
1335
1/2
✓ Branch 0 taken 1098 times.
✗ Branch 1 not taken.
1098 if ( Htable[j] != NULL ) HTfree(Htable[j]);
1336 }
1337
1338 // --- free object ID memory pool
1339
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 if ( MemPoolAllocated ) AllocFreePool();
1340 61 }
1341
1342 //=============================================================================
1343