lixiaojun
2025-03-10 939bbd43d708ccec94c3ee97e6a03e58bfae9bbe
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
/** @page ToolkitExamples Examples
Here are several examples of how the Toolkit can be used for different types of network analyses.
 
- @subpage Example1 "Embedded Engine Example"
- @subpage Example2 "Network Building Example"
- @subpage Example3 "Hydrant Rating Curve Example"
- @subpage Example4 "Chlorine Dosage Example"
 
*/
 
/** @page Example1 Embedded Engine Example
This example shows how simple it is for the Toolkit to provide a network analysis engine for other applications. There are three steps that the application would need to take:
-# Have the application write network data to an EPANET-formatted input file.
 
-# Create a project and call @ref EN_runproject, supplying the name of the EPANET input file, the name of a Report file where status and error messages are written, and the name of a binary Output file which will contain analysis results.
 
-# Have the application access the output file to display desired analysis results (see @ref OutFile).
 
Here is an example where a callback function `writeConsole` is provided to write EPANET's progress messages to the console:
 
\code {.c}
#include "epanet2_2.h"
 
void  writeConsole(char *s)
{
    fprintf(stdout, "\n%s", s);
}
 
int runEpanet(char* inpFile, char* rptFile, char* outFile)
{
    int errcode;
    EN_project ph;
    EN_createproject(&pH);
    errcode = EN_runproject(ph, inpFile, rptFile, outFile, &writeConsole);
    EN_deleteproject(ph);
    return errcode;
}
\endcode
*/
 
/** @page Example2 Network Building Example
This example shows how a network can be built just through toolkit function calls, eliminating the
need to always use an EPANET formatted input file. This creates opportunities to use other sources
of network data in one's code, such as relational database files or GIS/CAD files.
 
Below is a schematic of the network to be built.
<table style = "border: 0px solid black">
<tr><td>
@image html Example2.png
@image latex Example2.eps
</td></tr>
</table>
 
\code {.c}
#include "epanet2_2.h"
 
void netbuilder()
{
    // Create a project that uses gpm for flow units and
    // the Hazen-Williams formula for head loss
    int index;
    EN_Project ph;
    EN_createproject(&ph);
    EN_init(ph, "", "", EN_GPM, EN_HW);
 
    // Add the first junction node to the project with
    // an elevation of 700 ft and a demand of 0
    EN_addnode(ph, "J1", EN_JUNCTION, &index);
    EN_setjuncdata(ph, index, 700, 0, "");
 
    // Add the remaining two junctions with elevations of
    //  710 ft and demands of 250 and 500 gpm, respectively
    EN_addnode(ph, "J2", EN_JUNCTION, &index);
    EN_setjuncdata(ph, index, 710, 250, "");
    EN_addnode(ph, "J3", EN_JUNCTION, &index);
    EN_setjuncdata(ph, index, 710, 500, "");
 
    // Add the reservoir at an elevation of 650 ft
    EN_addnode(ph, "R1", EN_RESERVOIR, &index);
    EN_setnodevalue(ph, index, EN_ELEVATION, 650);
 
    // Add the tank node at elevation of 850 ft, initial water level
    // at 120 ft, minimum level at 100 ft, maximum level at 150 ft
    // and a diameter of 50.5 ft
    EN_addnode(ph, "T1", EN_TANK, &index);
    EN_settankdata(ph, index, 850, 120, 100, 150, 50.5, 0, "");
 
    // Add the pipes to the project, setting their length,
    // diameter, and roughness values
    EN_addlink(ph, "P1", EN_PIPE, "J1", "J2", &index);
    EN_setpipedata(ph, index, 10560, 12, 100, 0);
    EN_addlink(ph, "P2", EN_PIPE, "J1", "T1", &index);
    EN_setpipedata(ph, index, 5280, 14, 100, 0);
    EN_addlink(ph, "P3", EN_PIPE, "J1", "J3", &index);
    EN_setpipedata(ph, index, 5280, 14, 100, 0);
    EN_addlink(ph, "P4", EN_PIPE, "J2", "J3", &index);
    EN_setpipedata(ph, index, 5280, 14, 100, 0);
 
    // Add a pump to the project
    EN_addlink(ph, "PUMP", EN_PUMP, "R1", "J1", &index);
 
    // Create a single point head curve (index = 1) and
    // assign it to the pump
    EN_addcurve(ph, "C1");
    EN_setcurvevalue(ph, 1, 1, 1500, 250);
    EN_setlinkvalue(ph, index, EN_PUMP_HCURVE, 1);
 
    // Save the project for future use
    EN_saveinpfile(ph, "example2.inp");
 
    // Delete the project
    EN_deleteproject(ph);
}
\endcode
*/
 
/** @page Example3 Hydrant Rating Curve Example
 
This example illustrates how the Toolkit could be used to develop a hydrant rating curve used in fire flow studies. This curve shows the amount of flow available at a node in the system as a function of pressure. The curve is generated by running a number of steady state hydraulic analyses with the node of interest subjected to a different demand in each analysis. For this example we assume that the ID label of the node of interest is `MyNode` and that `N` different demand levels stored in the array `D` need to be examined. The corresponding pressures will be stored in `P`. To keep the code more readable, no error checking is made on the results returned from the Toolkit function calls.
 
\code {.c}
#include "epanet2_2.h"
 
void HydrantRating(char *MyNode, int N, double D[], double P[])
{
    EN_Project ph;
    int   i, nodeindex;
    long  t;
    double pressure;
 
    // Create a project
    EN_createproject(&ph);
 
    // Retrieve network data from an input file
    EN_open(ph, "example2.inp", "example2.rpt", "");
 
    // Open the hydraulic solver
    EN_openH(ph);
 
    // Get the index of the node of interest
    EN_getnodeindex(ph, MyNode, &nodeindex);
 
    // Iterate over all demands
    for (i=1; i<N; i++)
    {
        // Set nodal demand, initialize hydraulics, make a
        // single period run, and retrieve pressure
        EN_setnodevalue(ph, nodeindex, EN_BASEDEMAND, D[i]);
        EN_initH(ph, 0);
        EN_runH(ph, &t);
        EN_getnodevalue(ph, nodeindex, EN_PRESSURE, &pressure);
        P[i] = pressure;
    }
 
    // Close hydraulics solver & delete the project
    EN_closeH(ph);
    EN_deleteproject(ph);
}
\endcode
*/
 
/** @page Example4 Chlorine Dosage Example
 
This example illustrates how the Toolkit could be used to determine the lowest dose of chlorine applied at the entrance to a distribution system needed to ensure that a minimum residual is met throughout the system. We assume that the EPANET input file contains the proper set of kinetic coefficients that describe the rate at which chlorine will decay in the system being studied. In the example code, the ID label of the source node is contained in `SourceID`, the minimum residual target is given by `Ctarget`, and the target is only checked after a start-up duration of 5 days (432,000 seconds). To keep the code more readable, no error checking is made on the results returned from the Toolkit function calls.
 
\code {.c}
#include "epanet2_2.h"
 
double cl2dose(char *SourceID, double Ctarget)
{
    int i, nnodes, sourceindex, violation;
    double c, csource;
    long t, tstep;
    EN_Project ph;
 
    // Open the toolkit & obtain a hydraulic solution
    EN_createproject(&ph);
    EN_open(ph, "example3.inp", "example3.rpt", "");
    EN_solveH(ph);
 
    // Get the number of nodes and the source node's index
    EN_getcount(ph, EN_NODECOUNT, &nnodes);
    EN_getnodeindex(ph, SourceID, &sourceindex);
 
    // Setup the system to analyze for chlorine
    // (in case it was not done in the input file)
    EN_setqualtype(ph, EN_CHEM, "Chlorine", "mg/L", "");
 
    // Open the water quality solver
    EN_openQ(ph);
 
    // Begin the search for the source concentration
    csource = 0.0;
    do {
 
        // Update source concentration to next level
        csource = csource + 0.1;
        EN_setnodevalue(ph, sourceindex, EN_SOURCEQUAL, csource);
 
        // Run WQ simulation checking for target violations
        violation = 0;
        EN_initQ(ph, 0);
        do {
            EN_runQ(ph, &t);
            if (t > 432000) {
                for (i=1; i<=nnodes; i++) {
                    EN_getnodevalue(ph, i, EN_QUALITY, &c);
                    if (c < Ctarget) {
                        violation = 1;
                        break;
                    }
                }
            }
            EN_nextQ(ph, &tstep);
 
        // End WQ run if violation found
        } while (!violation && tstep > 0);
 
    // Continue search if violation found
    } while (violation && csource <= 4.0);
 
    // Close up the WQ solver and delete the project
    EN_closeQ(ph);
    EN_deleteproject(ph);
    return csource;
}
\endcode
 
*/