epanet-plus 0.0.1__pp311-pypy311_pp73-win_amd64.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.
Potentially problematic release.
This version of epanet-plus might be problematic. Click here for more details.
- docs/conf.py +67 -0
- epanet-msx-src/dispersion.h +27 -0
- epanet-msx-src/hash.c +107 -0
- epanet-msx-src/hash.h +28 -0
- epanet-msx-src/include/epanetmsx.h +104 -0
- epanet-msx-src/include/epanetmsx_export.h +42 -0
- epanet-msx-src/mathexpr.c +937 -0
- epanet-msx-src/mathexpr.h +39 -0
- epanet-msx-src/mempool.c +204 -0
- epanet-msx-src/mempool.h +24 -0
- epanet-msx-src/msxchem.c +1285 -0
- epanet-msx-src/msxcompiler.c +368 -0
- epanet-msx-src/msxdict.h +42 -0
- epanet-msx-src/msxdispersion.c +586 -0
- epanet-msx-src/msxerr.c +116 -0
- epanet-msx-src/msxfile.c +260 -0
- epanet-msx-src/msxfuncs.c +175 -0
- epanet-msx-src/msxfuncs.h +35 -0
- epanet-msx-src/msxinp.c +1504 -0
- epanet-msx-src/msxout.c +398 -0
- epanet-msx-src/msxproj.c +791 -0
- epanet-msx-src/msxqual.c +2011 -0
- epanet-msx-src/msxrpt.c +400 -0
- epanet-msx-src/msxtank.c +422 -0
- epanet-msx-src/msxtoolkit.c +1164 -0
- epanet-msx-src/msxtypes.h +551 -0
- epanet-msx-src/msxutils.c +524 -0
- epanet-msx-src/msxutils.h +56 -0
- epanet-msx-src/newton.c +158 -0
- epanet-msx-src/newton.h +34 -0
- epanet-msx-src/rk5.c +287 -0
- epanet-msx-src/rk5.h +39 -0
- epanet-msx-src/ros2.c +293 -0
- epanet-msx-src/ros2.h +35 -0
- epanet-msx-src/smatrix.c +816 -0
- epanet-msx-src/smatrix.h +29 -0
- epanet-src/AUTHORS +60 -0
- epanet-src/LICENSE +21 -0
- epanet-src/enumstxt.h +151 -0
- epanet-src/epanet.c +5937 -0
- epanet-src/epanet2.c +961 -0
- epanet-src/epanet2.def +131 -0
- epanet-src/errors.dat +79 -0
- epanet-src/flowbalance.c +186 -0
- epanet-src/funcs.h +219 -0
- epanet-src/genmmd.c +1000 -0
- epanet-src/hash.c +177 -0
- epanet-src/hash.h +28 -0
- epanet-src/hydcoeffs.c +1303 -0
- epanet-src/hydraul.c +1164 -0
- epanet-src/hydsolver.c +781 -0
- epanet-src/hydstatus.c +442 -0
- epanet-src/include/epanet2.h +466 -0
- epanet-src/include/epanet2_2.h +1962 -0
- epanet-src/include/epanet2_enums.h +518 -0
- epanet-src/inpfile.c +884 -0
- epanet-src/input1.c +672 -0
- epanet-src/input2.c +970 -0
- epanet-src/input3.c +2265 -0
- epanet-src/leakage.c +527 -0
- epanet-src/mempool.c +146 -0
- epanet-src/mempool.h +24 -0
- epanet-src/output.c +853 -0
- epanet-src/project.c +1691 -0
- epanet-src/quality.c +695 -0
- epanet-src/qualreact.c +800 -0
- epanet-src/qualroute.c +696 -0
- epanet-src/report.c +1559 -0
- epanet-src/rules.c +1500 -0
- epanet-src/smatrix.c +871 -0
- epanet-src/text.h +508 -0
- epanet-src/types.h +928 -0
- epanet-src/util/cstr_helper.c +59 -0
- epanet-src/util/cstr_helper.h +38 -0
- epanet-src/util/errormanager.c +92 -0
- epanet-src/util/errormanager.h +39 -0
- epanet-src/util/filemanager.c +212 -0
- epanet-src/util/filemanager.h +81 -0
- epanet-src/validate.c +408 -0
- epanet.pypy311-pp73-win_amd64.pyd +0 -0
- epanet_plus/VERSION +1 -0
- epanet_plus/__init__.py +8 -0
- epanet_plus/epanet_plus.c +118 -0
- epanet_plus/epanet_toolkit.py +2730 -0
- epanet_plus/epanet_wrapper.py +2414 -0
- epanet_plus/include/epanet_plus.h +9 -0
- epanet_plus-0.0.1.dist-info/METADATA +152 -0
- epanet_plus-0.0.1.dist-info/RECORD +105 -0
- epanet_plus-0.0.1.dist-info/WHEEL +5 -0
- epanet_plus-0.0.1.dist-info/licenses/LICENSE +21 -0
- epanet_plus-0.0.1.dist-info/top_level.txt +11 -0
- examples/basic_usage.py +35 -0
- python-extension/ext.c +344 -0
- python-extension/pyepanet.c +2133 -0
- python-extension/pyepanet.h +143 -0
- python-extension/pyepanet2.c +1823 -0
- python-extension/pyepanet2.h +141 -0
- python-extension/pyepanet_plus.c +37 -0
- python-extension/pyepanet_plus.h +4 -0
- python-extension/pyepanetmsx.c +388 -0
- python-extension/pyepanetmsx.h +35 -0
- tests/test_epanet.py +16 -0
- tests/test_epanetmsx.py +36 -0
- tests/test_epyt.py +114 -0
- tests/test_load_inp_from_buffer.py +18 -0
epanet-src/output.c
ADDED
|
@@ -0,0 +1,853 @@
|
|
|
1
|
+
/*
|
|
2
|
+
******************************************************************************
|
|
3
|
+
Project: OWA EPANET
|
|
4
|
+
Version: 2.3
|
|
5
|
+
Module: output.c
|
|
6
|
+
Description: binary file read/write routines
|
|
7
|
+
Authors: see AUTHORS
|
|
8
|
+
Copyright: see AUTHORS
|
|
9
|
+
License: see LICENSE
|
|
10
|
+
Last Updated: 08/13/2022
|
|
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
|
+
// Local functions
|
|
25
|
+
static int nodeoutput(Project *, int, REAL4 *, double);
|
|
26
|
+
static int linkoutput(Project *, int, REAL4 *, double);
|
|
27
|
+
static int savetimestat(Project *, REAL4 *, HdrType);
|
|
28
|
+
static int savenetreacts(Project *, double, double, double, double);
|
|
29
|
+
static int saveepilog(Project *);
|
|
30
|
+
|
|
31
|
+
// Functions to write/read x[1] to x[n] to/from binary file
|
|
32
|
+
size_t f_save(REAL4 *x, int n, FILE *file)
|
|
33
|
+
{
|
|
34
|
+
return fwrite(x + 1, sizeof(REAL4), n, file);
|
|
35
|
+
}
|
|
36
|
+
size_t f_read(REAL4 *x, int n, FILE *file)
|
|
37
|
+
{
|
|
38
|
+
return fread(x + 1, sizeof(REAL4), n, file);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
int savenetdata(Project *pr)
|
|
42
|
+
/*
|
|
43
|
+
**---------------------------------------------------------------
|
|
44
|
+
** Input: none
|
|
45
|
+
** Output: returns error code
|
|
46
|
+
** Purpose: saves input data in original units to binary
|
|
47
|
+
** output file using fixed-sized (4-byte) records
|
|
48
|
+
**---------------------------------------------------------------
|
|
49
|
+
*/
|
|
50
|
+
{
|
|
51
|
+
Network *net = &pr->network;
|
|
52
|
+
Outfile *out = &pr->outfile;
|
|
53
|
+
Report *rpt = &pr->report;
|
|
54
|
+
Quality *qual = &pr->quality;
|
|
55
|
+
Parser *parser = &pr->parser;
|
|
56
|
+
Times *time = &pr->times;
|
|
57
|
+
|
|
58
|
+
int i, nmax;
|
|
59
|
+
int errcode = 0;
|
|
60
|
+
INT4 *ibuf;
|
|
61
|
+
REAL4 *x;
|
|
62
|
+
Snode *node;
|
|
63
|
+
FILE *outFile = out->OutFile;
|
|
64
|
+
|
|
65
|
+
// Allocate buffer arrays
|
|
66
|
+
nmax = MAX(net->Nnodes, net->Nlinks) + 1;
|
|
67
|
+
nmax = MAX(nmax, 15);
|
|
68
|
+
ibuf = (INT4 *)calloc(nmax, sizeof(INT4));
|
|
69
|
+
x = (REAL4 *)calloc(nmax, sizeof(REAL4));
|
|
70
|
+
ERRCODE(MEMCHECK(ibuf));
|
|
71
|
+
ERRCODE(MEMCHECK(x));
|
|
72
|
+
|
|
73
|
+
// Write prolog section of binary output file
|
|
74
|
+
if (!errcode)
|
|
75
|
+
{
|
|
76
|
+
// Write integer variables to outFile
|
|
77
|
+
ibuf[0] = MAGICNUMBER;
|
|
78
|
+
ibuf[1] = 20012; // keep version at 2.00.12 so that GUI will run
|
|
79
|
+
ibuf[2] = net->Nnodes;
|
|
80
|
+
ibuf[3] = net->Ntanks;
|
|
81
|
+
ibuf[4] = net->Nlinks;
|
|
82
|
+
ibuf[5] = net->Npumps;
|
|
83
|
+
ibuf[6] = net->Nvalves;
|
|
84
|
+
ibuf[7] = qual->Qualflag;
|
|
85
|
+
ibuf[8] = qual->TraceNode;
|
|
86
|
+
ibuf[9] = parser->Flowflag;
|
|
87
|
+
ibuf[10] = parser->Pressflag;
|
|
88
|
+
ibuf[11] = rpt->Tstatflag;
|
|
89
|
+
ibuf[12] = (INT4)time->Rstart;
|
|
90
|
+
ibuf[13] = (INT4)time->Rstep;
|
|
91
|
+
ibuf[14] = (INT4)time->Dur;
|
|
92
|
+
fwrite(ibuf, sizeof(INT4), 15, outFile);
|
|
93
|
+
|
|
94
|
+
// Write string variables to outFile
|
|
95
|
+
fwrite(pr->Title[0], sizeof(char), TITLELEN + 1, outFile);
|
|
96
|
+
fwrite(pr->Title[1], sizeof(char), TITLELEN + 1, outFile);
|
|
97
|
+
fwrite(pr->Title[2], sizeof(char), TITLELEN + 1, outFile);
|
|
98
|
+
fwrite(parser->InpFname, sizeof(char), MAXFNAME + 1, outFile);
|
|
99
|
+
fwrite(rpt->Rpt2Fname, sizeof(char), MAXFNAME + 1, outFile);
|
|
100
|
+
fwrite(qual->ChemName, sizeof(char), MAXID + 1, outFile);
|
|
101
|
+
fwrite(rpt->Field[QUALITY].Units, sizeof(char), MAXID + 1, outFile);
|
|
102
|
+
|
|
103
|
+
// Write node ID information to outFile
|
|
104
|
+
for (i = 1; i <= net->Nnodes; i++)
|
|
105
|
+
{
|
|
106
|
+
node = &net->Node[i];
|
|
107
|
+
fwrite(node->ID, MAXID + 1, 1, outFile);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Write link information to outFile
|
|
111
|
+
// (Note: first transfer values to buffer array,
|
|
112
|
+
// then fwrite buffer array at offset of 1 )
|
|
113
|
+
for (i = 1; i <= net->Nlinks; i++)
|
|
114
|
+
{
|
|
115
|
+
fwrite(net->Link[i].ID, MAXID + 1, 1, outFile);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
for (i = 1; i <= net->Nlinks; i++) ibuf[i] = net->Link[i].N1;
|
|
119
|
+
fwrite(ibuf + 1, sizeof(INT4), net->Nlinks, outFile);
|
|
120
|
+
|
|
121
|
+
for (i = 1; i <= net->Nlinks; i++) ibuf[i] = net->Link[i].N2;
|
|
122
|
+
fwrite(ibuf + 1, sizeof(INT4), net->Nlinks, outFile);
|
|
123
|
+
|
|
124
|
+
for (i = 1; i <= net->Nlinks; i++) ibuf[i] = net->Link[i].Type;
|
|
125
|
+
fwrite(ibuf + 1, sizeof(INT4), net->Nlinks, outFile);
|
|
126
|
+
|
|
127
|
+
// Write tank information to outFile
|
|
128
|
+
for (i = 1; i <= net->Ntanks; i++) ibuf[i] = net->Tank[i].Node;
|
|
129
|
+
fwrite(ibuf + 1, sizeof(INT4), net->Ntanks, outFile);
|
|
130
|
+
|
|
131
|
+
for (i = 1; i <= net->Ntanks; i++) x[i] = (REAL4)net->Tank[i].A;
|
|
132
|
+
f_save(x, net->Ntanks, outFile);
|
|
133
|
+
|
|
134
|
+
// Save node elevations to outFile
|
|
135
|
+
for (i = 1; i <= net->Nnodes; i++)
|
|
136
|
+
{
|
|
137
|
+
x[i] = (REAL4)(net->Node[i].El * pr->Ucf[ELEV]);
|
|
138
|
+
}
|
|
139
|
+
f_save(x, net->Nnodes, outFile);
|
|
140
|
+
|
|
141
|
+
// Save link lengths & diameters to outFile
|
|
142
|
+
for (i = 1; i <= net->Nlinks; i++)
|
|
143
|
+
{
|
|
144
|
+
x[i] = (REAL4)(net->Link[i].Len * pr->Ucf[ELEV]);
|
|
145
|
+
}
|
|
146
|
+
f_save(x, net->Nlinks, outFile);
|
|
147
|
+
|
|
148
|
+
for (i = 1; i <= net->Nlinks; i++)
|
|
149
|
+
{
|
|
150
|
+
if (net->Link[i].Type != PUMP)
|
|
151
|
+
{
|
|
152
|
+
x[i] = (REAL4)(net->Link[i].Diam * pr->Ucf[DIAM]);
|
|
153
|
+
}
|
|
154
|
+
else x[i] = 0.0f;
|
|
155
|
+
}
|
|
156
|
+
if (f_save(x, net->Nlinks, outFile) < (unsigned)net->Nlinks) errcode = 308;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Free memory used for buffer arrays
|
|
160
|
+
free(ibuf);
|
|
161
|
+
free(x);
|
|
162
|
+
return errcode;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
int savehyd(Project *pr, long *htime)
|
|
166
|
+
/*
|
|
167
|
+
**--------------------------------------------------------------
|
|
168
|
+
** Input: *htime = current time
|
|
169
|
+
** Output: returns error code
|
|
170
|
+
** Purpose: saves current hydraulic solution to file HydFile
|
|
171
|
+
** in binary format
|
|
172
|
+
**--------------------------------------------------------------
|
|
173
|
+
*/
|
|
174
|
+
{
|
|
175
|
+
Network *net = &pr->network;
|
|
176
|
+
Outfile *out = &pr->outfile;
|
|
177
|
+
Hydraul *hyd = &pr->hydraul;
|
|
178
|
+
|
|
179
|
+
int i;
|
|
180
|
+
INT4 t;
|
|
181
|
+
int errcode = 0;
|
|
182
|
+
REAL4 *x;
|
|
183
|
+
FILE *HydFile = out->HydFile;
|
|
184
|
+
|
|
185
|
+
x = (REAL4 *)calloc(MAX(net->Nnodes, net->Nlinks) + 1, sizeof(REAL4));
|
|
186
|
+
if (x == NULL) return 101;
|
|
187
|
+
|
|
188
|
+
// Save current time (htime)
|
|
189
|
+
t = (INT4)(*htime);
|
|
190
|
+
fwrite(&t, sizeof(INT4), 1, HydFile);
|
|
191
|
+
|
|
192
|
+
// Save current nodal demands (D)
|
|
193
|
+
for (i = 1; i <= net->Nnodes; i++) x[i] = (REAL4)hyd->NodeDemand[i];
|
|
194
|
+
fwrite(x + 1, sizeof(REAL4), net->Nnodes, HydFile);
|
|
195
|
+
//f_save(x, net->Nnodes, HydFile);
|
|
196
|
+
|
|
197
|
+
// Save current nodal heads
|
|
198
|
+
for (i = 1; i <= net->Nnodes; i++) x[i] = (REAL4)hyd->NodeHead[i];
|
|
199
|
+
fwrite(x + 1, sizeof(REAL4), net->Nnodes, HydFile);
|
|
200
|
+
//f_save(x, net->Nnodes, HydFile);
|
|
201
|
+
|
|
202
|
+
// Force flow in closed links to be zero then save flows
|
|
203
|
+
for (i = 1; i <= net->Nlinks; i++)
|
|
204
|
+
{
|
|
205
|
+
if (hyd->LinkStatus[i] <= CLOSED) x[i] = 0.0f;
|
|
206
|
+
else x[i] = (REAL4)hyd->LinkFlow[i];
|
|
207
|
+
}
|
|
208
|
+
fwrite(x + 1, sizeof(REAL4), net->Nlinks, HydFile);
|
|
209
|
+
//f_save(x, net->Nlinks, HydFile);
|
|
210
|
+
|
|
211
|
+
// Save link status
|
|
212
|
+
for (i = 1; i <= net->Nlinks; i++) x[i] = (REAL4)hyd->LinkStatus[i];
|
|
213
|
+
fwrite(x + 1, sizeof(REAL4), net->Nlinks, HydFile);
|
|
214
|
+
//f_save(x, net->Nlinks, HydFile);
|
|
215
|
+
|
|
216
|
+
// Save link settings & check for successful write-to-disk
|
|
217
|
+
// (We assume that if any of the previous fwrites failed,
|
|
218
|
+
// then this one will also fail.)
|
|
219
|
+
for (i = 1; i <= net->Nlinks; i++) x[i] = (REAL4)hyd->LinkSetting[i];
|
|
220
|
+
if (fwrite(x + 1, sizeof(REAL4), net->Nlinks, HydFile) <
|
|
221
|
+
(unsigned)net->Nlinks
|
|
222
|
+
) errcode = 308;
|
|
223
|
+
//if (f_save(x, net->Nlinks, HydFile) < (unsigned)net->Nlinks) errcode = 308;
|
|
224
|
+
free(x);
|
|
225
|
+
fflush(HydFile);
|
|
226
|
+
return errcode;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
int savehydstep(Project *pr, long *hydstep)
|
|
230
|
+
/*
|
|
231
|
+
**--------------------------------------------------------------
|
|
232
|
+
** Input: *hydstep = next time step
|
|
233
|
+
** Output: returns error code
|
|
234
|
+
** Purpose: saves next hydraulic timestep to file HydFile
|
|
235
|
+
** in binary format
|
|
236
|
+
**--------------------------------------------------------------
|
|
237
|
+
*/
|
|
238
|
+
{
|
|
239
|
+
Outfile *out = &pr->outfile;
|
|
240
|
+
|
|
241
|
+
INT4 t;
|
|
242
|
+
int errcode = 0;
|
|
243
|
+
|
|
244
|
+
t = (INT4)(*hydstep);
|
|
245
|
+
if (fwrite(&t, sizeof(INT4), 1, out->HydFile) < 1) errcode = 308;
|
|
246
|
+
if (t == 0) fputc(EOFMARK, out->HydFile);
|
|
247
|
+
fflush(out->HydFile);
|
|
248
|
+
return errcode;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
int saveenergy(Project *pr)
|
|
252
|
+
/*
|
|
253
|
+
**--------------------------------------------------------------
|
|
254
|
+
** Input: none
|
|
255
|
+
** Output: returns error code
|
|
256
|
+
** Purpose: saves energy usage by each pump to outFile
|
|
257
|
+
** in binary format
|
|
258
|
+
**--------------------------------------------------------------
|
|
259
|
+
*/
|
|
260
|
+
{
|
|
261
|
+
Network *net = &pr->network;
|
|
262
|
+
Hydraul *hyd = &pr->hydraul;
|
|
263
|
+
Outfile *out = &pr->outfile;
|
|
264
|
+
Parser *parser = &pr->parser;
|
|
265
|
+
Times *time = &pr->times;
|
|
266
|
+
|
|
267
|
+
int i;
|
|
268
|
+
INT4 index;
|
|
269
|
+
REAL4 x[6]; // work array
|
|
270
|
+
double hdur, // total simulation duration in hours
|
|
271
|
+
t; // total pumping time duration
|
|
272
|
+
Spump *pump;
|
|
273
|
+
FILE *outFile = out->OutFile;
|
|
274
|
+
|
|
275
|
+
hdur = time->Dur / 3600.0;
|
|
276
|
+
for (i = 1; i <= net->Npumps; i++)
|
|
277
|
+
{
|
|
278
|
+
pump = &net->Pump[i];
|
|
279
|
+
if (hdur == 0.0) pump->Energy.TotalCost *= 24.0;
|
|
280
|
+
else
|
|
281
|
+
{
|
|
282
|
+
// ... convert total hrs. online to fraction of total time online
|
|
283
|
+
t = pump->Energy.TimeOnLine; //currently holds total hrs. online
|
|
284
|
+
pump->Energy.TimeOnLine = t / hdur;
|
|
285
|
+
|
|
286
|
+
// ... convert cumulative values to time-averaged ones
|
|
287
|
+
if (t > 0.0)
|
|
288
|
+
{
|
|
289
|
+
pump->Energy.Efficiency /= t;
|
|
290
|
+
pump->Energy.KwHrsPerFlow /= t;
|
|
291
|
+
pump->Energy.KwHrs /= t;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// ... convert total cost to cost per day
|
|
295
|
+
pump->Energy.TotalCost *= 24.0 / hdur;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// ... express time online and avg. efficiency as percentages
|
|
299
|
+
pump->Energy.TimeOnLine *= 100.0;
|
|
300
|
+
pump->Energy.Efficiency *= 100.0;
|
|
301
|
+
|
|
302
|
+
// ... compute KWH per Million Gallons or per Cubic Meter
|
|
303
|
+
if (parser->Unitsflag == SI)
|
|
304
|
+
{
|
|
305
|
+
pump->Energy.KwHrsPerFlow *= (1000. / LPSperCFS / 3600.);
|
|
306
|
+
}
|
|
307
|
+
else pump->Energy.KwHrsPerFlow *= (1.0e6 / GPMperCFS / 60.);
|
|
308
|
+
|
|
309
|
+
// ... save energy stats to REAL4 work array
|
|
310
|
+
x[0] = (REAL4)pump->Energy.TimeOnLine;
|
|
311
|
+
x[1] = (REAL4)pump->Energy.Efficiency;
|
|
312
|
+
x[2] = (REAL4)pump->Energy.KwHrsPerFlow;
|
|
313
|
+
x[3] = (REAL4)pump->Energy.KwHrs;
|
|
314
|
+
x[4] = (REAL4)pump->Energy.MaxKwatts;
|
|
315
|
+
x[5] = (REAL4)pump->Energy.TotalCost;
|
|
316
|
+
|
|
317
|
+
// ... save energy results to output file
|
|
318
|
+
index = pump->Link;
|
|
319
|
+
if (fwrite(&index, sizeof(INT4), 1, outFile) < 1) return 308;
|
|
320
|
+
if (fwrite(x, sizeof(REAL4), 6, outFile) < 6) return 308;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// ... compute and save demand charge
|
|
324
|
+
hyd->Emax = hyd->Emax * hyd->Dcost;
|
|
325
|
+
x[0] = (REAL4)hyd->Emax;
|
|
326
|
+
if (fwrite(&x[0], sizeof(REAL4), 1, outFile) < 1) return 308;
|
|
327
|
+
return (0);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
int readhyd(Project *pr, long *hydtime)
|
|
331
|
+
/*
|
|
332
|
+
**--------------------------------------------------------------
|
|
333
|
+
** Input: none
|
|
334
|
+
** Output: *hydtime = time of hydraulic solution
|
|
335
|
+
** Returns: 1 if successful, 0 if not
|
|
336
|
+
** Purpose: reads hydraulic solution from file HydFile
|
|
337
|
+
**
|
|
338
|
+
** NOTE: A hydraulic solution consists of the current time
|
|
339
|
+
** (hydtime), nodal demands (D) and heads (H), link
|
|
340
|
+
** flows (Q), link status (S), and link settings (K).
|
|
341
|
+
**--------------------------------------------------------------
|
|
342
|
+
*/
|
|
343
|
+
{
|
|
344
|
+
Network *net = &pr->network;
|
|
345
|
+
Hydraul *hyd = &pr->hydraul;
|
|
346
|
+
Outfile *out = &pr->outfile;
|
|
347
|
+
|
|
348
|
+
int i;
|
|
349
|
+
INT4 t;
|
|
350
|
+
int result = 1;
|
|
351
|
+
REAL4 *x;
|
|
352
|
+
FILE *HydFile = out->HydFile;
|
|
353
|
+
|
|
354
|
+
x = (REAL4 *)calloc(MAX(net->Nnodes, net->Nlinks) + 1, sizeof(REAL4));
|
|
355
|
+
if (x == NULL) return 0;
|
|
356
|
+
|
|
357
|
+
if (fread(&t, sizeof(INT4), 1, HydFile) < 1) result = 0;
|
|
358
|
+
*hydtime = t;
|
|
359
|
+
|
|
360
|
+
if (f_read(x, net->Nnodes, HydFile) < (unsigned)net->Nnodes) result = 0;
|
|
361
|
+
else for (i = 1; i <= net->Nnodes; i++) hyd->NodeDemand[i] = x[i];
|
|
362
|
+
|
|
363
|
+
if (f_read(x, net->Nnodes, HydFile) < (unsigned)net->Nnodes) result = 0;
|
|
364
|
+
else for (i = 1; i <= net->Nnodes; i++) hyd->NodeHead[i] = x[i];
|
|
365
|
+
|
|
366
|
+
if (f_read(x, net->Nlinks, HydFile) < (unsigned)net->Nlinks) result = 0;
|
|
367
|
+
else for (i = 1; i <= net->Nlinks; i++) hyd->LinkFlow[i] = x[i];
|
|
368
|
+
|
|
369
|
+
if (f_read(x, net->Nlinks, HydFile) < (unsigned)net->Nlinks) result = 0;
|
|
370
|
+
else for (i = 1; i <= net->Nlinks; i++) hyd->LinkStatus[i] = (char)x[i];
|
|
371
|
+
|
|
372
|
+
if (f_read(x, net->Nlinks, HydFile) < (unsigned)net->Nlinks) result = 0;
|
|
373
|
+
else for (i = 1; i <= net->Nlinks; i++) hyd->LinkSetting[i] = x[i];
|
|
374
|
+
|
|
375
|
+
free(x);
|
|
376
|
+
return result;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
int readhydstep(Project *pr, long *hydstep)
|
|
380
|
+
/*
|
|
381
|
+
**--------------------------------------------------------------
|
|
382
|
+
** Input: none
|
|
383
|
+
** Output: *hydstep = next hydraulic time step (sec)
|
|
384
|
+
** Returns: 1 if successful, 0 if not
|
|
385
|
+
** Purpose: reads hydraulic time step from file HydFile
|
|
386
|
+
**--------------------------------------------------------------
|
|
387
|
+
*/
|
|
388
|
+
{
|
|
389
|
+
FILE *hydFile = pr->outfile.HydFile;
|
|
390
|
+
INT4 t;
|
|
391
|
+
|
|
392
|
+
if (fread(&t, sizeof(INT4), 1, hydFile) < 1) return 0;
|
|
393
|
+
*hydstep = t;
|
|
394
|
+
return 1;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
int saveoutput(Project *pr)
|
|
398
|
+
/*
|
|
399
|
+
**--------------------------------------------------------------
|
|
400
|
+
** Input: none
|
|
401
|
+
** Output: returns error code
|
|
402
|
+
** Purpose: writes simulation results to output file
|
|
403
|
+
**--------------------------------------------------------------
|
|
404
|
+
*/
|
|
405
|
+
{
|
|
406
|
+
Network *net = &pr->network;
|
|
407
|
+
|
|
408
|
+
int j;
|
|
409
|
+
int errcode = 0;
|
|
410
|
+
REAL4 *x;
|
|
411
|
+
|
|
412
|
+
x = (REAL4 *)calloc(MAX(net->Nnodes, net->Nlinks) + 1, sizeof(REAL4));
|
|
413
|
+
if (x == NULL) return 101;
|
|
414
|
+
|
|
415
|
+
// Write out node results, then link results
|
|
416
|
+
for (j = DEMAND; j <= QUALITY; j++) ERRCODE(nodeoutput(pr, j, x, pr->Ucf[j]));
|
|
417
|
+
for (j = FLOW; j <= FRICTION; j++) ERRCODE(linkoutput(pr, j, x, pr->Ucf[j]));
|
|
418
|
+
free(x);
|
|
419
|
+
return errcode;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
int nodeoutput(Project *pr, int j, REAL4 *x, double ucf)
|
|
423
|
+
/*
|
|
424
|
+
**--------------------------------------------------------------
|
|
425
|
+
** Input: j = type of node variable
|
|
426
|
+
** *x = buffer for node values
|
|
427
|
+
** ucf = units conversion factor
|
|
428
|
+
** Output: returns error code
|
|
429
|
+
** Purpose: writes results for node variable j to output file
|
|
430
|
+
**-----------------------------------------------------------------
|
|
431
|
+
*/
|
|
432
|
+
{
|
|
433
|
+
Network *net = &pr->network;
|
|
434
|
+
Hydraul *hyd = &pr->hydraul;
|
|
435
|
+
Quality *qual = &pr->quality;
|
|
436
|
+
Outfile *out = &pr->outfile;
|
|
437
|
+
|
|
438
|
+
int i;
|
|
439
|
+
FILE *outFile = out->TmpOutFile;
|
|
440
|
+
|
|
441
|
+
// Load computed results (in proper units) into buffer x
|
|
442
|
+
switch (j)
|
|
443
|
+
{
|
|
444
|
+
case DEMAND:
|
|
445
|
+
for (i = 1; i <= net->Nnodes; i++)
|
|
446
|
+
{
|
|
447
|
+
x[i] = (REAL4)(hyd->NodeDemand[i] * ucf);
|
|
448
|
+
}
|
|
449
|
+
break;
|
|
450
|
+
|
|
451
|
+
case HEAD:
|
|
452
|
+
for (i = 1; i <= net->Nnodes; i++)
|
|
453
|
+
{
|
|
454
|
+
x[i] = (REAL4)(hyd->NodeHead[i] * ucf);
|
|
455
|
+
}
|
|
456
|
+
break;
|
|
457
|
+
|
|
458
|
+
case PRESSURE:
|
|
459
|
+
for (i = 1; i <= net->Nnodes; i++)
|
|
460
|
+
{
|
|
461
|
+
x[i] = (REAL4)((hyd->NodeHead[i] - net->Node[i].El) * ucf);
|
|
462
|
+
}
|
|
463
|
+
break;
|
|
464
|
+
|
|
465
|
+
case QUALITY:
|
|
466
|
+
for (i = 1; i <= net->Nnodes; i++)
|
|
467
|
+
{
|
|
468
|
+
x[i] = (REAL4)(qual->NodeQual[i] * ucf);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// Write x[1] to x[net->Nnodes] to output file
|
|
473
|
+
if (f_save(x, net->Nnodes, outFile) < (unsigned)net->Nnodes) return 308;
|
|
474
|
+
return 0;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
int linkoutput(Project *pr, int j, REAL4 *x, double ucf)
|
|
478
|
+
/*
|
|
479
|
+
**----------------------------------------------------------------
|
|
480
|
+
** Input: j = type of link variable
|
|
481
|
+
** *x = buffer for link values
|
|
482
|
+
** ucf = units conversion factor
|
|
483
|
+
** Output: returns error code
|
|
484
|
+
** Purpose: writes results for link variable j to output file
|
|
485
|
+
**----------------------------------------------------------------
|
|
486
|
+
*/
|
|
487
|
+
{
|
|
488
|
+
Network *net = &pr->network;
|
|
489
|
+
Hydraul *hyd = &pr->hydraul;
|
|
490
|
+
Quality *qual = &pr->quality;
|
|
491
|
+
Outfile *out = &pr->outfile;
|
|
492
|
+
|
|
493
|
+
int i;
|
|
494
|
+
double a, h, q, f, setting;
|
|
495
|
+
FILE *outFile = out->TmpOutFile;
|
|
496
|
+
|
|
497
|
+
// Load computed results (in proper units) into buffer x
|
|
498
|
+
switch (j)
|
|
499
|
+
{
|
|
500
|
+
case FLOW:
|
|
501
|
+
for (i = 1; i <= net->Nlinks; i++)
|
|
502
|
+
{
|
|
503
|
+
x[i] = (REAL4)(hyd->LinkFlow[i] * ucf);
|
|
504
|
+
}
|
|
505
|
+
break;
|
|
506
|
+
|
|
507
|
+
case VELOCITY:
|
|
508
|
+
for (i = 1; i <= net->Nlinks; i++)
|
|
509
|
+
{
|
|
510
|
+
if (net->Link[i].Type == PUMP) x[i] = 0.0f;
|
|
511
|
+
else
|
|
512
|
+
{
|
|
513
|
+
q = ABS(hyd->LinkFlow[i]);
|
|
514
|
+
a = PI * SQR(net->Link[i].Diam) / 4.0;
|
|
515
|
+
x[i] = (REAL4)(q / a * ucf);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
break;
|
|
519
|
+
|
|
520
|
+
case HEADLOSS:
|
|
521
|
+
for (i = 1; i <= net->Nlinks; i++)
|
|
522
|
+
{
|
|
523
|
+
if (hyd->LinkStatus[i] <= CLOSED) x[i] = 0.0f;
|
|
524
|
+
else
|
|
525
|
+
{
|
|
526
|
+
h = hyd->NodeHead[net->Link[i].N1] -
|
|
527
|
+
hyd->NodeHead[net->Link[i].N2];
|
|
528
|
+
if (net->Link[i].Type != PUMP) h = ABS(h);
|
|
529
|
+
if (net->Link[i].Type <= PIPE)
|
|
530
|
+
{
|
|
531
|
+
x[i] = (REAL4)(1000.0 * h / net->Link[i].Len);
|
|
532
|
+
}
|
|
533
|
+
else x[i] = (REAL4)(h * ucf);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
break;
|
|
537
|
+
|
|
538
|
+
case LINKQUAL:
|
|
539
|
+
for (i = 1; i <= net->Nlinks; i++)
|
|
540
|
+
{
|
|
541
|
+
x[i] = (REAL4)(avgqual(pr,i) * ucf);
|
|
542
|
+
}
|
|
543
|
+
break;
|
|
544
|
+
|
|
545
|
+
case STATUS:
|
|
546
|
+
for (i = 1; i <= net->Nlinks; i++)
|
|
547
|
+
{
|
|
548
|
+
x[i] = (REAL4)hyd->LinkStatus[i];
|
|
549
|
+
}
|
|
550
|
+
break;
|
|
551
|
+
|
|
552
|
+
case SETTING:
|
|
553
|
+
for (i = 1; i <= net->Nlinks; i++)
|
|
554
|
+
{
|
|
555
|
+
setting = hyd->LinkSetting[i];
|
|
556
|
+
if (setting != MISSING) switch (net->Link[i].Type)
|
|
557
|
+
{
|
|
558
|
+
case CVPIPE:
|
|
559
|
+
case PIPE:
|
|
560
|
+
x[i] = (REAL4)setting; break;
|
|
561
|
+
case PUMP:
|
|
562
|
+
x[i] = (REAL4)setting; break;
|
|
563
|
+
case PRV:
|
|
564
|
+
case PSV:
|
|
565
|
+
case PBV:
|
|
566
|
+
x[i] = (REAL4)(setting * pr->Ucf[PRESSURE]); break;
|
|
567
|
+
case FCV:
|
|
568
|
+
x[i] = (REAL4)(setting * pr->Ucf[FLOW]); break;
|
|
569
|
+
case TCV:
|
|
570
|
+
case PCV:
|
|
571
|
+
x[i] = (REAL4)setting; break;
|
|
572
|
+
default: x[i] = 0.0f;
|
|
573
|
+
}
|
|
574
|
+
else x[i] = 0.0f;
|
|
575
|
+
}
|
|
576
|
+
break;
|
|
577
|
+
|
|
578
|
+
case REACTRATE: // Overall reaction rate in mass/L/day
|
|
579
|
+
if (qual->Qualflag == NONE)
|
|
580
|
+
{
|
|
581
|
+
memset(x, 0, (net->Nlinks + 1) * sizeof(REAL4));
|
|
582
|
+
}
|
|
583
|
+
else for (i = 1; i <= net->Nlinks; i++)
|
|
584
|
+
{
|
|
585
|
+
x[i] = (REAL4)(qual->PipeRateCoeff[i] * ucf);
|
|
586
|
+
}
|
|
587
|
+
break;
|
|
588
|
+
|
|
589
|
+
case FRICTION: // Friction factor
|
|
590
|
+
// f = 2ghd/(Lu^2) where f = friction factor
|
|
591
|
+
// u = velocity, g = grav. accel., h = head
|
|
592
|
+
// loss, d = diam., & L = pipe length
|
|
593
|
+
for (i = 1; i <= net->Nlinks; i++)
|
|
594
|
+
{
|
|
595
|
+
if (net->Link[i].Type <= PIPE && ABS(hyd->LinkFlow[i]) > TINY)
|
|
596
|
+
{
|
|
597
|
+
h = ABS(hyd->NodeHead[net->Link[i].N1] -
|
|
598
|
+
hyd->NodeHead[net->Link[i].N2]);
|
|
599
|
+
f = 39.725 * h * pow(net->Link[i].Diam, 5) /
|
|
600
|
+
net->Link[i].Len / SQR(hyd->LinkFlow[i]);
|
|
601
|
+
x[i] = (REAL4)f;
|
|
602
|
+
}
|
|
603
|
+
else x[i] = 0.0f;
|
|
604
|
+
}
|
|
605
|
+
break;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
// Write x[1] to x[net->Nlinks] to output file
|
|
609
|
+
if (f_save(x, net->Nlinks, outFile) < (unsigned)net->Nlinks) return 308;
|
|
610
|
+
return 0;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
int savefinaloutput(Project *pr)
|
|
614
|
+
/*
|
|
615
|
+
**--------------------------------------------------------------
|
|
616
|
+
** Input: none
|
|
617
|
+
** Output: returns error code
|
|
618
|
+
** Purpose: saves time series statistics, reaction rates &
|
|
619
|
+
** epilog to output file.
|
|
620
|
+
**--------------------------------------------------------------
|
|
621
|
+
*/
|
|
622
|
+
{
|
|
623
|
+
Network *net = &pr->network;
|
|
624
|
+
Outfile *out = &pr->outfile;
|
|
625
|
+
Report *rpt = &pr->report;
|
|
626
|
+
Quality *qual = &pr->quality;
|
|
627
|
+
|
|
628
|
+
int errcode = 0;
|
|
629
|
+
REAL4 *x;
|
|
630
|
+
FILE *outFile = out->OutFile;
|
|
631
|
+
|
|
632
|
+
// Save time series statistic if computed
|
|
633
|
+
if (rpt->Tstatflag != SERIES && out->TmpOutFile != NULL)
|
|
634
|
+
{
|
|
635
|
+
x = (REAL4 *)calloc(MAX(net->Nnodes, net->Nlinks) + 1, sizeof(REAL4));
|
|
636
|
+
if (x == NULL) return 101;
|
|
637
|
+
ERRCODE(savetimestat(pr, x, NODEHDR));
|
|
638
|
+
ERRCODE(savetimestat(pr, x, LINKHDR));
|
|
639
|
+
if (!errcode) rpt->Nperiods = 1;
|
|
640
|
+
fclose(out->TmpOutFile);
|
|
641
|
+
out->TmpOutFile = NULL;
|
|
642
|
+
free(x);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
// Save avg. reaction rates & file epilog
|
|
646
|
+
if (outFile != NULL)
|
|
647
|
+
{
|
|
648
|
+
ERRCODE(savenetreacts(pr, qual->Wbulk, qual->Wwall, qual->Wtank,
|
|
649
|
+
qual->Wsource));
|
|
650
|
+
ERRCODE(saveepilog(pr));
|
|
651
|
+
}
|
|
652
|
+
return errcode;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
int savetimestat(Project *pr, REAL4 *x, HdrType objtype)
|
|
656
|
+
/*
|
|
657
|
+
**--------------------------------------------------------------
|
|
658
|
+
** Input: *x = buffer for node values
|
|
659
|
+
** objtype = NODEHDR (for nodes) or LINKHDR (for links)
|
|
660
|
+
** Output: returns error code
|
|
661
|
+
** Purpose: computes time series statistic for nodes or links
|
|
662
|
+
** and saves to normal output file.
|
|
663
|
+
**
|
|
664
|
+
** NOTE: This routine is dependent on how the output reporting
|
|
665
|
+
** variables were assigned to FieldType in TYPES.H.
|
|
666
|
+
**--------------------------------------------------------------
|
|
667
|
+
*/
|
|
668
|
+
{
|
|
669
|
+
Network *net = &pr->network;
|
|
670
|
+
Hydraul *hyd = &pr->hydraul;
|
|
671
|
+
Quality *qual = &pr->quality;
|
|
672
|
+
Outfile *out = &pr->outfile;
|
|
673
|
+
Report *rpt = &pr->report;
|
|
674
|
+
|
|
675
|
+
int n, n1, n2;
|
|
676
|
+
int i, j, p, errcode = 0;
|
|
677
|
+
long startbyte, skipbytes;
|
|
678
|
+
float *stat1, *stat2, xx;
|
|
679
|
+
FILE *outFile = out->OutFile;
|
|
680
|
+
|
|
681
|
+
// Compute number of bytes in temp output file to skip over (skipbytes)
|
|
682
|
+
// when moving from one time period to the next for a particular variable
|
|
683
|
+
if (objtype == NODEHDR)
|
|
684
|
+
{
|
|
685
|
+
// For nodes, we start at 0 and skip over node output for all
|
|
686
|
+
// node variables minus 1 plus link output for all link variables.
|
|
687
|
+
startbyte = 0;
|
|
688
|
+
skipbytes = (net->Nnodes * (QUALITY - DEMAND) +
|
|
689
|
+
net->Nlinks * (FRICTION - FLOW + 1)) * sizeof(REAL4);
|
|
690
|
+
n = net->Nnodes;
|
|
691
|
+
n1 = DEMAND;
|
|
692
|
+
n2 = QUALITY;
|
|
693
|
+
}
|
|
694
|
+
else
|
|
695
|
+
{
|
|
696
|
+
// For links, we start at the end of all node variables and skip
|
|
697
|
+
// over node output for all node variables plus link output for
|
|
698
|
+
// all link variables minus 1
|
|
699
|
+
startbyte = net->Nnodes * (QUALITY - DEMAND + 1) * sizeof(REAL4);
|
|
700
|
+
skipbytes = (net->Nnodes * (QUALITY - DEMAND + 1) +
|
|
701
|
+
net->Nlinks * (FRICTION - FLOW)) * sizeof(REAL4);
|
|
702
|
+
n = net->Nlinks;
|
|
703
|
+
n1 = FLOW;
|
|
704
|
+
n2 = FRICTION;
|
|
705
|
+
}
|
|
706
|
+
stat1 = (float *)calloc(n + 1, sizeof(float));
|
|
707
|
+
stat2 = (float *)calloc(n + 1, sizeof(float));
|
|
708
|
+
ERRCODE(MEMCHECK(stat1));
|
|
709
|
+
ERRCODE(MEMCHECK(stat2));
|
|
710
|
+
|
|
711
|
+
// Process each output reporting variable
|
|
712
|
+
if (!errcode) for (j = n1; j <= n2; j++)
|
|
713
|
+
{
|
|
714
|
+
// Initialize stat arrays
|
|
715
|
+
if (rpt->Tstatflag == AVG) memset(stat1, 0, (n + 1) * sizeof(float));
|
|
716
|
+
else for (i = 1; i <= n; i++)
|
|
717
|
+
{
|
|
718
|
+
stat1[i] = -MISSING;
|
|
719
|
+
stat2[i] = MISSING;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
// Position temp output file at start of output
|
|
723
|
+
fseek(out->TmpOutFile, startbyte + (j - n1) * n * sizeof(REAL4),
|
|
724
|
+
SEEK_SET);
|
|
725
|
+
|
|
726
|
+
// Process each time period
|
|
727
|
+
for (p = 1; p <= rpt->Nperiods; p++)
|
|
728
|
+
{
|
|
729
|
+
// Get output results for time period & update stats
|
|
730
|
+
f_read(x, n, out->TmpOutFile);
|
|
731
|
+
for (i = 1; i <= n; i++)
|
|
732
|
+
{
|
|
733
|
+
xx = x[i];
|
|
734
|
+
if (objtype == LINKHDR)
|
|
735
|
+
{
|
|
736
|
+
if (j == FLOW) xx = ABS(xx);
|
|
737
|
+
if (j == STATUS)
|
|
738
|
+
{
|
|
739
|
+
if (xx >= OPEN) xx = 1.0;
|
|
740
|
+
else xx = 0.0;
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
if (rpt->Tstatflag == AVG) stat1[i] += xx;
|
|
744
|
+
else
|
|
745
|
+
{
|
|
746
|
+
stat1[i] = MIN(stat1[i], xx);
|
|
747
|
+
stat2[i] = MAX(stat2[i], xx);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
// Advance file to next period
|
|
752
|
+
if (p < rpt->Nperiods) fseek(out->TmpOutFile, skipbytes, SEEK_CUR);
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// Compute resultant stat & save to regular output file
|
|
756
|
+
switch (rpt->Tstatflag)
|
|
757
|
+
{
|
|
758
|
+
case AVG:
|
|
759
|
+
for (i = 1; i <= n; i++) x[i] = stat1[i] / (float)rpt->Nperiods;
|
|
760
|
+
break;
|
|
761
|
+
case MIN:
|
|
762
|
+
for (i = 1; i <= n; i++) x[i] = stat1[i];
|
|
763
|
+
break;
|
|
764
|
+
case MAX:
|
|
765
|
+
for (i = 1; i <= n; i++) x[i] = stat2[i];
|
|
766
|
+
break;
|
|
767
|
+
case RANGE:
|
|
768
|
+
for (i = 1; i <= n; i++) x[i] = stat2[i] - stat1[i];
|
|
769
|
+
break;
|
|
770
|
+
}
|
|
771
|
+
if (objtype == LINKHDR && j == STATUS)
|
|
772
|
+
{
|
|
773
|
+
for (i = 1; i <= n; i++)
|
|
774
|
+
{
|
|
775
|
+
if (x[i] < 0.5f) x[i] = CLOSED;
|
|
776
|
+
else x[i] = OPEN;
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
if (f_save(x, n, outFile) < (unsigned)n) errcode = 308;
|
|
780
|
+
|
|
781
|
+
// Update internal output variables where applicable
|
|
782
|
+
if (objtype == NODEHDR) switch (j)
|
|
783
|
+
{
|
|
784
|
+
case DEMAND:
|
|
785
|
+
for (i = 1; i <= n; i++) hyd->NodeDemand[i] = x[i] / pr->Ucf[DEMAND];
|
|
786
|
+
break;
|
|
787
|
+
case HEAD:
|
|
788
|
+
for (i = 1; i <= n; i++) hyd->NodeHead[i] = x[i] / pr->Ucf[HEAD];
|
|
789
|
+
break;
|
|
790
|
+
case QUALITY:
|
|
791
|
+
for (i = 1; i <= n; i++) qual->NodeQual[i] = x[i] / pr->Ucf[QUALITY];
|
|
792
|
+
break;
|
|
793
|
+
}
|
|
794
|
+
else if (j == FLOW)
|
|
795
|
+
{
|
|
796
|
+
for (i = 1; i <= n; i++) hyd->LinkFlow[i] = x[i] / pr->Ucf[FLOW];
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
// Free allocated memory
|
|
801
|
+
free(stat1);
|
|
802
|
+
free(stat2);
|
|
803
|
+
return errcode;
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
int savenetreacts(Project *pr, double wbulk, double wwall, double wtank, double wsource)
|
|
807
|
+
/*
|
|
808
|
+
**-----------------------------------------------------
|
|
809
|
+
** Writes average network-wide reaction rates (in
|
|
810
|
+
** mass/hr) to binary output file.
|
|
811
|
+
**-----------------------------------------------------
|
|
812
|
+
*/
|
|
813
|
+
{
|
|
814
|
+
Outfile *out = &pr->outfile;
|
|
815
|
+
Times *time = &pr->times;
|
|
816
|
+
|
|
817
|
+
int errcode = 0;
|
|
818
|
+
double t;
|
|
819
|
+
REAL4 w[4];
|
|
820
|
+
FILE *outFile = out->OutFile;
|
|
821
|
+
|
|
822
|
+
if (time->Dur > 0) t = (double)time->Dur / 3600.;
|
|
823
|
+
else t = 1.;
|
|
824
|
+
w[0] = (REAL4)(wbulk / t);
|
|
825
|
+
w[1] = (REAL4)(wwall / t);
|
|
826
|
+
w[2] = (REAL4)(wtank / t);
|
|
827
|
+
w[3] = (REAL4)(wsource / t);
|
|
828
|
+
if (fwrite(w, sizeof(REAL4), 4, outFile) < 4) errcode = 308;
|
|
829
|
+
return errcode;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
int saveepilog(Project *pr)
|
|
833
|
+
/*
|
|
834
|
+
**-------------------------------------------------
|
|
835
|
+
** Writes Nperiods, Warnflag, & Magic Number to
|
|
836
|
+
** end of binary output file.
|
|
837
|
+
**-------------------------------------------------
|
|
838
|
+
*/
|
|
839
|
+
{
|
|
840
|
+
Outfile *out = &pr->outfile;
|
|
841
|
+
Report *rpt = &pr->report;
|
|
842
|
+
|
|
843
|
+
int errcode = 0;
|
|
844
|
+
INT4 i;
|
|
845
|
+
FILE *outFile = out->OutFile;
|
|
846
|
+
|
|
847
|
+
i = rpt->Nperiods;
|
|
848
|
+
if (fwrite(&i, sizeof(INT4), 1, outFile) < 1) errcode = 308;
|
|
849
|
+
i = pr->Warnflag;
|
|
850
|
+
if (fwrite(&i, sizeof(INT4), 1, outFile) < 1) errcode = 308;
|
|
851
|
+
i = MAGICNUMBER; if (fwrite(&i, sizeof(INT4), 1, outFile) < 1) errcode = 308;
|
|
852
|
+
return errcode;
|
|
853
|
+
}
|