epyt-flow 0.14.1__py3-none-any.whl → 0.15.0b1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. epyt_flow/VERSION +1 -1
  2. epyt_flow/__init__.py +0 -37
  3. epyt_flow/data/benchmarks/battledim.py +2 -2
  4. epyt_flow/data/benchmarks/leakdb.py +12 -9
  5. epyt_flow/gym/scenario_control_env.py +32 -33
  6. epyt_flow/simulation/events/actuator_events.py +24 -18
  7. epyt_flow/simulation/events/leakages.py +59 -57
  8. epyt_flow/simulation/events/quality_events.py +21 -30
  9. epyt_flow/simulation/events/system_event.py +3 -3
  10. epyt_flow/simulation/scada/complex_control.py +14 -12
  11. epyt_flow/simulation/scada/custom_control.py +22 -21
  12. epyt_flow/simulation/scada/scada_data.py +108 -105
  13. epyt_flow/simulation/scada/simple_control.py +38 -31
  14. epyt_flow/simulation/scenario_simulator.py +367 -395
  15. epyt_flow/simulation/sensor_config.py +31 -32
  16. epyt_flow/topology.py +11 -10
  17. epyt_flow/uncertainty/model_uncertainty.py +146 -122
  18. {epyt_flow-0.14.1.dist-info → epyt_flow-0.15.0b1.dist-info}/METADATA +12 -18
  19. epyt_flow-0.15.0b1.dist-info/RECORD +65 -0
  20. epyt_flow/EPANET/EPANET/SRC_engines/AUTHORS +0 -60
  21. epyt_flow/EPANET/EPANET/SRC_engines/LICENSE +0 -21
  22. epyt_flow/EPANET/EPANET/SRC_engines/enumstxt.h +0 -151
  23. epyt_flow/EPANET/EPANET/SRC_engines/epanet.c +0 -5930
  24. epyt_flow/EPANET/EPANET/SRC_engines/epanet2.c +0 -961
  25. epyt_flow/EPANET/EPANET/SRC_engines/errors.dat +0 -79
  26. epyt_flow/EPANET/EPANET/SRC_engines/flowbalance.c +0 -186
  27. epyt_flow/EPANET/EPANET/SRC_engines/funcs.h +0 -219
  28. epyt_flow/EPANET/EPANET/SRC_engines/genmmd.c +0 -1000
  29. epyt_flow/EPANET/EPANET/SRC_engines/hash.c +0 -177
  30. epyt_flow/EPANET/EPANET/SRC_engines/hash.h +0 -28
  31. epyt_flow/EPANET/EPANET/SRC_engines/hydcoeffs.c +0 -1303
  32. epyt_flow/EPANET/EPANET/SRC_engines/hydraul.c +0 -1172
  33. epyt_flow/EPANET/EPANET/SRC_engines/hydsolver.c +0 -781
  34. epyt_flow/EPANET/EPANET/SRC_engines/hydstatus.c +0 -442
  35. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2.h +0 -464
  36. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_2.h +0 -1960
  37. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_enums.h +0 -518
  38. epyt_flow/EPANET/EPANET/SRC_engines/inpfile.c +0 -884
  39. epyt_flow/EPANET/EPANET/SRC_engines/input1.c +0 -672
  40. epyt_flow/EPANET/EPANET/SRC_engines/input2.c +0 -735
  41. epyt_flow/EPANET/EPANET/SRC_engines/input3.c +0 -2265
  42. epyt_flow/EPANET/EPANET/SRC_engines/leakage.c +0 -527
  43. epyt_flow/EPANET/EPANET/SRC_engines/mempool.c +0 -146
  44. epyt_flow/EPANET/EPANET/SRC_engines/mempool.h +0 -24
  45. epyt_flow/EPANET/EPANET/SRC_engines/output.c +0 -853
  46. epyt_flow/EPANET/EPANET/SRC_engines/project.c +0 -1691
  47. epyt_flow/EPANET/EPANET/SRC_engines/quality.c +0 -695
  48. epyt_flow/EPANET/EPANET/SRC_engines/qualreact.c +0 -800
  49. epyt_flow/EPANET/EPANET/SRC_engines/qualroute.c +0 -696
  50. epyt_flow/EPANET/EPANET/SRC_engines/report.c +0 -1557
  51. epyt_flow/EPANET/EPANET/SRC_engines/rules.c +0 -1500
  52. epyt_flow/EPANET/EPANET/SRC_engines/smatrix.c +0 -871
  53. epyt_flow/EPANET/EPANET/SRC_engines/text.h +0 -508
  54. epyt_flow/EPANET/EPANET/SRC_engines/types.h +0 -928
  55. epyt_flow/EPANET/EPANET/SRC_engines/util/cstr_helper.c +0 -59
  56. epyt_flow/EPANET/EPANET/SRC_engines/util/cstr_helper.h +0 -38
  57. epyt_flow/EPANET/EPANET/SRC_engines/util/errormanager.c +0 -92
  58. epyt_flow/EPANET/EPANET/SRC_engines/util/errormanager.h +0 -39
  59. epyt_flow/EPANET/EPANET/SRC_engines/util/filemanager.c +0 -212
  60. epyt_flow/EPANET/EPANET/SRC_engines/util/filemanager.h +0 -81
  61. epyt_flow/EPANET/EPANET/SRC_engines/validate.c +0 -408
  62. epyt_flow/EPANET/EPANET-MSX/MSX_Updates.txt +0 -53
  63. epyt_flow/EPANET/EPANET-MSX/Src/dispersion.h +0 -27
  64. epyt_flow/EPANET/EPANET-MSX/Src/hash.c +0 -107
  65. epyt_flow/EPANET/EPANET-MSX/Src/hash.h +0 -28
  66. epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx.h +0 -102
  67. epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx_export.h +0 -42
  68. epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.c +0 -937
  69. epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.h +0 -39
  70. epyt_flow/EPANET/EPANET-MSX/Src/mempool.c +0 -204
  71. epyt_flow/EPANET/EPANET-MSX/Src/mempool.h +0 -24
  72. epyt_flow/EPANET/EPANET-MSX/Src/msxchem.c +0 -1285
  73. epyt_flow/EPANET/EPANET-MSX/Src/msxcompiler.c +0 -368
  74. epyt_flow/EPANET/EPANET-MSX/Src/msxdict.h +0 -42
  75. epyt_flow/EPANET/EPANET-MSX/Src/msxdispersion.c +0 -586
  76. epyt_flow/EPANET/EPANET-MSX/Src/msxerr.c +0 -116
  77. epyt_flow/EPANET/EPANET-MSX/Src/msxfile.c +0 -260
  78. epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.c +0 -175
  79. epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.h +0 -35
  80. epyt_flow/EPANET/EPANET-MSX/Src/msxinp.c +0 -1504
  81. epyt_flow/EPANET/EPANET-MSX/Src/msxout.c +0 -401
  82. epyt_flow/EPANET/EPANET-MSX/Src/msxproj.c +0 -791
  83. epyt_flow/EPANET/EPANET-MSX/Src/msxqual.c +0 -2010
  84. epyt_flow/EPANET/EPANET-MSX/Src/msxrpt.c +0 -400
  85. epyt_flow/EPANET/EPANET-MSX/Src/msxtank.c +0 -422
  86. epyt_flow/EPANET/EPANET-MSX/Src/msxtoolkit.c +0 -1164
  87. epyt_flow/EPANET/EPANET-MSX/Src/msxtypes.h +0 -551
  88. epyt_flow/EPANET/EPANET-MSX/Src/msxutils.c +0 -524
  89. epyt_flow/EPANET/EPANET-MSX/Src/msxutils.h +0 -56
  90. epyt_flow/EPANET/EPANET-MSX/Src/newton.c +0 -158
  91. epyt_flow/EPANET/EPANET-MSX/Src/newton.h +0 -34
  92. epyt_flow/EPANET/EPANET-MSX/Src/rk5.c +0 -287
  93. epyt_flow/EPANET/EPANET-MSX/Src/rk5.h +0 -39
  94. epyt_flow/EPANET/EPANET-MSX/Src/ros2.c +0 -293
  95. epyt_flow/EPANET/EPANET-MSX/Src/ros2.h +0 -35
  96. epyt_flow/EPANET/EPANET-MSX/Src/smatrix.c +0 -816
  97. epyt_flow/EPANET/EPANET-MSX/Src/smatrix.h +0 -29
  98. epyt_flow/EPANET/EPANET-MSX/readme.txt +0 -14
  99. epyt_flow/EPANET/compile_linux.sh +0 -4
  100. epyt_flow/EPANET/compile_macos.sh +0 -4
  101. epyt_flow/simulation/backend/__init__.py +0 -1
  102. epyt_flow/simulation/backend/my_epyt.py +0 -1101
  103. epyt_flow-0.14.1.dist-info/RECORD +0 -148
  104. {epyt_flow-0.14.1.dist-info → epyt_flow-0.15.0b1.dist-info}/WHEEL +0 -0
  105. {epyt_flow-0.14.1.dist-info → epyt_flow-0.15.0b1.dist-info}/licenses/LICENSE +0 -0
  106. {epyt_flow-0.14.1.dist-info → epyt_flow-0.15.0b1.dist-info}/top_level.txt +0 -0
@@ -1,1557 +0,0 @@
1
- /*
2
- ******************************************************************************
3
- Project: OWA EPANET
4
- Version: 2.3
5
- Module: report.c
6
- Description: procedures for writing formatted text to a report file
7
- Authors: see AUTHORS
8
- Copyright: see AUTHORS
9
- License: see LICENSE
10
- Last Updated: 02/14/2025
11
- ******************************************************************************
12
- */
13
-
14
- #include <stdlib.h>
15
- #include <stdio.h>
16
- #include <string.h>
17
-
18
- #ifdef _WIN32
19
- #define snprintf _snprintf
20
- #endif
21
-
22
- #include <math.h>
23
- #include <time.h>
24
-
25
- #include "types.h"
26
- #include "funcs.h"
27
- #include "hash.h"
28
- #include "text.h"
29
-
30
- #define MAXCOUNT 10 // Max. # of disconnected nodes listed
31
-
32
- // Defined in ENUMSTXT.H
33
- extern char *NodeTxt[];
34
- extern char *LinkTxt[];
35
- extern char *StatTxt[];
36
- extern char *TstatTxt[];
37
- extern char *RptFormTxt[];
38
- extern char *DemandModelTxt[];
39
-
40
- // Local functions
41
- typedef REAL4 *Pfloat;
42
- static void writenodetable(Project *, Pfloat *);
43
- static void writelinktable(Project *, Pfloat *);
44
- static void writeenergy(Project *);
45
- static int writeresults(Project *);
46
- static int disconnected(Project *);
47
- static void marknodes(Project *, int, int *, char *);
48
- static void getclosedlink(Project *, int, char *, int *);
49
- static void writelimits(Project *, int, int);
50
- static int checklimits(Report *, double *, int, int);
51
- static char *fillstr(char *, char, int);
52
- static int getnodetype(Network *, int);
53
-
54
- int clearreport(Project *pr)
55
- /*
56
- **------------------------------------------------------
57
- ** Input: none
58
- ** Output: returns error code
59
- ** Purpose: clears contents of a project's report file
60
- **------------------------------------------------------
61
- */
62
- {
63
- Report *rpt = &pr->report;
64
- if (rpt->RptFile == NULL) return 0;
65
- if (freopen(rpt->Rpt1Fname, "w", rpt->RptFile) == NULL) return 303;
66
- writelogo(pr);
67
- return 0;
68
- }
69
-
70
- int copyreport(Project* pr, const char *filename)
71
- /*
72
- **------------------------------------------------------
73
- ** Input: filename = name of file to copy to
74
- ** Output: returns error code
75
- ** Purpose: copies contents of a project's report file
76
- **------------------------------------------------------
77
- */
78
- {
79
- FILE *tfile;
80
- int c;
81
- Report *rpt = &pr->report;
82
-
83
- // Check that project's report file exists
84
- if (rpt->RptFile == NULL) return 0;
85
-
86
- // Open the new destination file
87
- tfile = fopen(filename, "w");
88
- if (tfile == NULL) return 303;
89
-
90
- // Re-open project's report file in read mode
91
- fclose(rpt->RptFile);
92
- rpt->RptFile = fopen(rpt->Rpt1Fname, "r");
93
-
94
- // Copy contents of project's report file
95
- if (rpt->RptFile)
96
- {
97
- while ((c = fgetc(rpt->RptFile)) != EOF) fputc(c, tfile);
98
- fclose(rpt->RptFile);
99
- }
100
-
101
- // Close destination file
102
- fclose(tfile);
103
-
104
- // Re-open project's report file in append mode
105
- rpt->RptFile = fopen(rpt->Rpt1Fname, "a");
106
- if (rpt->RptFile == NULL) return 303;
107
- return 0;
108
- }
109
-
110
- int writereport(Project *pr)
111
- /*
112
- **------------------------------------------------------
113
- ** Input: none
114
- ** Output: returns error code
115
- ** Purpose: writes formatted output report to file
116
- **------------------------------------------------------
117
- */
118
- {
119
- Report *rpt = &pr->report;
120
- Parser *parser = &pr->parser;
121
-
122
- int tflag;
123
- FILE *tfile;
124
- int errcode = 0;
125
-
126
- // If no secondary report file specified then
127
- // write formatted output to primary report file
128
- rpt->Fprinterr = FALSE;
129
- if (rpt->Rptflag && strlen(rpt->Rpt2Fname) == 0 && rpt->RptFile != NULL)
130
- {
131
- if (rpt->Energyflag) writeenergy(pr);
132
- errcode = writeresults(pr);
133
- }
134
-
135
- // A secondary report file was specified
136
- else if (strlen(rpt->Rpt2Fname) > 0)
137
- {
138
- // If secondary report file has same name as either input
139
- // or primary report file then use primary report file.
140
- if (strcomp(rpt->Rpt2Fname, parser->InpFname) ||
141
- strcomp(rpt->Rpt2Fname, rpt->Rpt1Fname))
142
- {
143
- if (rpt->Energyflag) writeenergy(pr);
144
- errcode = writeresults(pr);
145
- }
146
-
147
- // Otherwise write report to secondary report file
148
- else
149
- {
150
- // Try to open file
151
- tfile = rpt->RptFile;
152
- tflag = rpt->Rptflag;
153
- if ((rpt->RptFile = fopen(rpt->Rpt2Fname, "wt")) == NULL)
154
- {
155
- rpt->RptFile = tfile;
156
- rpt->Rptflag = tflag;
157
- errcode = 303;
158
- }
159
-
160
- // Write full formatted report to file
161
- else
162
- {
163
- rpt->Rptflag = 1;
164
- writelogo(pr);
165
- if (rpt->Summaryflag) writesummary(pr);
166
- if (rpt->Energyflag) writeenergy(pr);
167
- errcode = writeresults(pr);
168
- fclose(rpt->RptFile);
169
- rpt->RptFile = tfile;
170
- rpt->Rptflag = tflag;
171
- }
172
- }
173
- }
174
-
175
- // Special error handler for write-to-file error
176
- if (rpt->Fprinterr) errmsg(pr, 309);
177
- return errcode;
178
- }
179
-
180
- void writelogo(Project *pr)
181
- /*
182
- **--------------------------------------------------------------
183
- ** Input: none
184
- ** Output: none
185
- ** Purpose: writes program logo to report file.
186
- **--------------------------------------------------------------
187
- */
188
- {
189
- Report *rpt = &pr->report;
190
-
191
- int version;
192
- int major;
193
- int minor;
194
- char s[80];
195
- time_t timer; // time_t structure & functions time() &
196
- // ctime() are defined in time.h
197
-
198
- version = CODEVERSION;
199
- major = version / 10000;
200
- minor = (version % 10000) / 100;
201
-
202
- time(&timer);
203
- strcpy(rpt->DateStamp, ctime(&timer));
204
- rpt->PageNum = 1;
205
- rpt->LineNum = 2;
206
- fprintf(rpt->RptFile, FMT18);
207
- fprintf(rpt->RptFile, "%s", rpt->DateStamp);
208
- writeline(pr, LOGO1);
209
- writeline(pr, LOGO2);
210
- writeline(pr, LOGO3);
211
- writeline(pr, LOGO4);
212
- sprintf(s, LOGO5, major, minor);
213
- writeline(pr, s);
214
- writeline(pr, LOGO6);
215
- writeline(pr, "");
216
- }
217
-
218
- void writesummary(Project *pr)
219
- /*
220
- **--------------------------------------------------------------
221
- ** Input: none
222
- ** Output: none
223
- ** Purpose: writes summary system information to report file
224
- **--------------------------------------------------------------
225
- */
226
- {
227
- Network *net = &pr->network;
228
- Hydraul *hyd = &pr->hydraul;
229
- Quality *qual = &pr->quality;
230
- Report *rpt = &pr->report;
231
- Parser *parser = &pr->parser;
232
- Times *time = &pr->times;
233
-
234
- char s[MAXLINE + 1];
235
- int i;
236
- int nres = 0;
237
-
238
- for (i = 0; i < 3; i++)
239
- {
240
- if (strlen(pr->Title[i]) > 0)
241
- {
242
- sprintf(s, "%-.70s", pr->Title[i]);
243
- writeline(pr, s);
244
- }
245
- }
246
- writeline(pr, " ");
247
- sprintf(s, FMT19, parser->InpFname);
248
- writeline(pr, s);
249
- sprintf(s, FMT20, net->Njuncs);
250
- writeline(pr, s);
251
- for (i = 1; i <= net->Ntanks; i++) if (net->Tank[i].A == 0.0) nres++;
252
- sprintf(s, FMT21a, nres);
253
- writeline(pr, s);
254
- sprintf(s, FMT21b, net->Ntanks - nres);
255
- writeline(pr, s);
256
- sprintf(s, FMT22, net->Npipes);
257
- writeline(pr, s);
258
- sprintf(s, FMT23, net->Npumps);
259
- writeline(pr, s);
260
- sprintf(s, FMT24, net->Nvalves);
261
- writeline(pr, s);
262
- sprintf(s, FMT25, RptFormTxt[hyd->Formflag]);
263
- writeline(pr, s);
264
- sprintf(s, FMT25a, DemandModelTxt[hyd->DemandModel]);
265
- writeline(pr, s);
266
- sprintf(s, FMT26, time->Hstep * pr->Ucf[TIME], rpt->Field[TIME].Units);
267
- writeline(pr, s);
268
- sprintf(s, FMT27, hyd->Hacc);
269
- writeline(pr, s);
270
-
271
- if (hyd->HeadErrorLimit > 0.0)
272
- {
273
- sprintf(s, FMT27d, hyd->HeadErrorLimit*pr->Ucf[HEAD], rpt->Field[HEAD].Units);
274
- writeline(pr, s);
275
- }
276
- if (hyd->FlowChangeLimit > 0.0)
277
- {
278
- sprintf(s, FMT27e, hyd->FlowChangeLimit*pr->Ucf[FLOW], rpt->Field[FLOW].Units);
279
- writeline(pr, s);
280
- }
281
-
282
- sprintf(s, FMT27a, hyd->CheckFreq);
283
- writeline(pr, s);
284
- sprintf(s, FMT27b, hyd->MaxCheck);
285
- writeline(pr, s);
286
- sprintf(s, FMT27c, hyd->DampLimit);
287
- writeline(pr, s);
288
- sprintf(s, FMT28, hyd->MaxIter);
289
- writeline(pr, s);
290
-
291
- if (qual->Qualflag == NONE || time->Dur == 0.0) sprintf(s, FMT29);
292
- else if (qual->Qualflag == CHEM) sprintf(s, FMT30, qual->ChemName);
293
- else if (qual->Qualflag == TRACE) sprintf(s, FMT31, net->Node[qual->TraceNode].ID);
294
- else if (qual->Qualflag == AGE) sprintf(s, FMT32);
295
- writeline(pr, s);
296
- if (qual->Qualflag != NONE && time->Dur > 0)
297
- {
298
- sprintf(s, FMT33, (float)time->Qstep / 60.0);
299
- writeline(pr, s);
300
- sprintf(s, FMT34, qual->Ctol * pr->Ucf[QUALITY], rpt->Field[QUALITY].Units);
301
- writeline(pr, s);
302
- }
303
-
304
- sprintf(s, FMT36, hyd->SpGrav);
305
- writeline(pr, s);
306
- sprintf(s, FMT37a, hyd->Viscos / VISCOS);
307
- writeline(pr, s);
308
- sprintf(s, FMT37b, qual->Diffus / DIFFUS);
309
- writeline(pr, s);
310
- sprintf(s, FMT38, hyd->Dmult);
311
- writeline(pr, s);
312
- sprintf(s, FMT39, time->Dur * pr->Ucf[TIME], rpt->Field[TIME].Units);
313
- writeline(pr, s);
314
-
315
- if (rpt->Rptflag)
316
- {
317
- sprintf(s, FMT40);
318
- writeline(pr, s);
319
- if (rpt->Nodeflag == 0) writeline(pr, FMT41);
320
- if (rpt->Nodeflag == 1) writeline(pr, FMT42);
321
- if (rpt->Nodeflag == 2) writeline(pr, FMT43);
322
- writelimits(pr, DEMAND, QUALITY);
323
- if (rpt->Linkflag == 0) writeline(pr, FMT44);
324
- if (rpt->Linkflag == 1) writeline(pr, FMT45);
325
- if (rpt->Linkflag == 2) writeline(pr, FMT46);
326
- writelimits(pr, DIAM, HEADLOSS);
327
- }
328
- writeline(pr, " ");
329
- }
330
-
331
- void writehydstat(Project *pr, int iter, double relerr)
332
- /*
333
- **--------------------------------------------------------------
334
- ** Input: iter = # iterations to find hydraulic solution
335
- ** relerr = convergence error in hydraulic solution
336
- ** Output: none
337
- ** Purpose: writes hydraulic status report for solution found
338
- ** at current time period to report file
339
- **--------------------------------------------------------------
340
- */
341
- {
342
- Network *net = &pr->network;
343
- Hydraul *hyd = &pr->hydraul;
344
- Report *rpt = &pr->report;
345
- Times *time = &pr->times;
346
-
347
- int i, n;
348
- double *NodeDemand;
349
- char s1[MAXLINE + 1];
350
- char atime[13];
351
- StatusType newstat;
352
- Stank *Tank = net->Tank;
353
- Slink *Link = net->Link;
354
-
355
- // Display system status
356
- strcpy(atime, clocktime(rpt->Atime, time->Htime));
357
- if (iter > 0)
358
- {
359
- if (relerr <= hyd->Hacc) sprintf(s1, FMT58, atime, iter);
360
- else sprintf(s1, FMT59, atime, iter, relerr);
361
- writeline(pr, s1);
362
- if (hyd->DemandModel == PDA && hyd->DeficientNodes > 0)
363
- {
364
- if (hyd->DeficientNodes == 1)
365
- sprintf(s1, FMT69a, hyd->DemandReduction);
366
- else
367
- sprintf(s1, FMT69b, hyd->DeficientNodes, hyd->DemandReduction);
368
- writeline(pr, s1);
369
- }
370
- }
371
-
372
- // Display status changes for tanks:
373
- // D[n] is net inflow to tank at node n;
374
- // old tank status is stored in OldStatus[]
375
- // at indexes Nlinks+1 to Nlinks+Ntanks.
376
- for (i = 1; i <= net->Ntanks; i++)
377
- {
378
- n = net->Tank[i].Node;
379
- NodeDemand = hyd->NodeDemand;
380
- if (ABS(NodeDemand[n]) < 0.001) newstat = CLOSED;
381
- else if (NodeDemand[n] < 0.0) newstat = EMPTYING;
382
- else if (NodeDemand[n] > 0.0)
383
- {
384
- if (Tank[i].A > 0.0 && ABS(hyd->NodeHead[n] - Tank[i].Hmax) < 0.001)
385
- newstat = OVERFLOWING;
386
- else newstat = FILLING;
387
- }
388
- else newstat = hyd->OldStatus[net->Nlinks + i];
389
- if (newstat != hyd->OldStatus[net->Nlinks + i])
390
- {
391
- if (Tank[i].A > 0.0)
392
- {
393
- snprintf(s1, MAXLINE, FMT50, atime, net->Node[n].ID, StatTxt[newstat],
394
- (hyd->NodeHead[n] - net->Node[n].El) * pr->Ucf[HEAD],
395
- rpt->Field[HEAD].Units);
396
- }
397
- else
398
- {
399
- snprintf(s1, MAXLINE, FMT51, atime, net->Node[n].ID, StatTxt[newstat]);
400
- }
401
- writeline(pr, s1);
402
- hyd->OldStatus[net->Nlinks + i] = newstat;
403
- }
404
- }
405
-
406
- // Display status changes for links
407
- for (i = 1; i <= net->Nlinks; i++)
408
- {
409
- if (hyd->LinkStatus[i] != hyd->OldStatus[i])
410
- {
411
- if (time->Htime == 0)
412
- {
413
- sprintf(s1, FMT52, atime, LinkTxt[(int)net->Link[i].Type],
414
- net->Link[i].ID, StatTxt[(int)hyd->LinkStatus[i]]);
415
- }
416
- else sprintf(s1, FMT53, atime, LinkTxt[Link[i].Type], net->Link[i].ID,
417
- StatTxt[hyd->OldStatus[i]], StatTxt[hyd->LinkStatus[i]]);
418
- writeline(pr, s1);
419
- hyd->OldStatus[i] = hyd->LinkStatus[i];
420
- }
421
- }
422
- writeline(pr, " ");
423
- }
424
-
425
- void writeflowbalance(Project *pr)
426
- /*
427
- **-------------------------------------------------------------
428
- ** Input: none
429
- ** Output: none
430
- ** Purpose: writes hydraulic flow balance ratio to report file.
431
- **-------------------------------------------------------------
432
- */
433
- {
434
- Hydraul *hyd = &pr->hydraul;
435
- Report *rpt = &pr->report;
436
- char s1[MAXMSG+1];
437
- double ucf = pr->Ucf[FLOW];
438
-
439
- snprintf(s1, MAXMSG, "Hydraulic Flow Balance (%s)", rpt->Field[DEMAND].Units);
440
- writeline(pr, s1);
441
- snprintf(s1, MAXMSG, "================================");
442
- writeline(pr, s1);
443
- snprintf(s1, MAXMSG, "Total Inflow: %12.3f", hyd->FlowBalance.totalInflow*ucf);
444
- writeline(pr, s1);
445
- snprintf(s1, MAXMSG, "Consumer Demand: %12.3f", hyd->FlowBalance.consumerDemand*ucf);
446
- writeline(pr, s1);
447
- snprintf(s1, MAXMSG, "Demand Deficit: %12.3f", hyd->FlowBalance.deficitDemand*ucf);
448
- writeline(pr, s1);
449
- snprintf(s1, MAXMSG, "Emitter Flow: %12.3f", hyd->FlowBalance.emitterDemand*ucf);
450
- writeline(pr, s1);
451
- snprintf(s1, MAXMSG, "Leakage Flow: %12.3f", hyd->FlowBalance.leakageDemand*ucf);
452
- writeline(pr, s1);
453
- snprintf(s1, MAXMSG, "Total Outflow: %12.3f", hyd->FlowBalance.totalOutflow*ucf);
454
- writeline(pr, s1);
455
- snprintf(s1, MAXMSG, "Storage Flow: %12.3f", hyd->FlowBalance.storageDemand*ucf);
456
- writeline(pr, s1);
457
- snprintf(s1, MAXMSG, "Flow Ratio: %12.3f", hyd->FlowBalance.ratio);
458
- writeline(pr, s1);
459
- snprintf(s1, MAXMSG, "================================\n");
460
- writeline(pr, s1);
461
- }
462
-
463
- void writemassbalance(Project *pr)
464
- /*
465
- **-------------------------------------------------------------
466
- ** Input: none
467
- ** Output: none
468
- ** Purpose: writes water quality mass balance ratio
469
- ** (Outflow + Final Storage) / Inflow + Initial Storage
470
- ** to report file.
471
- **-------------------------------------------------------------
472
- */
473
- {
474
- Quality *qual = &pr->quality;
475
-
476
- char s1[MAXMSG+1];
477
- char *units[] = {"", " (mg)", " (ug)", " (hrs)"};
478
- int kunits = 0;
479
-
480
- if (qual->Qualflag == TRACE) kunits = 1;
481
- else if (qual->Qualflag == AGE) kunits = 3;
482
- else
483
- {
484
- if (match(qual->ChemUnits, "mg")) kunits = 1;
485
- else if (match(qual->ChemUnits, "ug")) kunits = 2;
486
- }
487
-
488
- snprintf(s1, MAXMSG, "Water Quality Mass Balance%s", units[kunits]);
489
- writeline(pr, s1);
490
- snprintf(s1, MAXMSG, "================================");
491
- writeline(pr, s1);
492
- snprintf(s1, MAXMSG, "Initial Mass: %12.5e", qual->MassBalance.initial);
493
- writeline(pr, s1);
494
- snprintf(s1, MAXMSG, "Mass Inflow: %12.5e", qual->MassBalance.inflow);
495
- writeline(pr, s1);
496
- snprintf(s1, MAXMSG, "Mass Outflow: %12.5e", qual->MassBalance.outflow);
497
- writeline(pr, s1);
498
- snprintf(s1, MAXMSG, "Mass Reacted: %12.5e", qual->MassBalance.reacted);
499
- writeline(pr, s1);
500
- snprintf(s1, MAXMSG, "Final Mass: %12.5e", qual->MassBalance.final);
501
- writeline(pr, s1);
502
- snprintf(s1, MAXMSG, "Mass Ratio: %-.5f", qual->MassBalance.ratio);
503
- writeline(pr, s1);
504
- snprintf(s1, MAXMSG, "Total Segments: %d", qual->MassBalance.segCount);
505
- writeline(pr, s1);
506
- snprintf(s1, MAXMSG, "================================\n");
507
- writeline(pr, s1);
508
- }
509
-
510
- void writeenergy(Project *pr)
511
- /*
512
- **-------------------------------------------------------------
513
- ** Input: none
514
- ** Output: none
515
- ** Purpose: writes energy usage report to report file
516
- **-------------------------------------------------------------
517
- */
518
- {
519
- Network *net = &pr->network;
520
- Hydraul *hyd = &pr->hydraul;
521
- Report *rpt = &pr->report;
522
-
523
- int j;
524
- double csum;
525
- char s[MAXLINE + 1];
526
- Spump *pump;
527
-
528
- if (net->Npumps == 0) return;
529
- writeline(pr, " ");
530
- writeheader(pr,ENERHDR, 0);
531
-
532
- csum = 0.0;
533
- for (j = 1; j <= net->Npumps; j++)
534
- {
535
- pump = &net->Pump[j];
536
- csum += pump->Energy.TotalCost;
537
- if (rpt->LineNum == (long)rpt->PageSize) writeheader(pr, ENERHDR, 1);
538
-
539
- sprintf(s, "%-8s %6.2f %6.2f %9.2f %9.2f %9.2f %9.2f",
540
- net->Link[pump->Link].ID, pump->Energy.TimeOnLine,
541
- pump->Energy.Efficiency, pump->Energy.KwHrsPerFlow,
542
- pump->Energy.KwHrs, pump->Energy.MaxKwatts,
543
- pump->Energy.TotalCost);
544
- writeline(pr, s);
545
- }
546
-
547
- fillstr(s, '-', 63);
548
- writeline(pr, s);
549
- sprintf(s, FMT74, "", hyd->Emax * hyd->Dcost);
550
- writeline(pr, s);
551
- sprintf(s, FMT75, "", csum + hyd->Emax * hyd->Dcost);
552
- writeline(pr, s);
553
- writeline(pr, " ");
554
- }
555
-
556
- int writeresults(Project *pr)
557
- /*
558
- **--------------------------------------------------------------
559
- ** Input: none
560
- ** Output: returns error code
561
- ** Purpose: writes simulation results to report file
562
- **--------------------------------------------------------------
563
- */
564
- {
565
- Network *net = &pr->network;
566
- Outfile *out = &pr->outfile;
567
- Report *rpt = &pr->report;
568
- Times *time = &pr->times;
569
-
570
- int j, m, n,
571
- np, // Reporting period counter
572
- nnv, // # node variables reported on
573
- nlv; // # link variables reported on
574
- int errcode = 0;
575
- Pfloat *x; // Array of pointers to floats (i.e., a 2-D array)
576
- FILE *outFile = out->OutFile;
577
-
578
- //-----------------------------------------------------------
579
- // NOTE: The OutFile contains results for 4 node variables
580
- // (demand, head, pressure, & quality) and 8 link
581
- // variables (flow, velocity, headloss, quality,
582
- // status, setting, reaction rate & friction factor)
583
- // at each reporting time.
584
- //-----------------------------------------------------------
585
-
586
- // Return if no nodes or links selected for reporting
587
- // or if no node or link report variables enabled
588
- if (!rpt->Nodeflag && !rpt->Linkflag) return errcode;
589
-
590
- nnv = 0;
591
- for (j = ELEV; j <= QUALITY; j++) nnv += rpt->Field[j].Enabled;
592
- nlv = 0;
593
- for (j = LENGTH; j <= FRICTION; j++) nlv += rpt->Field[j].Enabled;
594
- if (nnv == 0 && nlv == 0) return errcode;
595
-
596
- // Return if no output file
597
- if (outFile == NULL) outFile = fopen(pr->outfile.OutFname, "rb");
598
- if (outFile == NULL) return 106;
599
-
600
- // Allocate memory for output variables:
601
- // m = larger of # node variables & # link variables
602
- // n = larger of # nodes & # links
603
- m = MAX((QUALITY - DEMAND + 1), (FRICTION - FLOW + 1));
604
- n = MAX((net->Nnodes + 1), (net->Nlinks + 1));
605
- x = (Pfloat *)calloc(m, sizeof(Pfloat));
606
- ERRCODE(MEMCHECK(x));
607
- if (errcode) return errcode;
608
- for (j = 0; j < m; j++)
609
- {
610
- x[j] = (REAL4 *)calloc(n, sizeof(REAL4));
611
- if (x[j] == NULL) errcode = 101;
612
- }
613
- if (!errcode)
614
- {
615
- // Re-position output file & initialize report time
616
- fseek(outFile, out->OutOffset2, SEEK_SET);
617
- time->Htime = time->Rstart;
618
-
619
- // For each reporting time:
620
- for (np = 1; np <= rpt->Nperiods; np++)
621
- {
622
- // Read in node results & write node table
623
- // (Remember to offset x[j] by 1 because array is zero-based)
624
- for (j = DEMAND; j <= QUALITY; j++)
625
- {
626
- fread((x[j - DEMAND]) + 1, sizeof(REAL4), net->Nnodes, outFile);
627
- }
628
- if (nnv > 0 && rpt->Nodeflag > 0) writenodetable(pr, x);
629
-
630
- // Read in link results & write link table
631
- for (j = FLOW; j <= FRICTION; j++)
632
- {
633
- fread((x[j - FLOW]) + 1, sizeof(REAL4), net->Nlinks, outFile);
634
- }
635
- if (nlv > 0 && rpt->Linkflag > 0) writelinktable(pr, x);
636
- time->Htime += time->Rstep;
637
- }
638
- }
639
-
640
- // Free output file
641
- if (outFile != NULL)
642
- {
643
- fclose(outFile);
644
- outFile = NULL;
645
- }
646
-
647
- // Free allocated memory
648
- for (j = 0; j < m; j++) free(x[j]);
649
- free(x);
650
- return errcode;
651
- }
652
-
653
- void writenodetable(Project *pr, Pfloat *x)
654
- /*
655
- **---------------------------------------------------------------
656
- ** Input: x = pointer to node results for current time
657
- ** Output: none
658
- ** Purpose: writes node results for current time to report file
659
- **---------------------------------------------------------------
660
- */
661
- {
662
- Network *net = &pr->network;
663
- Report *rpt = &pr->report;
664
-
665
- int i, j;
666
- char s[MAXLINE + 1], s1[16];
667
- double y[MAXVAR];
668
- Snode *node;
669
-
670
- // Write table header
671
- writeheader(pr, NODEHDR, 0);
672
-
673
- // For each node:
674
- for (i = 1; i <= net->Nnodes; i++)
675
- {
676
- // Place node's results for each variable in y
677
- node = &net->Node[i];
678
- y[ELEV] = node->El * pr->Ucf[ELEV];
679
- for (j = DEMAND; j <= QUALITY; j++) y[j] = *((x[j - DEMAND]) + i);
680
-
681
- // Check if node gets reported on
682
- if ((rpt->Nodeflag == 1 || node->Rpt) &&
683
- checklimits(rpt, y, ELEV, QUALITY))
684
- {
685
- // Check if new page needed
686
- if (rpt->LineNum == (long)rpt->PageSize) writeheader(pr, NODEHDR, 1);
687
-
688
- // Add node ID and each reported field to string s
689
- sprintf(s, "%-15s", node->ID);
690
- for (j = ELEV; j <= QUALITY; j++)
691
- {
692
- if (rpt->Field[j].Enabled == TRUE)
693
- {
694
- if (fabs(y[j]) > 1.e6) sprintf(s1, "%10.2e", y[j]);
695
- else sprintf(s1, "%10.*f", rpt->Field[j].Precision, y[j]);
696
- strcat(s, s1);
697
- }
698
- }
699
-
700
- // Note if node is a reservoir/tank
701
- if (i > net->Njuncs)
702
- {
703
- strcat(s, " ");
704
- strcat(s, NodeTxt[getnodetype(net, i)]);
705
- }
706
-
707
- // Write results for node to report file
708
- writeline(pr, s);
709
- }
710
- }
711
- writeline(pr, " ");
712
- }
713
-
714
- void writelinktable(Project *pr, Pfloat *x)
715
- /*
716
- **---------------------------------------------------------------
717
- ** Input: x = pointer to link results for current time
718
- ** Output: none
719
- ** Purpose: writes link results for current time to report file
720
- **---------------------------------------------------------------
721
- */
722
- {
723
- Network *net = &pr->network;
724
- Report *rpt = &pr->report;
725
-
726
- int i, j, k;
727
- char s[MAXLINE + 1], s1[16];
728
- double y[MAXVAR];
729
- double *Ucf = pr->Ucf;
730
- Slink *Link = net->Link;
731
-
732
- // Write table header
733
- writeheader(pr, LINKHDR, 0);
734
-
735
- // For each link:
736
- for (i = 1; i <= net->Nlinks; i++)
737
- {
738
- // Place results for each link variable in y
739
- y[LENGTH] = Link[i].Len * Ucf[LENGTH];
740
- y[DIAM] = Link[i].Diam * Ucf[DIAM];
741
- for (j = FLOW; j <= FRICTION; j++) y[j] = *((x[j - FLOW]) + i);
742
-
743
- // Check if link gets reported on
744
- if ((rpt->Linkflag == 1 || Link[i].Rpt) && checklimits(rpt, y, DIAM, FRICTION))
745
- {
746
- // Check if new page needed
747
- if (rpt->LineNum == (long)rpt->PageSize) writeheader(pr, LINKHDR, 1);
748
-
749
- // Add link ID and each reported field to string s
750
- sprintf(s, "%-15s", Link[i].ID);
751
- for (j = LENGTH; j <= FRICTION; j++)
752
- {
753
- if (rpt->Field[j].Enabled == TRUE)
754
- {
755
- if (j == STATUS)
756
- {
757
- if (y[j] <= CLOSED) k = CLOSED;
758
- else if (y[j] == ACTIVE) k = ACTIVE;
759
- else k = OPEN;
760
- sprintf(s1, "%10s", StatTxt[k]);
761
- }
762
- else
763
- {
764
- if (fabs(y[j]) > 1.e6) sprintf(s1, "%10.2e", y[j]);
765
- else sprintf(s1, "%10.*f", rpt->Field[j].Precision, y[j]);
766
- }
767
- strcat(s, s1);
768
- }
769
- }
770
-
771
- // Note if link is a pump or valve
772
- if ((j = Link[i].Type) > PIPE)
773
- {
774
- strcat(s, " ");
775
- strcat(s, LinkTxt[j]);
776
- }
777
-
778
- // Write results for link
779
- writeline(pr, s);
780
- }
781
- }
782
- writeline(pr, " ");
783
- }
784
-
785
- void writeheader(Project *pr, int type, int contin)
786
- /*
787
- **--------------------------------------------------------------
788
- ** Input: type = table type
789
- ** contin = table continuation flag
790
- ** Output: none
791
- ** Purpose: writes column headings for output report tables
792
- **--------------------------------------------------------------
793
- */
794
- {
795
- Report *rpt = &pr->report;
796
- Quality *qual = &pr->quality;
797
- Parser *parser = &pr->parser;
798
- Times *time = &pr->times;
799
-
800
- char s[MAXLINE + 1], s1[MAXLINE + 1], s2[MAXLINE + 1], s3[MAXLINE + 1];
801
- int i, n;
802
-
803
- // Move to next page if < 11 lines remain on current page
804
- if (rpt->Rptflag && rpt->LineNum + 11 > (long)rpt->PageSize)
805
- {
806
- while (rpt->LineNum < (long)rpt->PageSize) writeline(pr, " ");
807
- }
808
- writeline(pr, " ");
809
-
810
- // Hydraulic Status Table
811
- if (type == STATHDR)
812
- {
813
- sprintf(s, FMT49);
814
- if (contin) strcat(s, t_CONTINUED);
815
- writeline(pr, s);
816
- fillstr(s, '-', 70);
817
- writeline(pr, s);
818
- }
819
-
820
- // Energy Usage Table
821
- if (type == ENERHDR)
822
- {
823
- if (parser->Unitsflag == SI) strcpy(s1, t_perM3);
824
- else strcpy(s1, t_perMGAL);
825
- sprintf(s, FMT71);
826
- if (contin) strcat(s, t_CONTINUED);
827
- writeline(pr, s);
828
- fillstr(s, '-', 63);
829
- writeline(pr, s);
830
- sprintf(s, FMT72);
831
- writeline(pr, s);
832
- sprintf(s, FMT73, s1);
833
- writeline(pr, s);
834
- fillstr(s, '-', 63);
835
- writeline(pr, s);
836
- }
837
-
838
- // Node Results Table
839
- if (type == NODEHDR)
840
- {
841
- if (rpt->Tstatflag == RANGE) sprintf(s, FMT76, t_DIFFER);
842
- else if (rpt->Tstatflag != SERIES)
843
- {
844
- sprintf(s, FMT76, TstatTxt[rpt->Tstatflag]);
845
- }
846
- else if (time->Dur == 0) sprintf(s, FMT77);
847
- else sprintf(s, FMT78, clocktime(rpt->Atime, time->Htime));
848
- if (contin) strcat(s, t_CONTINUED);
849
- writeline(pr, s);
850
-
851
- n = 15;
852
- sprintf(s2, "%15s", "");
853
- strcpy(s, t_NODEID);
854
- sprintf(s3, "%-15s", s);
855
-
856
- for (i = ELEV; i < QUALITY; i++)
857
- {
858
- if (rpt->Field[i].Enabled == TRUE)
859
- {
860
- n += 10;
861
- sprintf(s, "%10s", rpt->Field[i].Name);
862
- strcat(s2, s);
863
- sprintf(s, "%10s", rpt->Field[i].Units);
864
- strcat(s3, s);
865
- }
866
- }
867
-
868
- if (rpt->Field[QUALITY].Enabled == TRUE)
869
- {
870
- n += 10;
871
- sprintf(s, "%10s", qual->ChemName);
872
- strcat(s2, s);
873
- sprintf(s, "%10s", qual->ChemUnits);
874
- strcat(s3, s);
875
- }
876
- fillstr(s1, '-', n);
877
- writeline(pr, s1);
878
- writeline(pr, s2);
879
- writeline(pr, s3);
880
- writeline(pr, s1);
881
- }
882
-
883
- // Link Results Table
884
- if (type == LINKHDR)
885
- {
886
- if (rpt->Tstatflag == RANGE) sprintf(s, FMT79, t_DIFFER);
887
- else if (rpt->Tstatflag != SERIES)
888
- {
889
- sprintf(s, FMT79, TstatTxt[rpt->Tstatflag]);
890
- }
891
- else if (time->Dur == 0) sprintf(s, FMT80);
892
- else sprintf(s, FMT81, clocktime(rpt->Atime, time->Htime));
893
- if (contin) strcat(s, t_CONTINUED);
894
- writeline(pr, s);
895
-
896
- n = 15;
897
- sprintf(s2, "%15s", "");
898
- strcpy(s, t_LINKID);
899
- sprintf(s3, "%-15s", s);
900
- for (i = LENGTH; i <= FRICTION; i++)
901
- {
902
- if (rpt->Field[i].Enabled == TRUE)
903
- {
904
- n += 10;
905
- sprintf(s, "%10s", rpt->Field[i].Name);
906
- strcat(s2, s);
907
- sprintf(s, "%10s", rpt->Field[i].Units);
908
- strcat(s3, s);
909
- }
910
- }
911
- fillstr(s1, '-', n);
912
- writeline(pr, s1);
913
- writeline(pr, s2);
914
- writeline(pr, s3);
915
- writeline(pr, s1);
916
- }
917
- }
918
-
919
- void writeline(Project *pr, const char *s)
920
- /*
921
- **--------------------------------------------------------------
922
- ** Input: *s = text string
923
- ** Output: none
924
- ** Purpose: writes a line of output to report file
925
- **--------------------------------------------------------------
926
- */
927
- {
928
- Report *rpt = &pr->report;
929
-
930
- if (pr->report.reportCallback != NULL)
931
- {
932
- pr->report.reportCallback(pr->report.reportCallbackUserData, pr, s);
933
- return;
934
- }
935
-
936
- if (rpt->RptFile == NULL) return;
937
- if (rpt->Rptflag)
938
- {
939
- if (rpt->LineNum == (long)rpt->PageSize)
940
- {
941
- rpt->PageNum++;
942
- if (fprintf(rpt->RptFile, FMT82, (int)rpt->PageNum, pr->Title[0]) < 0)
943
- {
944
- rpt->Fprinterr = TRUE;
945
- }
946
- rpt->LineNum = 3;
947
- }
948
- }
949
- if (fprintf(rpt->RptFile, "\n %s", s) < 0) rpt->Fprinterr = TRUE;
950
- rpt->LineNum++;
951
- }
952
-
953
- void writerelerr(Project *pr, int iter, double relerr)
954
- /*
955
- **-----------------------------------------------------------------
956
- ** Input: iter = current iteration of hydraulic solution
957
- ** relerr = current convergence error
958
- ** Output: none
959
- ** Purpose: writes out convergence status of hydraulic solution
960
- **-----------------------------------------------------------------
961
- */
962
- {
963
- Report *rpt = &pr->report;
964
- Times *time = &pr->times;
965
-
966
- if (iter == 0)
967
- {
968
- sprintf(pr->Msg, FMT64, clocktime(rpt->Atime, time->Htime));
969
- writeline(pr, pr->Msg);
970
- }
971
- else
972
- {
973
- sprintf(pr->Msg, FMT65, iter, relerr);
974
- writeline(pr, pr->Msg);
975
- }
976
- }
977
-
978
- void writestatchange(Project *pr, int k, char s1, char s2)
979
- /*
980
- **--------------------------------------------------------------
981
- ** Input: k = link index
982
- ** s1 = old link status
983
- ** s2 = new link status
984
- ** Output: none
985
- ** Purpose: writes change in link status to output report
986
- **--------------------------------------------------------------
987
- */
988
- {
989
- Network *net = &pr->network;
990
- Hydraul *hyd = &pr->hydraul;
991
-
992
- int j1, j2;
993
- double setting;
994
- double *Ucf = pr->Ucf;
995
- double *LinkSetting = hyd->LinkSetting;
996
- Slink *Link = net->Link;
997
-
998
- // We have a pump/valve setting change instead of a status change
999
- if (s1 == s2)
1000
- {
1001
- setting = LinkSetting[k];
1002
- switch (Link[k].Type)
1003
- {
1004
- case PRV:
1005
- case PSV:
1006
- case PBV:
1007
- setting *= Ucf[PRESSURE];
1008
- break;
1009
- case FCV:
1010
- setting *= Ucf[FLOW];
1011
- break;
1012
- default:
1013
- break;
1014
- }
1015
- sprintf(pr->Msg, FMT56, LinkTxt[Link[k].Type], Link[k].ID, setting);
1016
- writeline(pr, pr->Msg);
1017
- return;
1018
- }
1019
-
1020
- // We have a status change - write the old & new status types
1021
- if (s1 == ACTIVE) j1 = ACTIVE;
1022
- else if (s1 <= CLOSED) j1 = CLOSED;
1023
- else j1 = OPEN;
1024
- if (s2 == ACTIVE) j2 = ACTIVE;
1025
- else if (s2 <= CLOSED) j2 = CLOSED;
1026
- else j2 = OPEN;
1027
- if (j1 != j2)
1028
- {
1029
- sprintf(pr->Msg, FMT57, LinkTxt[Link[k].Type], Link[k].ID, StatTxt[j1],
1030
- StatTxt[j2]);
1031
- writeline(pr, pr->Msg);
1032
- }
1033
- }
1034
-
1035
- void writecontrolaction(Project *pr, int k, int i)
1036
- /*
1037
- ----------------------------------------------------------------
1038
- ** Input: k = link index
1039
- ** i = control index
1040
- ** Output: none
1041
- ** Purpose: writes control action taken to status report
1042
- **--------------------------------------------------------------
1043
- */
1044
- {
1045
- Network *net = &pr->network;
1046
- Report *rpt = &pr->report;
1047
- Times *time = &pr->times;
1048
-
1049
- int n;
1050
- Snode *Node = net->Node;
1051
- Slink *Link = net->Link;
1052
- Scontrol *Control = net->Control;
1053
-
1054
- switch (Control[i].Type)
1055
- {
1056
- case LOWLEVEL:
1057
- case HILEVEL:
1058
- n = Control[i].Node;
1059
- sprintf(pr->Msg, FMT54, clocktime(rpt->Atime, time->Htime),
1060
- LinkTxt[Link[k].Type], Link[k].ID,
1061
- NodeTxt[getnodetype(net, n)], Node[n].ID);
1062
- break;
1063
-
1064
- case TIMER:
1065
- case TIMEOFDAY:
1066
- sprintf(pr->Msg, FMT55, clocktime(rpt->Atime, time->Htime),
1067
- LinkTxt[Link[k].Type], Link[k].ID);
1068
- break;
1069
- default:
1070
- return;
1071
- }
1072
- writeline(pr, pr->Msg);
1073
- }
1074
-
1075
- void writeruleaction(Project *pr, int k, char *ruleID)
1076
- /*
1077
- **--------------------------------------------------------------
1078
- ** Input: k = link index
1079
- ** *ruleID = rule ID
1080
- ** Output: none
1081
- ** Purpose: writes rule action taken to status report
1082
- **--------------------------------------------------------------
1083
- */
1084
- {
1085
- Network *net = &pr->network;
1086
- Report *rpt = &pr->report;
1087
- Times *time = &pr->times;
1088
-
1089
- Slink *Link = net->Link;
1090
-
1091
- sprintf(pr->Msg, FMT63, clocktime(rpt->Atime, time->Htime),
1092
- LinkTxt[Link[k].Type], Link[k].ID, ruleID);
1093
- writeline(pr, pr->Msg);
1094
- }
1095
-
1096
- int writehydwarn(Project *pr, int iter, double relerr)
1097
- /*
1098
- **--------------------------------------------------------------
1099
- ** Input: iter = # iterations to find hydraulic solution
1100
- ** Output: warning flag code
1101
- ** Purpose: writes hydraulic warning message to report file
1102
- **
1103
- ** Note: Warning conditions checked in following order:
1104
- ** 1. System balanced but unstable
1105
- ** 2. Negative pressures
1106
- ** 3. FCV cannot supply flow or PRV/PSV cannot maintain pressure
1107
- ** 4. Pump out of range
1108
- ** 5. Network disconnected
1109
- ** 6. System unbalanced
1110
- **--------------------------------------------------------------
1111
- */
1112
- {
1113
- Network *net = &pr->network;
1114
- Hydraul *hyd = &pr->hydraul;
1115
- Report *rpt = &pr->report;
1116
- Times *time = &pr->times;
1117
-
1118
- int i, j;
1119
- char flag = 0;
1120
- int s;
1121
- Snode *node;
1122
- Slink *link;
1123
- Spump *pump;
1124
-
1125
- // Check if system unstable
1126
- if (iter > hyd->MaxIter && relerr <= hyd->Hacc)
1127
- {
1128
- sprintf(pr->Msg, WARN02, clocktime(rpt->Atime, time->Htime));
1129
- if (rpt->Messageflag) writeline(pr, pr->Msg);
1130
- flag = 2;
1131
- }
1132
-
1133
- // Check for pressure deficient nodes
1134
- if (hyd->DemandModel == DDA)
1135
- {
1136
- hyd->DeficientNodes = 0;
1137
- for (i = 1; i <= net->Njuncs; i++)
1138
- {
1139
- node = &net->Node[i];
1140
- if (hyd->NodeHead[i] < node->El && hyd->NodeDemand[i] > 0.0)
1141
- hyd->DeficientNodes++;
1142
- }
1143
- if (hyd->DeficientNodes > 0)
1144
- {
1145
- if (rpt->Messageflag)
1146
- {
1147
- sprintf(pr->Msg, WARN06, clocktime(rpt->Atime, time->Htime));
1148
- writeline(pr, pr->Msg);
1149
- }
1150
- flag = 6;
1151
- }
1152
- }
1153
-
1154
- // Check for abnormal valve condition
1155
- for (i = 1; i <= net->Nvalves; i++)
1156
- {
1157
- j = net->Valve[i].Link;
1158
- link = &net->Link[j];
1159
- if (hyd->LinkStatus[j] >= XFCV)
1160
- {
1161
- if (rpt->Messageflag)
1162
- {
1163
- sprintf(pr->Msg, WARN05, LinkTxt[link->Type], link->ID,
1164
- StatTxt[hyd->LinkStatus[j]],
1165
- clocktime(rpt->Atime, time->Htime));
1166
- writeline(pr, pr->Msg);
1167
- }
1168
- flag = 5;
1169
- }
1170
- }
1171
-
1172
- // Check for abnormal pump condition
1173
- for (i = 1; i <= net->Npumps; i++)
1174
- {
1175
- pump = &net->Pump[i];
1176
- j = pump->Link;
1177
- s = hyd->LinkStatus[j];
1178
- if (hyd->LinkStatus[j] >= OPEN)
1179
- {
1180
- if (hyd->LinkFlow[j] > hyd->LinkSetting[j] * pump->Qmax) s = XFLOW;
1181
- if (hyd->LinkFlow[j] < 0.0) s = XHEAD;
1182
- }
1183
- if (s == XHEAD || s == XFLOW)
1184
- {
1185
- if (rpt->Messageflag)
1186
- {
1187
- sprintf(pr->Msg, WARN04, net->Link[j].ID, StatTxt[s],
1188
- clocktime(rpt->Atime, time->Htime));
1189
- writeline(pr, pr->Msg);
1190
- }
1191
- flag = 4;
1192
- }
1193
- }
1194
-
1195
- // Check if system is unbalanced
1196
- if (iter > hyd->MaxIter && relerr > hyd->Hacc)
1197
- {
1198
- if (rpt->Messageflag)
1199
- {
1200
- sprintf(pr->Msg, WARN01, clocktime(rpt->Atime, time->Htime));
1201
- if (hyd->ExtraIter == -1) strcat(pr->Msg, t_HALTED);
1202
- writeline(pr, pr->Msg);
1203
- }
1204
- flag = 1;
1205
- }
1206
-
1207
- // Check for disconnected network & update project's warning flag
1208
- if (flag > 0)
1209
- {
1210
- disconnected(pr);
1211
- pr->Warnflag = flag;
1212
- if (rpt->Messageflag) writeline(pr, " ");
1213
- }
1214
- return flag;
1215
- }
1216
-
1217
- void writehyderr(Project *pr, int errnode)
1218
- /*
1219
- **-----------------------------------------------------------
1220
- ** Input: none
1221
- ** Output: none
1222
- ** Purpose: outputs status & checks connectivity when
1223
- ** network hydraulic equations cannot be solved.
1224
- **-----------------------------------------------------------
1225
- */
1226
- {
1227
- Network *net = &pr->network;
1228
- Report *rpt = &pr->report;
1229
- Times *time = &pr->times;
1230
-
1231
- Snode *Node = net->Node;
1232
-
1233
- if (rpt->Messageflag)
1234
- {
1235
- sprintf(pr->Msg, FMT62, clocktime(rpt->Atime, time->Htime),
1236
- Node[errnode].ID);
1237
- writeline(pr, pr->Msg);
1238
- }
1239
- writehydstat(pr, 0, 0);
1240
- disconnected(pr);
1241
- }
1242
-
1243
- int disconnected(Project *pr)
1244
- /*
1245
- **-------------------------------------------------------------------
1246
- ** Input: None
1247
- ** Output: Returns number of disconnected nodes
1248
- ** Purpose: Tests current hydraulic solution to see if any closed
1249
- ** links have caused the network to become disconnected.
1250
- **-------------------------------------------------------------------
1251
- */
1252
- {
1253
- Network *net = &pr->network;
1254
- Hydraul *hyd = &pr->hydraul;
1255
- Report *rpt = &pr->report;
1256
- Times *time = &pr->times;
1257
-
1258
- int i, j;
1259
- int count, mcount;
1260
- int errcode = 0;
1261
- int *nodelist;
1262
- char *marked;
1263
- Snode *node;
1264
-
1265
- // Allocate memory for node list & marked list
1266
- nodelist = (int *)calloc(net->Nnodes + 1, sizeof(int));
1267
- marked = (char *)calloc(net->Nnodes + 1, sizeof(char));
1268
- ERRCODE(MEMCHECK(nodelist));
1269
- ERRCODE(MEMCHECK(marked));
1270
-
1271
- // If allocation fails return with 0 nodes disconnected
1272
- if (errcode)
1273
- {
1274
- free(nodelist);
1275
- free(marked);
1276
- return (0);
1277
- }
1278
-
1279
- // Place tanks on node list and marked list
1280
- for (i = 1; i <= net->Ntanks; i++)
1281
- {
1282
- j = net->Njuncs + i;
1283
- nodelist[i] = j;
1284
- marked[j] = 1;
1285
- }
1286
-
1287
- // Place junctions with negative demands on the lists
1288
- mcount = net->Ntanks;
1289
- for (i = 1; i <= net->Njuncs; i++)
1290
- {
1291
- if (hyd->NodeDemand[i] < 0.0)
1292
- {
1293
- mcount++;
1294
- nodelist[mcount] = i;
1295
- marked[i] = 1;
1296
- }
1297
- }
1298
-
1299
- // Mark all nodes that can be connected to tanks
1300
- // and count number of nodes remaining unmarked
1301
- marknodes(pr, mcount, nodelist, marked);
1302
- j = 0;
1303
- count = 0;
1304
- for (i = 1; i <= net->Njuncs; i++)
1305
- {
1306
- node = &net->Node[i];
1307
- if (!marked[i] && hyd->NodeDemand[i] != 0.0)
1308
- {
1309
- count++;
1310
- if (count <= MAXCOUNT && rpt->Messageflag)
1311
- {
1312
- sprintf(pr->Msg, WARN03a, node->ID,
1313
- clocktime(rpt->Atime, time->Htime));
1314
- writeline(pr, pr->Msg);
1315
- }
1316
- j = i; // Last unmarked node
1317
- }
1318
- }
1319
-
1320
- // Report number of unmarked nodes and find closed link
1321
- // on path from node j back to a tank
1322
- if (count > 0 && rpt->Messageflag)
1323
- {
1324
- if (count > MAXCOUNT)
1325
- {
1326
- sprintf(pr->Msg, WARN03b, count - MAXCOUNT,
1327
- clocktime(rpt->Atime, time->Htime));
1328
- writeline(pr, pr->Msg);
1329
- }
1330
- getclosedlink(pr, j, marked, nodelist);
1331
- }
1332
-
1333
- // Free allocated memory
1334
- free(nodelist);
1335
- free(marked);
1336
- return count;
1337
- }
1338
-
1339
- void marknodes(Project *pr, int m, int *nodelist, char *marked)
1340
- /*
1341
- **----------------------------------------------------------------
1342
- ** Input: m = number of source nodes
1343
- ** nodelist[] = list of nodes to be traced from
1344
- ** marked[] = TRUE if node connected to source
1345
- ** Output: None.
1346
- ** Purpose: Marks all junction nodes connected to tanks.
1347
- **----------------------------------------------------------------
1348
- */
1349
- {
1350
- Network *net = &pr->network;
1351
- Hydraul *hyd = &pr->hydraul;
1352
-
1353
- int i, j, k, n;
1354
- Padjlist alink;
1355
-
1356
- // Scan each successive entry of node list
1357
- n = 1;
1358
- while (n <= m)
1359
- {
1360
- // Scan all nodes connected to current node
1361
- i = nodelist[n];
1362
- for (alink = net->Adjlist[i]; alink != NULL; alink = alink->next)
1363
- {
1364
- // Get indexes of connecting link and node
1365
- k = alink->link;
1366
- j = alink->node;
1367
- if (marked[j]) continue;
1368
-
1369
- // Check if valve connection is in correct direction
1370
- switch (net->Link[k].Type)
1371
- {
1372
- case CVPIPE:
1373
- case PRV:
1374
- case PSV:
1375
- if (j == net->Link[k].N1) continue;
1376
- break;
1377
- default:
1378
- break;
1379
- }
1380
-
1381
- // Mark connection node if link not closed
1382
- if (hyd->LinkStatus[k] > CLOSED)
1383
- {
1384
- marked[j] = 1;
1385
- m++;
1386
- nodelist[m] = j;
1387
- }
1388
- }
1389
- n++;
1390
- }
1391
- }
1392
-
1393
- void getclosedlink(Project *pr, int i, char *marked, int *stack)
1394
- /*
1395
- **----------------------------------------------------------------
1396
- ** Input: i = junction index
1397
- ** marked[] = marks nodes already examined
1398
- ** stack[] = stack to hold nodes to examine
1399
- ** Output: None.
1400
- ** Purpose: Determines if a closed link connects to junction i.
1401
- **----------------------------------------------------------------
1402
- */
1403
- {
1404
- Network *net = &pr->network;
1405
-
1406
- int j, k;
1407
- Padjlist alink;
1408
-
1409
- int top = 0;
1410
-
1411
- // Mark the current junction as examined and push onto stack
1412
- marked[i] = 2;
1413
- stack[top] = i;
1414
-
1415
- while (top >= 0) {
1416
- i = stack[top--];
1417
- alink = net->Adjlist[i];
1418
-
1419
- // Iterate through each link adjacent to the current node
1420
- while (alink != NULL) {
1421
- k = alink->link;
1422
- j = alink->node;
1423
-
1424
- // Skip nodes that have already been examined
1425
- if (marked[j] == 2) {
1426
- alink = alink->next;
1427
- continue;
1428
- }
1429
-
1430
- // If a closed link is found, return and display a warning message
1431
- if (marked[j] == 1) {
1432
- sprintf(pr->Msg, WARN03c, net->Link[k].ID);
1433
- writeline(pr, pr->Msg);
1434
- return;
1435
- }
1436
-
1437
- // Mark the node as examined and push it onto the stack
1438
- marked[j] = 2;
1439
- stack[++top] = j;
1440
- alink = alink->next;
1441
- }
1442
- }
1443
-
1444
- }
1445
-
1446
- void writelimits(Project *pr, int j1, int j2)
1447
- /*
1448
- **--------------------------------------------------------------
1449
- ** Input: j1 = index of first output variable
1450
- ** j2 = index of last output variable
1451
- ** Output: none
1452
- ** Purpose: writes reporting criteria to output report
1453
- **--------------------------------------------------------------
1454
- */
1455
- {
1456
- Report *rpt = &pr->report;
1457
- int j;
1458
-
1459
- for (j = j1; j <= j2; j++)
1460
- {
1461
- if (rpt->Field[j].RptLim[LOW] < BIG)
1462
- {
1463
- sprintf(pr->Msg, FMT47, rpt->Field[j].Name,
1464
- rpt->Field[j].RptLim[LOW],
1465
- rpt->Field[j].Units);
1466
- writeline(pr, pr->Msg);
1467
- }
1468
- if (rpt->Field[j].RptLim[HI] > -BIG)
1469
- {
1470
- sprintf(pr->Msg, FMT48, rpt->Field[j].Name,
1471
- rpt->Field[j].RptLim[HI],
1472
- rpt->Field[j].Units);
1473
- writeline(pr, pr->Msg);
1474
- }
1475
- }
1476
- }
1477
-
1478
- int checklimits(Report *rpt, double *y, int j1, int j2)
1479
- /*
1480
- **--------------------------------------------------------------
1481
- ** Input: *y = array of output results
1482
- ** j1 = index of first output variable
1483
- ** j2 = index of last output variable
1484
- ** Output: returns 1 if criteria met, 0 otherwise
1485
- ** Purpose: checks if output reporting criteria is met
1486
- **--------------------------------------------------------------
1487
- */
1488
- {
1489
- int j;
1490
- for (j = j1; j <= j2; j++)
1491
- {
1492
- if (y[j] > rpt->Field[j].RptLim[LOW] ||
1493
- y[j] < rpt->Field[j].RptLim[HI]
1494
- ) return 0;
1495
- }
1496
- return 1;
1497
- }
1498
-
1499
- void writetime(Project *pr, char *fmt)
1500
- /*
1501
- **----------------------------------------------------------------
1502
- ** Input: fmt = format string
1503
- ** Output: none
1504
- ** Purpose: writes starting/ending time of a run to report file
1505
- **----------------------------------------------------------------
1506
- */
1507
- {
1508
- time_t timer;
1509
- time(&timer);
1510
- sprintf(pr->Msg, fmt, ctime(&timer));
1511
- writeline(pr, pr->Msg);
1512
- }
1513
-
1514
- char *clocktime(char *atime, long seconds)
1515
- /*
1516
- **--------------------------------------------------------------
1517
- ** Input: seconds = time in seconds
1518
- ** Output: atime = time in hrs:min
1519
- ** (returns pointer to atime)
1520
- ** Purpose: converts time in seconds to hours:minutes format
1521
- **--------------------------------------------------------------
1522
- */
1523
- {
1524
- long h, m, s;
1525
- h = seconds / 3600;
1526
- m = seconds % 3600 / 60;
1527
- s = seconds - 3600 * h - 60 * m;
1528
- sprintf(atime, "%01d:%02d:%02d", (int)h, (int)m, (int)s);
1529
- return atime;
1530
- }
1531
-
1532
- char *fillstr(char *s, char ch, int n)
1533
- /*
1534
- **---------------------------------------------------------
1535
- ** Fills n bytes of s to character ch.
1536
- ** NOTE: does not check for overwriting s.
1537
- **---------------------------------------------------------
1538
- */
1539
- {
1540
- int i;
1541
- for (i = 0; i <= n; i++) s[i] = ch;
1542
- s[n + 1] = '\0';
1543
- return (s);
1544
- }
1545
-
1546
- int getnodetype(Network *net, int i)
1547
- /*
1548
- **---------------------------------------------------------
1549
- ** Determines type of node with index i
1550
- ** (junction = 0, reservoir = 1, tank = 2).
1551
- **---------------------------------------------------------
1552
- */
1553
- {
1554
- if (i <= net->Njuncs) return 0;
1555
- if (net->Tank[i - net->Njuncs].A == 0.0) return 1;
1556
- return 2;
1557
- }