epyt-flow 0.1.0__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 (131) hide show
  1. epyt_flow/EPANET/EPANET/SRC_engines/AUTHORS +28 -0
  2. epyt_flow/EPANET/EPANET/SRC_engines/LICENSE +21 -0
  3. epyt_flow/EPANET/EPANET/SRC_engines/Readme_SRC_Engines.txt +18 -0
  4. epyt_flow/EPANET/EPANET/SRC_engines/enumstxt.h +134 -0
  5. epyt_flow/EPANET/EPANET/SRC_engines/epanet.c +5578 -0
  6. epyt_flow/EPANET/EPANET/SRC_engines/epanet2.c +865 -0
  7. epyt_flow/EPANET/EPANET/SRC_engines/epanet2.def +131 -0
  8. epyt_flow/EPANET/EPANET/SRC_engines/errors.dat +73 -0
  9. epyt_flow/EPANET/EPANET/SRC_engines/funcs.h +193 -0
  10. epyt_flow/EPANET/EPANET/SRC_engines/genmmd.c +1000 -0
  11. epyt_flow/EPANET/EPANET/SRC_engines/hash.c +177 -0
  12. epyt_flow/EPANET/EPANET/SRC_engines/hash.h +28 -0
  13. epyt_flow/EPANET/EPANET/SRC_engines/hydcoeffs.c +1151 -0
  14. epyt_flow/EPANET/EPANET/SRC_engines/hydraul.c +1117 -0
  15. epyt_flow/EPANET/EPANET/SRC_engines/hydsolver.c +720 -0
  16. epyt_flow/EPANET/EPANET/SRC_engines/hydstatus.c +476 -0
  17. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2.h +431 -0
  18. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_2.h +1786 -0
  19. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_enums.h +468 -0
  20. epyt_flow/EPANET/EPANET/SRC_engines/inpfile.c +810 -0
  21. epyt_flow/EPANET/EPANET/SRC_engines/input1.c +707 -0
  22. epyt_flow/EPANET/EPANET/SRC_engines/input2.c +864 -0
  23. epyt_flow/EPANET/EPANET/SRC_engines/input3.c +2170 -0
  24. epyt_flow/EPANET/EPANET/SRC_engines/main.c +93 -0
  25. epyt_flow/EPANET/EPANET/SRC_engines/mempool.c +142 -0
  26. epyt_flow/EPANET/EPANET/SRC_engines/mempool.h +24 -0
  27. epyt_flow/EPANET/EPANET/SRC_engines/output.c +852 -0
  28. epyt_flow/EPANET/EPANET/SRC_engines/project.c +1359 -0
  29. epyt_flow/EPANET/EPANET/SRC_engines/quality.c +685 -0
  30. epyt_flow/EPANET/EPANET/SRC_engines/qualreact.c +743 -0
  31. epyt_flow/EPANET/EPANET/SRC_engines/qualroute.c +694 -0
  32. epyt_flow/EPANET/EPANET/SRC_engines/report.c +1489 -0
  33. epyt_flow/EPANET/EPANET/SRC_engines/rules.c +1362 -0
  34. epyt_flow/EPANET/EPANET/SRC_engines/smatrix.c +871 -0
  35. epyt_flow/EPANET/EPANET/SRC_engines/text.h +497 -0
  36. epyt_flow/EPANET/EPANET/SRC_engines/types.h +874 -0
  37. epyt_flow/EPANET/EPANET-MSX/MSX_Updates.txt +53 -0
  38. epyt_flow/EPANET/EPANET-MSX/Src/dispersion.h +27 -0
  39. epyt_flow/EPANET/EPANET-MSX/Src/hash.c +107 -0
  40. epyt_flow/EPANET/EPANET-MSX/Src/hash.h +28 -0
  41. epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx.h +102 -0
  42. epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx_export.h +42 -0
  43. epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.c +937 -0
  44. epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.h +39 -0
  45. epyt_flow/EPANET/EPANET-MSX/Src/mempool.c +204 -0
  46. epyt_flow/EPANET/EPANET-MSX/Src/mempool.h +24 -0
  47. epyt_flow/EPANET/EPANET-MSX/Src/msxchem.c +1285 -0
  48. epyt_flow/EPANET/EPANET-MSX/Src/msxcompiler.c +368 -0
  49. epyt_flow/EPANET/EPANET-MSX/Src/msxdict.h +42 -0
  50. epyt_flow/EPANET/EPANET-MSX/Src/msxdispersion.c +586 -0
  51. epyt_flow/EPANET/EPANET-MSX/Src/msxerr.c +116 -0
  52. epyt_flow/EPANET/EPANET-MSX/Src/msxfile.c +260 -0
  53. epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.c +175 -0
  54. epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.h +35 -0
  55. epyt_flow/EPANET/EPANET-MSX/Src/msxinp.c +1504 -0
  56. epyt_flow/EPANET/EPANET-MSX/Src/msxout.c +401 -0
  57. epyt_flow/EPANET/EPANET-MSX/Src/msxproj.c +791 -0
  58. epyt_flow/EPANET/EPANET-MSX/Src/msxqual.c +2010 -0
  59. epyt_flow/EPANET/EPANET-MSX/Src/msxrpt.c +400 -0
  60. epyt_flow/EPANET/EPANET-MSX/Src/msxtank.c +422 -0
  61. epyt_flow/EPANET/EPANET-MSX/Src/msxtoolkit.c +1164 -0
  62. epyt_flow/EPANET/EPANET-MSX/Src/msxtypes.h +551 -0
  63. epyt_flow/EPANET/EPANET-MSX/Src/msxutils.c +524 -0
  64. epyt_flow/EPANET/EPANET-MSX/Src/msxutils.h +56 -0
  65. epyt_flow/EPANET/EPANET-MSX/Src/newton.c +158 -0
  66. epyt_flow/EPANET/EPANET-MSX/Src/newton.h +34 -0
  67. epyt_flow/EPANET/EPANET-MSX/Src/rk5.c +287 -0
  68. epyt_flow/EPANET/EPANET-MSX/Src/rk5.h +39 -0
  69. epyt_flow/EPANET/EPANET-MSX/Src/ros2.c +293 -0
  70. epyt_flow/EPANET/EPANET-MSX/Src/ros2.h +35 -0
  71. epyt_flow/EPANET/EPANET-MSX/Src/smatrix.c +816 -0
  72. epyt_flow/EPANET/EPANET-MSX/Src/smatrix.h +29 -0
  73. epyt_flow/EPANET/EPANET-MSX/readme.txt +14 -0
  74. epyt_flow/EPANET/compile.sh +4 -0
  75. epyt_flow/VERSION +1 -0
  76. epyt_flow/__init__.py +24 -0
  77. epyt_flow/data/__init__.py +0 -0
  78. epyt_flow/data/benchmarks/__init__.py +11 -0
  79. epyt_flow/data/benchmarks/batadal.py +257 -0
  80. epyt_flow/data/benchmarks/batadal_data.py +28 -0
  81. epyt_flow/data/benchmarks/battledim.py +473 -0
  82. epyt_flow/data/benchmarks/battledim_data.py +51 -0
  83. epyt_flow/data/benchmarks/gecco_water_quality.py +267 -0
  84. epyt_flow/data/benchmarks/leakdb.py +592 -0
  85. epyt_flow/data/benchmarks/leakdb_data.py +18923 -0
  86. epyt_flow/data/benchmarks/water_usage.py +123 -0
  87. epyt_flow/data/networks.py +650 -0
  88. epyt_flow/gym/__init__.py +4 -0
  89. epyt_flow/gym/control_gyms.py +47 -0
  90. epyt_flow/gym/scenario_control_env.py +101 -0
  91. epyt_flow/metrics.py +404 -0
  92. epyt_flow/models/__init__.py +2 -0
  93. epyt_flow/models/event_detector.py +31 -0
  94. epyt_flow/models/sensor_interpolation_detector.py +118 -0
  95. epyt_flow/rest_api/__init__.py +4 -0
  96. epyt_flow/rest_api/base_handler.py +70 -0
  97. epyt_flow/rest_api/res_manager.py +95 -0
  98. epyt_flow/rest_api/scada_data_handler.py +476 -0
  99. epyt_flow/rest_api/scenario_handler.py +352 -0
  100. epyt_flow/rest_api/server.py +106 -0
  101. epyt_flow/serialization.py +438 -0
  102. epyt_flow/simulation/__init__.py +5 -0
  103. epyt_flow/simulation/events/__init__.py +6 -0
  104. epyt_flow/simulation/events/actuator_events.py +259 -0
  105. epyt_flow/simulation/events/event.py +81 -0
  106. epyt_flow/simulation/events/leakages.py +404 -0
  107. epyt_flow/simulation/events/sensor_faults.py +267 -0
  108. epyt_flow/simulation/events/sensor_reading_attack.py +185 -0
  109. epyt_flow/simulation/events/sensor_reading_event.py +170 -0
  110. epyt_flow/simulation/events/system_event.py +88 -0
  111. epyt_flow/simulation/parallel_simulation.py +147 -0
  112. epyt_flow/simulation/scada/__init__.py +3 -0
  113. epyt_flow/simulation/scada/advanced_control.py +134 -0
  114. epyt_flow/simulation/scada/scada_data.py +1589 -0
  115. epyt_flow/simulation/scada/scada_data_export.py +255 -0
  116. epyt_flow/simulation/scenario_config.py +608 -0
  117. epyt_flow/simulation/scenario_simulator.py +1897 -0
  118. epyt_flow/simulation/scenario_visualizer.py +61 -0
  119. epyt_flow/simulation/sensor_config.py +1289 -0
  120. epyt_flow/topology.py +290 -0
  121. epyt_flow/uncertainty/__init__.py +3 -0
  122. epyt_flow/uncertainty/model_uncertainty.py +302 -0
  123. epyt_flow/uncertainty/sensor_noise.py +73 -0
  124. epyt_flow/uncertainty/uncertainties.py +555 -0
  125. epyt_flow/uncertainty/utils.py +206 -0
  126. epyt_flow/utils.py +306 -0
  127. epyt_flow-0.1.0.dist-info/LICENSE +21 -0
  128. epyt_flow-0.1.0.dist-info/METADATA +139 -0
  129. epyt_flow-0.1.0.dist-info/RECORD +131 -0
  130. epyt_flow-0.1.0.dist-info/WHEEL +5 -0
  131. epyt_flow-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,810 @@
1
+ /*
2
+ ******************************************************************************
3
+ Project: OWA EPANET
4
+ Version: 2.2
5
+ Module: inpfile.c
6
+ Description: saves network data to an EPANET formatted text file
7
+ Authors: see AUTHORS
8
+ Copyright: see AUTHORS
9
+ License: see LICENSE
10
+ Last Updated: 10/29/2019
11
+ ******************************************************************************
12
+ */
13
+
14
+ #include <stdlib.h>
15
+ #include <stdio.h>
16
+ #include <string.h>
17
+ #include <math.h>
18
+
19
+ #include "types.h"
20
+ #include "funcs.h"
21
+ #include "hash.h"
22
+ #include "text.h"
23
+
24
+ // Defined in enumstxt.h in EPANET.C
25
+ extern char *LinkTxt[];
26
+ extern char *FormTxt[];
27
+ extern char *StatTxt[];
28
+ extern char *FlowUnitsTxt[];
29
+ extern char *PressUnitsTxt[];
30
+ extern char *ControlTxt[];
31
+ extern char *SourceTxt[];
32
+ extern char *MixTxt[];
33
+ extern char *TstatTxt[];
34
+ extern char *RptFlagTxt[];
35
+ extern char *SectTxt[];
36
+
37
+ void saveauxdata(Project *pr, FILE *f)
38
+ /*
39
+ ------------------------------------------------------------
40
+ Writes auxilary data from original input file to new file.
41
+ ------------------------------------------------------------
42
+ */
43
+ {
44
+ int sect, newsect;
45
+ char *tok;
46
+ char write;
47
+ char line[MAXLINE + 1];
48
+ char s[MAXLINE + 1];
49
+ FILE *InFile = pr->parser.InFile;
50
+
51
+ // Re-open the input file
52
+ if (InFile == NULL)
53
+ {
54
+ InFile = fopen(pr->parser.InpFname, "rt");
55
+ if (InFile == NULL) return;
56
+ }
57
+ rewind(InFile);
58
+ sect = -1;
59
+
60
+ // Read each line of the input file
61
+ while (fgets(line, MAXLINE, InFile) != NULL)
62
+ {
63
+ strcpy(s, line);
64
+ tok = strtok(s, SEPSTR);
65
+ if (tok == NULL) continue;
66
+
67
+ // Check if line begins with a new section heading
68
+ if (*tok == '[')
69
+ {
70
+ newsect = findmatch(tok, SectTxt);
71
+ if (newsect >= 0)
72
+ {
73
+ sect = newsect;
74
+ if (sect == _END) break;
75
+
76
+ // Write section heading to file
77
+ switch (sect)
78
+ {
79
+ case _LABELS:
80
+ case _BACKDROP:
81
+ case _TAGS:
82
+ fprintf(f, "\n%s", line);
83
+ }
84
+ }
85
+ }
86
+
87
+ // Write line of auxilary data to file
88
+ else
89
+ {
90
+ write = FALSE;
91
+ switch (sect)
92
+ {
93
+ case _TAGS:
94
+ if (*tok == ';' ||
95
+ (match("NODE", tok) && findnode(&pr->network, strtok(NULL, SEPSTR))) ||
96
+ (match("LINK", tok) && findlink(&pr->network, strtok(NULL, SEPSTR))))
97
+ write = TRUE;
98
+ break;
99
+ case _LABELS:
100
+ case _BACKDROP:
101
+ write = TRUE; break;
102
+ default:
103
+ break;
104
+ }
105
+ if (write) fprintf(f, "%s", line);
106
+ }
107
+ }
108
+ fclose(InFile);
109
+ InFile = NULL;
110
+ }
111
+
112
+ int saveinpfile(Project *pr, const char *fname)
113
+ /*
114
+ -------------------------------------------------
115
+ Writes network data to text file.
116
+ -------------------------------------------------
117
+ */
118
+ {
119
+ Network *net = &pr->network;
120
+ Parser *parser = &pr->parser;
121
+ Report *rpt = &pr->report;
122
+ Outfile *out = &pr->outfile;
123
+ Hydraul *hyd = &pr->hydraul;
124
+ Quality *qual = &pr->quality;
125
+ Times *time = &pr->times;
126
+
127
+ int i, j, n;
128
+ double d, kc, ke, km, ucf;
129
+ char s[MAXLINE + 1], s1[MAXLINE + 1], s2[MAXLINE + 1];
130
+ Pdemand demand;
131
+ Psource source;
132
+ FILE *f;
133
+ Slink *link;
134
+ Stank *tank;
135
+ Snode *node;
136
+ Spump *pump;
137
+ Scontrol *control;
138
+ Scurve *curve;
139
+
140
+ // Open the new text file
141
+ if ((f = fopen(fname, "wt")) == NULL) return 302;
142
+
143
+ // Write [TITLE] section
144
+ fprintf(f, s_TITLE);
145
+ for (i = 0; i < 3; i++)
146
+ {
147
+ if (strlen(pr->Title[i]) > 0) fprintf(f, "\n%s", pr->Title[i]);
148
+ }
149
+
150
+ // Write [JUNCTIONS] section
151
+ // (Leave demands for [DEMANDS] section)
152
+ fprintf(f, "\n\n");
153
+ fprintf(f, s_JUNCTIONS);
154
+ for (i = 1; i <= net->Njuncs; i++)
155
+ {
156
+ node = &net->Node[i];
157
+ fprintf(f, "\n %-31s %12.4f", node->ID, node->El * pr->Ucf[ELEV]);
158
+ if (node->Comment) fprintf(f, " ;%s", node->Comment);
159
+ }
160
+
161
+ // Write [RESERVOIRS] section
162
+ fprintf(f, "\n\n");
163
+ fprintf(f, s_RESERVOIRS);
164
+ for (i = 1; i <= net->Ntanks; i++)
165
+ {
166
+ tank = &net->Tank[i];
167
+ if (tank->A == 0.0)
168
+ {
169
+ node = &net->Node[tank->Node];
170
+ sprintf(s, " %-31s %12.4f", node->ID, node->El * pr->Ucf[ELEV]);
171
+ if ((j = tank->Pat) > 0) sprintf(s1, " %s", net->Pattern[j].ID);
172
+ else strcpy(s1, " ");
173
+ fprintf(f, "\n%s %-31s", s, s1);
174
+ if (node->Comment) fprintf(f, " ;%s", node->Comment);
175
+ }
176
+ }
177
+
178
+ // Write [TANKS] section
179
+ fprintf(f, "\n\n");
180
+ fprintf(f, s_TANKS);
181
+ for (i = 1; i <= net->Ntanks; i++)
182
+ {
183
+ tank = &net->Tank[i];
184
+ if (tank->A > 0.0)
185
+ {
186
+ node = &net->Node[tank->Node];
187
+ sprintf(s, " %-31s %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f",
188
+ node->ID, node->El * pr->Ucf[ELEV],
189
+ (tank->H0 - node->El) * pr->Ucf[ELEV],
190
+ (tank->Hmin - node->El) * pr->Ucf[ELEV],
191
+ (tank->Hmax - node->El) * pr->Ucf[ELEV],
192
+ sqrt(4.0 * tank->A / PI) * pr->Ucf[ELEV],
193
+ tank->Vmin * SQR(pr->Ucf[ELEV]) * pr->Ucf[ELEV]);
194
+ if ((j = tank->Vcurve) > 0) sprintf(s1, "%s", net->Curve[j].ID);
195
+ else if (tank->CanOverflow) strcpy(s1, "*");
196
+ else strcpy(s1, " ");
197
+ fprintf(f, "\n%s %-31s", s, s1);
198
+ if (tank->CanOverflow) fprintf(f, " YES ");
199
+ if (node->Comment) fprintf(f, " ;%s", node->Comment);
200
+ }
201
+ }
202
+
203
+ // Write [PIPES] section
204
+ fprintf(f, "\n\n");
205
+ fprintf(f, s_PIPES);
206
+ for (i = 1; i <= net->Nlinks; i++)
207
+ {
208
+ link = &net->Link[i];
209
+ if (link->Type <= PIPE)
210
+ {
211
+ d = link->Diam;
212
+ kc = link->Kc;
213
+ if (hyd->Formflag == DW) kc = kc * pr->Ucf[ELEV] * 1000.0;
214
+ km = link->Km * SQR(d) * SQR(d) / 0.02517;
215
+
216
+ sprintf(s, " %-31s %-31s %-31s %12.4f %12.4f %12.4f %12.4f",
217
+ link->ID, net->Node[link->N1].ID, net->Node[link->N2].ID,
218
+ link->Len * pr->Ucf[LENGTH], d * pr->Ucf[DIAM], kc, km);
219
+
220
+ if (link->Type == CVPIPE) sprintf(s2, "CV");
221
+ else if (link->Status == CLOSED) sprintf(s2, "CLOSED");
222
+ else strcpy(s2, " ");
223
+ fprintf(f, "\n%s %-6s", s, s2);
224
+ if (link->Comment) fprintf(f, " ;%s", link->Comment);
225
+ }
226
+ }
227
+
228
+ // Write [PUMPS] section
229
+ fprintf(f, "\n\n");
230
+ fprintf(f, s_PUMPS);
231
+ for (i = 1; i <= net->Npumps; i++)
232
+ {
233
+ n = net->Pump[i].Link;
234
+ link = &net->Link[n];
235
+ pump = &net->Pump[i];
236
+ sprintf(s, " %-31s %-31s %-31s", link->ID, net->Node[link->N1].ID,
237
+ net->Node[link->N2].ID);
238
+
239
+ // Pump has constant power
240
+ if (pump->Ptype == CONST_HP) sprintf(s1, " POWER %.4f", link->Km);
241
+
242
+ // Pump has a head curve
243
+ else if ((j = pump->Hcurve) > 0)
244
+ {
245
+ sprintf(s1, " HEAD %s", net->Curve[j].ID);
246
+ }
247
+
248
+ // Old format used for pump curve
249
+ else
250
+ {
251
+ fprintf(f, "\n%s %12.4f %12.4f %12.4f 0.0 %12.4f", s,
252
+ -pump->H0 * pr->Ucf[HEAD],
253
+ (-pump->H0 - pump->R * pow(pump->Q0, pump->N)) * pr->Ucf[HEAD],
254
+ pump->Q0 * pr->Ucf[FLOW], pump->Qmax * pr->Ucf[FLOW]);
255
+ continue;
256
+ }
257
+ strcat(s, s1);
258
+
259
+ // Optional speed pattern
260
+ if ((j = pump->Upat) > 0)
261
+ {
262
+ sprintf(s1, " PATTERN %s", net->Pattern[j].ID);
263
+ strcat(s, s1);
264
+ }
265
+
266
+ // Optional speed setting
267
+ if (link->Kc != 1.0)
268
+ {
269
+ sprintf(s1, " SPEED %.4f", link->Kc);
270
+ strcat(s, s1);
271
+ }
272
+
273
+ fprintf(f, "\n%s", s);
274
+ if (link->Comment) fprintf(f, " ;%s", link->Comment);
275
+
276
+ }
277
+
278
+ // Write [VALVES] section
279
+ fprintf(f, "\n\n");
280
+ fprintf(f, s_VALVES);
281
+ for (i = 1; i <= net->Nvalves; i++)
282
+ {
283
+ n = net->Valve[i].Link;
284
+ link = &net->Link[n];
285
+ d = link->Diam;
286
+
287
+ // Valve setting
288
+ kc = link->Kc;
289
+ if (kc == MISSING) kc = 0.0;
290
+ switch (link->Type)
291
+ {
292
+ case FCV:
293
+ kc *= pr->Ucf[FLOW];
294
+ break;
295
+ case PRV:
296
+ case PSV:
297
+ case PBV:
298
+ kc *= pr->Ucf[PRESSURE];
299
+ break;
300
+ default:
301
+ break;
302
+ }
303
+ km = link->Km * SQR(d) * SQR(d) / 0.02517;
304
+
305
+ sprintf(s, " %-31s %-31s %-31s %12.4f %5s",
306
+ link->ID, net->Node[link->N1].ID,
307
+ net->Node[link->N2].ID, d * pr->Ucf[DIAM],
308
+ LinkTxt[link->Type]);
309
+
310
+ // For GPV, setting = head curve index
311
+ if (link->Type == GPV && (j = ROUND(link->Kc)) > 0)
312
+ {
313
+ sprintf(s1, "%-31s %12.4f", net->Curve[j].ID, km);
314
+ }
315
+ else sprintf(s1, "%12.4f %12.4f", kc, km);
316
+ fprintf(f, "\n%s %s", s, s1);
317
+ if (link->Comment) fprintf(f, " ;%s", link->Comment);
318
+ }
319
+
320
+
321
+ // Write [DEMANDS] section
322
+ fprintf(f, "\n\n");
323
+ fprintf(f, s_DEMANDS);
324
+ ucf = pr->Ucf[DEMAND];
325
+ for (i = 1; i <= net->Njuncs; i++)
326
+ {
327
+ node = &net->Node[i];
328
+ for (demand = node->D; demand != NULL; demand = demand->next)
329
+ {
330
+ sprintf(s, " %-31s %14.6f", node->ID, ucf * demand->Base);
331
+ if ((j = demand->Pat) > 0) sprintf(s1, " %-31s", net->Pattern[j].ID);
332
+ else strcpy(s1, " ");
333
+ fprintf(f, "\n%s %-31s", s, s1);
334
+ if (demand->Name) fprintf(f, " ;%s", demand->Name);
335
+ }
336
+ }
337
+
338
+
339
+ // Write [EMITTERS] section
340
+ fprintf(f, "\n\n");
341
+ fprintf(f, s_EMITTERS);
342
+ for (i = 1; i <= net->Njuncs; i++)
343
+ {
344
+ node = &net->Node[i];
345
+ if (node->Ke == 0.0) continue;
346
+ ke = pr->Ucf[FLOW] / pow(pr->Ucf[PRESSURE] * node->Ke, (1.0 / hyd->Qexp));
347
+ fprintf(f, "\n %-31s %14.6f", node->ID, ke);
348
+ }
349
+
350
+ // Write [STATUS] section
351
+ fprintf(f, "\n\n");
352
+ fprintf(f, s_STATUS);
353
+ for (i = 1; i <= net->Nlinks; i++)
354
+ {
355
+ link = &net->Link[i];
356
+ if (link->Type <= PUMP)
357
+ {
358
+ if (link->Status == CLOSED)
359
+ {
360
+ fprintf(f, "\n %-31s %s", link->ID, StatTxt[CLOSED]);
361
+ }
362
+
363
+ // Write pump speed here for pumps with old-style pump curve input
364
+ else if (link->Type == PUMP)
365
+ {
366
+ n = findpump(net, i);
367
+ pump = &net->Pump[n];
368
+ if (pump->Hcurve == 0 && pump->Ptype != CONST_HP &&
369
+ link->Kc != 1.0)
370
+ {
371
+ fprintf(f, "\n %-31s %-.4f", link->ID, link->Kc);
372
+ }
373
+ }
374
+ }
375
+
376
+ // Write fixed-status PRVs & PSVs (setting = MISSING)
377
+ else if (link->Kc == MISSING)
378
+ {
379
+ if (link->Status == OPEN)
380
+ {
381
+ fprintf(f, "\n %-31s %s", link->ID, StatTxt[OPEN]);
382
+ }
383
+ if (link->Status == CLOSED)
384
+ {
385
+ fprintf(f, "\n%-31s %s", link->ID, StatTxt[CLOSED]);
386
+ }
387
+ }
388
+ }
389
+
390
+ // Write [PATTERNS] section
391
+ // (Use 6 pattern factors per line)
392
+ fprintf(f, "\n\n");
393
+ fprintf(f, s_PATTERNS);
394
+ for (i = 1; i <= net->Npats; i++)
395
+ {
396
+ if (net->Pattern[i].Comment) fprintf(f, "\n;%s", net->Pattern[i].Comment);
397
+ for (j = 0; j < net->Pattern[i].Length; j++)
398
+ {
399
+ if (j % 6 == 0) fprintf(f, "\n %-31s", net->Pattern[i].ID);
400
+ fprintf(f, " %12.4f", net->Pattern[i].F[j]);
401
+ }
402
+ }
403
+
404
+ // Write [CURVES] section
405
+ fprintf(f, "\n\n");
406
+ fprintf(f, s_CURVES);
407
+ for (i = 1; i <= net->Ncurves; i++)
408
+ {
409
+ if (net->Curve[i].Comment) fprintf(f, "\n;%s", net->Curve[i].Comment);
410
+ for (j = 0; j < net->Curve[i].Npts; j++)
411
+ {
412
+ curve = &net->Curve[i];
413
+ fprintf(f, "\n %-31s %12.4f %12.4f", curve->ID, curve->X[j], curve->Y[j]);
414
+ }
415
+ }
416
+
417
+ // Write [CONTROLS] section
418
+ fprintf(f, "\n\n");
419
+ fprintf(f, s_CONTROLS);
420
+ for (i = 1; i <= net->Ncontrols; i++)
421
+ {
422
+ // Check that controlled link exists
423
+ control = &net->Control[i];
424
+ if ((j = control->Link) <= 0) continue;
425
+ link = &net->Link[j];
426
+
427
+ // Get text of control's link status/setting
428
+ if (control->Setting == MISSING)
429
+ {
430
+ sprintf(s, " LINK %s %s ", link->ID, StatTxt[control->Status]);
431
+ }
432
+ else
433
+ {
434
+ kc = control->Setting;
435
+ switch (link->Type)
436
+ {
437
+ case PRV:
438
+ case PSV:
439
+ case PBV:
440
+ kc *= pr->Ucf[PRESSURE];
441
+ break;
442
+ case FCV:
443
+ kc *= pr->Ucf[FLOW];
444
+ break;
445
+ default:
446
+ break;
447
+ }
448
+ sprintf(s, " LINK %s %.4f", link->ID, kc);
449
+ }
450
+
451
+ switch (control->Type)
452
+ {
453
+ // Print level control
454
+ case LOWLEVEL:
455
+ case HILEVEL:
456
+ n = control->Node;
457
+ node = &net->Node[n];
458
+ kc = control->Grade - node->El;
459
+ if (n > net->Njuncs) kc *= pr->Ucf[HEAD];
460
+ else kc *= pr->Ucf[PRESSURE];
461
+ fprintf(f, "\n%s IF NODE %s %s %.4f", s, node->ID,
462
+ ControlTxt[control->Type], kc);
463
+ break;
464
+
465
+ // Print timer control
466
+ case TIMER:
467
+ fprintf(f, "\n%s AT %s %.4f HOURS", s, ControlTxt[TIMER],
468
+ control->Time / 3600.);
469
+ break;
470
+
471
+ // Print time-of-day control
472
+ case TIMEOFDAY:
473
+ fprintf(f, "\n%s AT %s %s", s, ControlTxt[TIMEOFDAY],
474
+ clocktime(rpt->Atime, control->Time));
475
+ break;
476
+ }
477
+ }
478
+
479
+ // Write [RULES] section
480
+ fprintf(f, "\n\n");
481
+ fprintf(f, s_RULES);
482
+ for (i = 1; i <= net->Nrules; i++)
483
+ {
484
+ fprintf(f, "\nRULE %s", pr->network.Rule[i].label);
485
+ writerule(pr, f, i); // see RULES.C
486
+ fprintf(f, "\n");
487
+ }
488
+
489
+ // Write [QUALITY] section
490
+ // (Skip nodes with default quality of 0)
491
+ fprintf(f, "\n\n");
492
+ fprintf(f, s_QUALITY);
493
+ for (i = 1; i <= net->Nnodes; i++)
494
+ {
495
+ node = &net->Node[i];
496
+ if (node->C0 == 0.0) continue;
497
+ fprintf(f, "\n %-31s %14.6f", node->ID, node->C0 * pr->Ucf[QUALITY]);
498
+ }
499
+
500
+ // Write [SOURCES] section
501
+ fprintf(f, "\n\n");
502
+ fprintf(f, s_SOURCES);
503
+ for (i = 1; i <= net->Nnodes; i++)
504
+ {
505
+ node = &net->Node[i];
506
+ source = node->S;
507
+ if (source == NULL) continue;
508
+ sprintf(s, " %-31s %-8s %14.6f", node->ID, SourceTxt[source->Type],
509
+ source->C0);
510
+ if ((j = source->Pat) > 0)
511
+ {
512
+ sprintf(s1, "%s", net->Pattern[j].ID);
513
+ }
514
+ else strcpy(s1, "");
515
+ fprintf(f, "\n%s %s", s, s1);
516
+ }
517
+
518
+ // Write [MIXING] section
519
+ fprintf(f, "\n\n");
520
+ fprintf(f, s_MIXING);
521
+ for (i = 1; i <= net->Ntanks; i++)
522
+ {
523
+ tank = &net->Tank[i];
524
+ if (tank->A == 0.0) continue;
525
+ fprintf(f, "\n %-31s %-8s %12.4f", net->Node[tank->Node].ID,
526
+ MixTxt[tank->MixModel], (tank->V1max / tank->Vmax));
527
+ }
528
+
529
+ // Write [REACTIONS] section
530
+ fprintf(f, "\n\n");
531
+ fprintf(f, s_REACTIONS);
532
+
533
+ // General parameters
534
+ fprintf(f, "\n ORDER BULK %-.2f", qual->BulkOrder);
535
+ fprintf(f, "\n ORDER WALL %-.0f", qual->WallOrder);
536
+ fprintf(f, "\n ORDER TANK %-.2f", qual->TankOrder);
537
+ fprintf(f, "\n GLOBAL BULK %-.6f", qual->Kbulk * SECperDAY);
538
+ fprintf(f, "\n GLOBAL WALL %-.6f", qual->Kwall * SECperDAY);
539
+
540
+ if (qual->Climit > 0.0)
541
+ {
542
+ fprintf(f, "\n LIMITING POTENTIAL %-.6f", qual->Climit * pr->Ucf[QUALITY]);
543
+ }
544
+ if (qual->Rfactor != MISSING && qual->Rfactor != 0.0)
545
+ {
546
+ fprintf(f, "\n ROUGHNESS CORRELATION %-.6f", qual->Rfactor);
547
+ }
548
+
549
+ // Pipe-specific parameters
550
+ for (i = 1; i <= net->Nlinks; i++)
551
+ {
552
+ link = &net->Link[i];
553
+ if (link->Type > PIPE) continue;
554
+ if (link->Kb != qual->Kbulk)
555
+ {
556
+ fprintf(f, "\n BULK %-31s %-.6f", link->ID, link->Kb * SECperDAY);
557
+ }
558
+ if (link->Kw != qual->Kwall)
559
+ {
560
+ fprintf(f, "\n WALL %-31s %-.6f", link->ID, link->Kw * SECperDAY);
561
+ }
562
+ }
563
+
564
+ // Tank parameters
565
+ for (i = 1; i <= net->Ntanks; i++)
566
+ {
567
+ tank = &net->Tank[i];
568
+ if (tank->A == 0.0) continue;
569
+ if (tank->Kb != qual->Kbulk)
570
+ {
571
+ fprintf(f, "\n TANK %-31s %-.6f", net->Node[tank->Node].ID,
572
+ tank->Kb * SECperDAY);
573
+ }
574
+ }
575
+
576
+ // Write [ENERGY] section
577
+ fprintf(f, "\n\n");
578
+ fprintf(f, s_ENERGY);
579
+
580
+ // General parameters
581
+ if (hyd->Ecost != 0.0)
582
+ {
583
+ fprintf(f, "\n GLOBAL PRICE %-.4f", hyd->Ecost);
584
+ }
585
+ if (hyd->Epat != 0)
586
+ {
587
+ fprintf(f, "\n GLOBAL PATTERN %s", net->Pattern[hyd->Epat].ID);
588
+ }
589
+ fprintf(f, "\n GLOBAL EFFIC %-.4f", hyd->Epump);
590
+ fprintf(f, "\n DEMAND CHARGE %-.4f", hyd->Dcost);
591
+
592
+ // Pump-specific parameters
593
+ for (i = 1; i <= net->Npumps; i++)
594
+ {
595
+ pump = &net->Pump[i];
596
+ if (pump->Ecost > 0.0)
597
+ {
598
+ fprintf(f, "\n PUMP %-31s PRICE %-.4f", net->Link[pump->Link].ID,
599
+ pump->Ecost);
600
+ }
601
+ if (pump->Epat > 0.0)
602
+ {
603
+ fprintf(f, "\n PUMP %-31s PATTERN %s", net->Link[pump->Link].ID,
604
+ net->Pattern[pump->Epat].ID);
605
+ }
606
+ if (pump->Ecurve > 0.0)
607
+ {
608
+ fprintf(f, "\n PUMP %-31s EFFIC %s", net->Link[pump->Link].ID,
609
+ net->Curve[pump->Ecurve].ID);
610
+ }
611
+ }
612
+
613
+ // Write [TIMES] section
614
+ fprintf(f, "\n\n");
615
+ fprintf(f, s_TIMES);
616
+ fprintf(f, "\n DURATION %s", clocktime(rpt->Atime, time->Dur));
617
+ fprintf(f, "\n HYDRAULIC TIMESTEP %s", clocktime(rpt->Atime, time->Hstep));
618
+ fprintf(f, "\n QUALITY TIMESTEP %s", clocktime(rpt->Atime, time->Qstep));
619
+ fprintf(f, "\n REPORT TIMESTEP %s", clocktime(rpt->Atime, time->Rstep));
620
+ fprintf(f, "\n REPORT START %s", clocktime(rpt->Atime, time->Rstart));
621
+ fprintf(f, "\n PATTERN TIMESTEP %s", clocktime(rpt->Atime, time->Pstep));
622
+ fprintf(f, "\n PATTERN START %s", clocktime(rpt->Atime, time->Pstart));
623
+ fprintf(f, "\n RULE TIMESTEP %s", clocktime(rpt->Atime, time->Rulestep));
624
+ fprintf(f, "\n START CLOCKTIME %s", clocktime(rpt->Atime, time->Tstart));
625
+ fprintf(f, "\n STATISTIC %s", TstatTxt[rpt->Tstatflag]);
626
+
627
+ // Write [OPTIONS] section
628
+ fprintf(f, "\n\n");
629
+ fprintf(f, s_OPTIONS);
630
+ fprintf(f, "\n UNITS %s", FlowUnitsTxt[parser->Flowflag]);
631
+ fprintf(f, "\n PRESSURE %s", PressUnitsTxt[parser->Pressflag]);
632
+ fprintf(f, "\n HEADLOSS %s", FormTxt[hyd->Formflag]);
633
+ switch (out->Hydflag)
634
+ {
635
+ case USE:
636
+ fprintf(f, "\n HYDRAULICS USE %s", out->HydFname);
637
+ break;
638
+ case SAVE:
639
+ fprintf(f, "\n HYDRAULICS SAVE %s", out->HydFname);
640
+ break;
641
+ }
642
+ if (hyd->ExtraIter == -1)
643
+ {
644
+ fprintf(f, "\n UNBALANCED STOP");
645
+ }
646
+ if (hyd->ExtraIter >= 0)
647
+ {
648
+ fprintf(f, "\n UNBALANCED CONTINUE %d", hyd->ExtraIter);
649
+ }
650
+
651
+ switch (qual->Qualflag)
652
+ {
653
+ case CHEM:
654
+ fprintf(f, "\n QUALITY %s %s",
655
+ qual->ChemName, qual->ChemUnits);
656
+ break;
657
+ case TRACE:
658
+ fprintf(f, "\n QUALITY TRACE %-31s",
659
+ net->Node[qual->TraceNode].ID);
660
+ break;
661
+ case AGE:
662
+ fprintf(f, "\n QUALITY AGE");
663
+ break;
664
+ case NONE:
665
+ fprintf(f, "\n QUALITY NONE");
666
+ break;
667
+ }
668
+
669
+ fprintf(f, "\n DEMAND MULTIPLIER %-.4f", hyd->Dmult);
670
+ fprintf(f, "\n EMITTER EXPONENT %-.4f", 1.0 / hyd->Qexp);
671
+ fprintf(f, "\n VISCOSITY %-.6f", hyd->Viscos / VISCOS);
672
+ fprintf(f, "\n DIFFUSIVITY %-.6f", qual->Diffus / DIFFUS);
673
+ fprintf(f, "\n SPECIFIC GRAVITY %-.6f", hyd->SpGrav);
674
+ fprintf(f, "\n TRIALS %-d", hyd->MaxIter);
675
+ fprintf(f, "\n ACCURACY %-.8f", hyd->Hacc);
676
+ fprintf(f, "\n TOLERANCE %-.8f", qual->Ctol * pr->Ucf[QUALITY]);
677
+ fprintf(f, "\n CHECKFREQ %-d", hyd->CheckFreq);
678
+ fprintf(f, "\n MAXCHECK %-d", hyd->MaxCheck);
679
+ fprintf(f, "\n DAMPLIMIT %-.8f", hyd->DampLimit);
680
+ if (hyd->HeadErrorLimit > 0.0)
681
+ {
682
+ fprintf(f, "\n HEADERROR %-.8f",
683
+ hyd->HeadErrorLimit * pr->Ucf[HEAD]);
684
+ }
685
+ if (hyd->FlowChangeLimit > 0.0)
686
+ {
687
+ fprintf(f, "\n FLOWCHANGE %-.8f",
688
+ hyd->FlowChangeLimit * pr->Ucf[FLOW]);
689
+ }
690
+ if (hyd->DemandModel == PDA)
691
+ {
692
+ fprintf(f, "\n DEMAND MODEL PDA");
693
+ fprintf(f, "\n MINIMUM PRESSURE %-.4f", hyd->Pmin * pr->Ucf[PRESSURE]);
694
+ fprintf(f, "\n REQUIRED PRESSURE %-.4f", hyd->Preq * pr->Ucf[PRESSURE]);
695
+ fprintf(f, "\n PRESSURE EXPONENT %-.4f", hyd->Pexp);
696
+ }
697
+
698
+ // Write [REPORT] section
699
+ fprintf(f, "\n\n");
700
+ fprintf(f, s_REPORT);
701
+
702
+ // General options
703
+ fprintf(f, "\n PAGESIZE %d", rpt->PageSize);
704
+ fprintf(f, "\n STATUS %s", RptFlagTxt[rpt->Statflag]);
705
+ fprintf(f, "\n SUMMARY %s", RptFlagTxt[rpt->Summaryflag]);
706
+ fprintf(f, "\n ENERGY %s", RptFlagTxt[rpt->Energyflag]);
707
+ fprintf(f, "\n MESSAGES %s", RptFlagTxt[rpt->Messageflag]);
708
+ if (strlen(rpt->Rpt2Fname) > 0)
709
+ {
710
+ fprintf(f, "\n FILE %s", rpt->Rpt2Fname);
711
+ }
712
+
713
+ // Node reporting
714
+ switch (rpt->Nodeflag)
715
+ {
716
+ case 0:
717
+ fprintf(f, "\n NODES NONE");
718
+ break;
719
+ case 1:
720
+ fprintf(f, "\n NODES ALL");
721
+ break;
722
+ default:
723
+ j = 0;
724
+ for (i = 1; i <= net->Nnodes; i++)
725
+ {
726
+ node = &net->Node[i];
727
+ if (node->Rpt == 1)
728
+ {
729
+ if (j % 5 == 0) fprintf(f, "\n NODES ");
730
+ fprintf(f, "%s ", node->ID);
731
+ j++;
732
+ }
733
+ }
734
+ }
735
+
736
+ // Link reporting
737
+ switch (rpt->Linkflag)
738
+ {
739
+ case 0:
740
+ fprintf(f, "\n LINKS NONE");
741
+ break;
742
+ case 1:
743
+ fprintf(f, "\n LINKS ALL");
744
+ break;
745
+ default:
746
+ j = 0;
747
+ for (i = 1; i <= net->Nlinks; i++)
748
+ {
749
+ link = &net->Link[i];
750
+ if (link->Rpt == 1)
751
+ {
752
+ if (j % 5 == 0) fprintf(f, "\n LINKS ");
753
+ fprintf(f, "%s ", link->ID);
754
+ j++;
755
+ }
756
+ }
757
+ }
758
+
759
+ // Field formatting options
760
+ for (i = 0; i < FRICTION; i++)
761
+ {
762
+ SField *field = &rpt->Field[i];
763
+ if (field->Enabled == TRUE)
764
+ {
765
+ fprintf(f, "\n %-20sPRECISION %d", field->Name, field->Precision);
766
+ if (field->RptLim[LOW] < BIG)
767
+ {
768
+ fprintf(f, "\n %-20sBELOW %.6f", field->Name, field->RptLim[LOW]);
769
+ }
770
+ if (field->RptLim[HI] > -BIG)
771
+ {
772
+ fprintf(f, "\n %-20sABOVE %.6f", field->Name, field->RptLim[HI]);
773
+ }
774
+ }
775
+ else fprintf(f, "\n %-20sNO",field->Name);
776
+ }
777
+
778
+ // Write [COORDINATES] section
779
+ fprintf(f, "\n\n");
780
+ fprintf(f, s_COORDS);
781
+ for (i = 1; i <= net->Nnodes; i++)
782
+ {
783
+ node = &net->Node[i];
784
+ if (node->X == MISSING || node->Y == MISSING) continue;
785
+ fprintf(f, "\n %-31s %14.6f %14.6f", node->ID, node->X, node->Y);
786
+ }
787
+
788
+ // Write [VERTICES] section
789
+ fprintf(f, "\n\n");
790
+ fprintf(f, s_VERTICES);
791
+ for (i = 1; i <= net->Nlinks; i++)
792
+ {
793
+ link = &net->Link[i];
794
+ if (link->Vertices != NULL)
795
+ {
796
+ for (j = 0; j < link->Vertices->Npts; j++)
797
+ fprintf(f, "\n %-31s %14.6f %14.6f",
798
+ link->ID, link->Vertices->X[j], link->Vertices->Y[j]);
799
+ }
800
+ }
801
+
802
+ // Save auxilary data to new input file
803
+ fprintf(f, "\n");
804
+ saveauxdata(pr, f);
805
+
806
+ // Close the new input file
807
+ fprintf(f, "\n%s\n", s_END);
808
+ fclose(f);
809
+ return 0;
810
+ }