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.
- epyt_flow/EPANET/EPANET/SRC_engines/AUTHORS +28 -0
- epyt_flow/EPANET/EPANET/SRC_engines/LICENSE +21 -0
- epyt_flow/EPANET/EPANET/SRC_engines/Readme_SRC_Engines.txt +18 -0
- epyt_flow/EPANET/EPANET/SRC_engines/enumstxt.h +134 -0
- epyt_flow/EPANET/EPANET/SRC_engines/epanet.c +5578 -0
- epyt_flow/EPANET/EPANET/SRC_engines/epanet2.c +865 -0
- epyt_flow/EPANET/EPANET/SRC_engines/epanet2.def +131 -0
- epyt_flow/EPANET/EPANET/SRC_engines/errors.dat +73 -0
- epyt_flow/EPANET/EPANET/SRC_engines/funcs.h +193 -0
- epyt_flow/EPANET/EPANET/SRC_engines/genmmd.c +1000 -0
- epyt_flow/EPANET/EPANET/SRC_engines/hash.c +177 -0
- epyt_flow/EPANET/EPANET/SRC_engines/hash.h +28 -0
- epyt_flow/EPANET/EPANET/SRC_engines/hydcoeffs.c +1151 -0
- epyt_flow/EPANET/EPANET/SRC_engines/hydraul.c +1117 -0
- epyt_flow/EPANET/EPANET/SRC_engines/hydsolver.c +720 -0
- epyt_flow/EPANET/EPANET/SRC_engines/hydstatus.c +476 -0
- epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2.h +431 -0
- epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_2.h +1786 -0
- epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_enums.h +468 -0
- epyt_flow/EPANET/EPANET/SRC_engines/inpfile.c +810 -0
- epyt_flow/EPANET/EPANET/SRC_engines/input1.c +707 -0
- epyt_flow/EPANET/EPANET/SRC_engines/input2.c +864 -0
- epyt_flow/EPANET/EPANET/SRC_engines/input3.c +2170 -0
- epyt_flow/EPANET/EPANET/SRC_engines/main.c +93 -0
- epyt_flow/EPANET/EPANET/SRC_engines/mempool.c +142 -0
- epyt_flow/EPANET/EPANET/SRC_engines/mempool.h +24 -0
- epyt_flow/EPANET/EPANET/SRC_engines/output.c +852 -0
- epyt_flow/EPANET/EPANET/SRC_engines/project.c +1359 -0
- epyt_flow/EPANET/EPANET/SRC_engines/quality.c +685 -0
- epyt_flow/EPANET/EPANET/SRC_engines/qualreact.c +743 -0
- epyt_flow/EPANET/EPANET/SRC_engines/qualroute.c +694 -0
- epyt_flow/EPANET/EPANET/SRC_engines/report.c +1489 -0
- epyt_flow/EPANET/EPANET/SRC_engines/rules.c +1362 -0
- epyt_flow/EPANET/EPANET/SRC_engines/smatrix.c +871 -0
- epyt_flow/EPANET/EPANET/SRC_engines/text.h +497 -0
- epyt_flow/EPANET/EPANET/SRC_engines/types.h +874 -0
- epyt_flow/EPANET/EPANET-MSX/MSX_Updates.txt +53 -0
- epyt_flow/EPANET/EPANET-MSX/Src/dispersion.h +27 -0
- epyt_flow/EPANET/EPANET-MSX/Src/hash.c +107 -0
- epyt_flow/EPANET/EPANET-MSX/Src/hash.h +28 -0
- epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx.h +102 -0
- epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx_export.h +42 -0
- epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.c +937 -0
- epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.h +39 -0
- epyt_flow/EPANET/EPANET-MSX/Src/mempool.c +204 -0
- epyt_flow/EPANET/EPANET-MSX/Src/mempool.h +24 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxchem.c +1285 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxcompiler.c +368 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxdict.h +42 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxdispersion.c +586 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxerr.c +116 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxfile.c +260 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.c +175 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.h +35 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxinp.c +1504 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxout.c +401 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxproj.c +791 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxqual.c +2010 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxrpt.c +400 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxtank.c +422 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxtoolkit.c +1164 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxtypes.h +551 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxutils.c +524 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxutils.h +56 -0
- epyt_flow/EPANET/EPANET-MSX/Src/newton.c +158 -0
- epyt_flow/EPANET/EPANET-MSX/Src/newton.h +34 -0
- epyt_flow/EPANET/EPANET-MSX/Src/rk5.c +287 -0
- epyt_flow/EPANET/EPANET-MSX/Src/rk5.h +39 -0
- epyt_flow/EPANET/EPANET-MSX/Src/ros2.c +293 -0
- epyt_flow/EPANET/EPANET-MSX/Src/ros2.h +35 -0
- epyt_flow/EPANET/EPANET-MSX/Src/smatrix.c +816 -0
- epyt_flow/EPANET/EPANET-MSX/Src/smatrix.h +29 -0
- epyt_flow/EPANET/EPANET-MSX/readme.txt +14 -0
- epyt_flow/EPANET/compile.sh +4 -0
- epyt_flow/VERSION +1 -0
- epyt_flow/__init__.py +24 -0
- epyt_flow/data/__init__.py +0 -0
- epyt_flow/data/benchmarks/__init__.py +11 -0
- epyt_flow/data/benchmarks/batadal.py +257 -0
- epyt_flow/data/benchmarks/batadal_data.py +28 -0
- epyt_flow/data/benchmarks/battledim.py +473 -0
- epyt_flow/data/benchmarks/battledim_data.py +51 -0
- epyt_flow/data/benchmarks/gecco_water_quality.py +267 -0
- epyt_flow/data/benchmarks/leakdb.py +592 -0
- epyt_flow/data/benchmarks/leakdb_data.py +18923 -0
- epyt_flow/data/benchmarks/water_usage.py +123 -0
- epyt_flow/data/networks.py +650 -0
- epyt_flow/gym/__init__.py +4 -0
- epyt_flow/gym/control_gyms.py +47 -0
- epyt_flow/gym/scenario_control_env.py +101 -0
- epyt_flow/metrics.py +404 -0
- epyt_flow/models/__init__.py +2 -0
- epyt_flow/models/event_detector.py +31 -0
- epyt_flow/models/sensor_interpolation_detector.py +118 -0
- epyt_flow/rest_api/__init__.py +4 -0
- epyt_flow/rest_api/base_handler.py +70 -0
- epyt_flow/rest_api/res_manager.py +95 -0
- epyt_flow/rest_api/scada_data_handler.py +476 -0
- epyt_flow/rest_api/scenario_handler.py +352 -0
- epyt_flow/rest_api/server.py +106 -0
- epyt_flow/serialization.py +438 -0
- epyt_flow/simulation/__init__.py +5 -0
- epyt_flow/simulation/events/__init__.py +6 -0
- epyt_flow/simulation/events/actuator_events.py +259 -0
- epyt_flow/simulation/events/event.py +81 -0
- epyt_flow/simulation/events/leakages.py +404 -0
- epyt_flow/simulation/events/sensor_faults.py +267 -0
- epyt_flow/simulation/events/sensor_reading_attack.py +185 -0
- epyt_flow/simulation/events/sensor_reading_event.py +170 -0
- epyt_flow/simulation/events/system_event.py +88 -0
- epyt_flow/simulation/parallel_simulation.py +147 -0
- epyt_flow/simulation/scada/__init__.py +3 -0
- epyt_flow/simulation/scada/advanced_control.py +134 -0
- epyt_flow/simulation/scada/scada_data.py +1589 -0
- epyt_flow/simulation/scada/scada_data_export.py +255 -0
- epyt_flow/simulation/scenario_config.py +608 -0
- epyt_flow/simulation/scenario_simulator.py +1897 -0
- epyt_flow/simulation/scenario_visualizer.py +61 -0
- epyt_flow/simulation/sensor_config.py +1289 -0
- epyt_flow/topology.py +290 -0
- epyt_flow/uncertainty/__init__.py +3 -0
- epyt_flow/uncertainty/model_uncertainty.py +302 -0
- epyt_flow/uncertainty/sensor_noise.py +73 -0
- epyt_flow/uncertainty/uncertainties.py +555 -0
- epyt_flow/uncertainty/utils.py +206 -0
- epyt_flow/utils.py +306 -0
- epyt_flow-0.1.0.dist-info/LICENSE +21 -0
- epyt_flow-0.1.0.dist-info/METADATA +139 -0
- epyt_flow-0.1.0.dist-info/RECORD +131 -0
- epyt_flow-0.1.0.dist-info/WHEEL +5 -0
- epyt_flow-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,791 @@
|
|
|
1
|
+
/******************************************************************************
|
|
2
|
+
** MODULE: MSXPROJ.C
|
|
3
|
+
** PROJECT: EPANET-MSX
|
|
4
|
+
** DESCRIPTION: project data manager used by the EPANET Multi-Species
|
|
5
|
+
** Extension toolkit.
|
|
6
|
+
** AUTHORS: see AUTHORS
|
|
7
|
+
** Copyright: see AUTHORS
|
|
8
|
+
** License: see LICENSE
|
|
9
|
+
** VERSION: 2.0.00
|
|
10
|
+
** LAST UPDATE: 08/30/2022
|
|
11
|
+
******************************************************************************/
|
|
12
|
+
|
|
13
|
+
#include <stdio.h>
|
|
14
|
+
#include <string.h>
|
|
15
|
+
#include <math.h>
|
|
16
|
+
#include <stdlib.h>
|
|
17
|
+
|
|
18
|
+
#include "msxtypes.h"
|
|
19
|
+
#include "msxutils.h"
|
|
20
|
+
//#include "mempool.h"
|
|
21
|
+
#include "hash.h"
|
|
22
|
+
#include "smatrix.h"
|
|
23
|
+
#include "epanet2.h"
|
|
24
|
+
#include "dispersion.h"
|
|
25
|
+
// Exported variables
|
|
26
|
+
//--------------------
|
|
27
|
+
MSXproject MSX; // MSX project data
|
|
28
|
+
|
|
29
|
+
// Local variables
|
|
30
|
+
//-----------------
|
|
31
|
+
static alloc_handle_t *HashPool; // Memory pool for hash tables
|
|
32
|
+
static HTtable *Htable[MAX_OBJECTS]; // Hash tables for object ID names
|
|
33
|
+
|
|
34
|
+
static char * Errmsg[] =
|
|
35
|
+
{"unknown error code.",
|
|
36
|
+
"Error 501 - insufficient memory available.",
|
|
37
|
+
"Error 502 - no EPANET data file supplied.",
|
|
38
|
+
"Error 503 - could not open MSX input file.",
|
|
39
|
+
"Error 504 - could not open hydraulic results file.",
|
|
40
|
+
"Error 505 - could not read hydraulic results file.",
|
|
41
|
+
"Error 506 - could not read MSX input file.",
|
|
42
|
+
"Error 507 - too few pipe reaction expressions.",
|
|
43
|
+
"Error 508 - too few tank reaction expressions.",
|
|
44
|
+
"Error 509 - could not open differential equation solver.",
|
|
45
|
+
"Error 510 - could not open algebraic equation solver.",
|
|
46
|
+
"Error 511 - could not open binary results file.",
|
|
47
|
+
"Error 512 - read/write error on binary results file.",
|
|
48
|
+
"Error 513 - could not integrate reaction rate expressions.",
|
|
49
|
+
"Error 514 - could not solve reaction equilibrium expressions.",
|
|
50
|
+
"Error 515 - reference made to an unknown type of object.",
|
|
51
|
+
"Error 516 - reference made to an illegal object index.",
|
|
52
|
+
"Error 517 - reference made to an undefined object ID.",
|
|
53
|
+
"Error 518 - invalid property values were specified.",
|
|
54
|
+
"Error 519 - an MSX project was not opened.",
|
|
55
|
+
"Error 520 - an MSX project is already opened.",
|
|
56
|
+
"Error 521 - could not open MSX report file.", //(LR-11/20/07)
|
|
57
|
+
|
|
58
|
+
"Error 522 - could not compile chemistry functions.",
|
|
59
|
+
"Error 523 - could not load functions from compiled chemistry file.",
|
|
60
|
+
"Error 524 - illegal math operation."};
|
|
61
|
+
|
|
62
|
+
// Imported functions
|
|
63
|
+
//--------------------
|
|
64
|
+
int MSXinp_countMsxObjects(void);
|
|
65
|
+
int MSXinp_countNetObjects(void);
|
|
66
|
+
int MSXinp_readNetData(void);
|
|
67
|
+
int MSXinp_readMsxData(void);
|
|
68
|
+
|
|
69
|
+
// Exported functions
|
|
70
|
+
//--------------------
|
|
71
|
+
int MSXproj_open(char *fname);
|
|
72
|
+
int MSXproj_addObject(int type, char *id, int n);
|
|
73
|
+
int MSXproj_findObject(int type, char *id);
|
|
74
|
+
char * MSXproj_findID(int type, char *id);
|
|
75
|
+
char * MSXproj_getErrmsg(int errcode);
|
|
76
|
+
|
|
77
|
+
// Local functions
|
|
78
|
+
//-----------------
|
|
79
|
+
static void setDefaults(void);
|
|
80
|
+
static int convertUnits(void);
|
|
81
|
+
static int createObjects(void);
|
|
82
|
+
static void deleteObjects(void);
|
|
83
|
+
static int createHashTables(void);
|
|
84
|
+
static void deleteHashTables(void);
|
|
85
|
+
|
|
86
|
+
static int openRptFile(void); //(LR-11/20/07)
|
|
87
|
+
|
|
88
|
+
static int buildadjlists();
|
|
89
|
+
static void freeadjlists();
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
//=============================================================================
|
|
93
|
+
|
|
94
|
+
int MSXproj_open(char *fname)
|
|
95
|
+
/*
|
|
96
|
+
** Purpose:
|
|
97
|
+
** opens an EPANET-MSX project.
|
|
98
|
+
**
|
|
99
|
+
** Input:
|
|
100
|
+
** fname = name of EPANET-MSX input file
|
|
101
|
+
**
|
|
102
|
+
** Returns:
|
|
103
|
+
** an error code (0 if no error)
|
|
104
|
+
*/
|
|
105
|
+
{
|
|
106
|
+
// --- initialize data to default values
|
|
107
|
+
|
|
108
|
+
int errcode = 0;
|
|
109
|
+
MSX.ProjectOpened = FALSE;
|
|
110
|
+
MSX.QualityOpened = FALSE;
|
|
111
|
+
setDefaults();
|
|
112
|
+
|
|
113
|
+
// --- open the MSX input file
|
|
114
|
+
|
|
115
|
+
strcpy(MSX.MsxFile.name, fname);
|
|
116
|
+
if ((MSX.MsxFile.file = fopen(fname,"rt")) == NULL) return ERR_OPEN_MSX_FILE;
|
|
117
|
+
|
|
118
|
+
// --- create hash tables to look up object ID names
|
|
119
|
+
|
|
120
|
+
CALL(errcode, createHashTables());
|
|
121
|
+
|
|
122
|
+
// --- allocate memory for the required number of objects
|
|
123
|
+
|
|
124
|
+
CALL(errcode, MSXinp_countMsxObjects());
|
|
125
|
+
CALL(errcode, MSXinp_countNetObjects());
|
|
126
|
+
CALL(errcode, createObjects());
|
|
127
|
+
|
|
128
|
+
MSX.DispersionFlag = 0; //no dispersion by default, unless yes in msx file
|
|
129
|
+
|
|
130
|
+
// --- read in the EPANET and MSX object data
|
|
131
|
+
|
|
132
|
+
CALL(errcode, MSXinp_readNetData());
|
|
133
|
+
CALL(errcode, MSXinp_readMsxData());
|
|
134
|
+
|
|
135
|
+
if (strcmp(MSX.RptFile.name, ""))
|
|
136
|
+
CALL(errcode, openRptFile());
|
|
137
|
+
|
|
138
|
+
// --- convert user's units to internal units
|
|
139
|
+
|
|
140
|
+
CALL(errcode, convertUnits());
|
|
141
|
+
|
|
142
|
+
if (MSX.DispersionFlag != 0)
|
|
143
|
+
{
|
|
144
|
+
float relvis;
|
|
145
|
+
ENgetoption(13, &relvis);
|
|
146
|
+
MSX.Dispersion.viscosity = relvis * 1.1E-5;
|
|
147
|
+
|
|
148
|
+
msx_createsparse(); //symmetric matrix
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Build nodal adjacency lists
|
|
152
|
+
if (errcode == 0 && MSX.Adjlist == NULL)
|
|
153
|
+
{
|
|
154
|
+
errcode = buildadjlists(); //parallel links are included
|
|
155
|
+
if (errcode) return errcode;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// --- close input file
|
|
159
|
+
|
|
160
|
+
if ( MSX.MsxFile.file ) fclose(MSX.MsxFile.file);
|
|
161
|
+
MSX.MsxFile.file = NULL;
|
|
162
|
+
if ( !errcode ) MSX.ProjectOpened = TRUE;
|
|
163
|
+
return errcode;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
//=============================================================================
|
|
167
|
+
|
|
168
|
+
void MSXproj_close()
|
|
169
|
+
/*
|
|
170
|
+
** Purpose:
|
|
171
|
+
** closes the current EPANET-MSX project.
|
|
172
|
+
**
|
|
173
|
+
** Input:
|
|
174
|
+
** none
|
|
175
|
+
*/
|
|
176
|
+
{
|
|
177
|
+
// --- close all files
|
|
178
|
+
|
|
179
|
+
if ( MSX.RptFile.file ) fclose(MSX.RptFile.file); //(LR-11/20/07, to fix bug 08)
|
|
180
|
+
if ( MSX.HydFile.file ) fclose(MSX.HydFile.file);
|
|
181
|
+
if ( MSX.TmpOutFile.file && MSX.TmpOutFile.file != MSX.OutFile.file )
|
|
182
|
+
fclose(MSX.TmpOutFile.file);
|
|
183
|
+
if ( MSX.OutFile.file ) fclose(MSX.OutFile.file);
|
|
184
|
+
|
|
185
|
+
// --- delete all temporary files
|
|
186
|
+
|
|
187
|
+
if ( MSX.HydFile.mode == SCRATCH_FILE ) remove(MSX.HydFile.name);
|
|
188
|
+
if ( MSX.OutFile.mode == SCRATCH_FILE ) remove(MSX.OutFile.name);
|
|
189
|
+
remove(MSX.TmpOutFile.name);
|
|
190
|
+
|
|
191
|
+
// --- free all allocated memory
|
|
192
|
+
|
|
193
|
+
MSX.RptFile.file = NULL; //(LR-11/20/07, to fix bug 08)
|
|
194
|
+
MSX.HydFile.file = NULL;
|
|
195
|
+
MSX.OutFile.file = NULL;
|
|
196
|
+
MSX.TmpOutFile.file = NULL;
|
|
197
|
+
deleteObjects();
|
|
198
|
+
deleteHashTables();
|
|
199
|
+
MSX.ProjectOpened = FALSE;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
//=============================================================================
|
|
203
|
+
|
|
204
|
+
int MSXproj_addObject(int type, char *id, int n)
|
|
205
|
+
/*
|
|
206
|
+
** Purpose:
|
|
207
|
+
** adds an object ID to the project's hash tables.
|
|
208
|
+
**
|
|
209
|
+
** Input:
|
|
210
|
+
** type = object type
|
|
211
|
+
** id = object ID string
|
|
212
|
+
** n = object index.
|
|
213
|
+
**
|
|
214
|
+
** Returns:
|
|
215
|
+
** 0 if object already added, 1 if not, -1 if hashing fails.
|
|
216
|
+
*/
|
|
217
|
+
{
|
|
218
|
+
int result;
|
|
219
|
+
int len;
|
|
220
|
+
char *newID;
|
|
221
|
+
|
|
222
|
+
// --- do nothing if object already exists in a hash table
|
|
223
|
+
|
|
224
|
+
if ( MSXproj_findObject(type, id) > 0 ) return 0;
|
|
225
|
+
|
|
226
|
+
// --- use memory from the hash tables' common memory pool to store
|
|
227
|
+
// a copy of the object's ID string
|
|
228
|
+
|
|
229
|
+
len = (int)strlen(id) + 1;
|
|
230
|
+
newID = (char *) Alloc(len*sizeof(char));
|
|
231
|
+
strcpy(newID, id);
|
|
232
|
+
|
|
233
|
+
// --- insert object's ID into the hash table for that type of object
|
|
234
|
+
|
|
235
|
+
result = HTinsert(Htable[type], newID, n);
|
|
236
|
+
if ( result == 0 ) result = -1;
|
|
237
|
+
return result;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
//=============================================================================
|
|
241
|
+
|
|
242
|
+
int MSXproj_findObject(int type, char *id)
|
|
243
|
+
/*
|
|
244
|
+
** Purpose:
|
|
245
|
+
** uses hash table to find index of an object with a given ID.
|
|
246
|
+
**
|
|
247
|
+
** Input:
|
|
248
|
+
** type = object type
|
|
249
|
+
** id = object ID.
|
|
250
|
+
**
|
|
251
|
+
** Returns:
|
|
252
|
+
** index of object with given ID, or -1 if ID not found.
|
|
253
|
+
*/
|
|
254
|
+
{
|
|
255
|
+
return HTfind(Htable[type], id);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
//=============================================================================
|
|
259
|
+
|
|
260
|
+
char * MSXproj_findID(int type, char *id)
|
|
261
|
+
/*
|
|
262
|
+
** Purpose:
|
|
263
|
+
** uses hash table to find address of given string entry.
|
|
264
|
+
**
|
|
265
|
+
** Input:
|
|
266
|
+
** type = object type
|
|
267
|
+
** id = ID name being sought.
|
|
268
|
+
**
|
|
269
|
+
** Returns:
|
|
270
|
+
** pointer to location where object's ID string is stored.
|
|
271
|
+
*/
|
|
272
|
+
{
|
|
273
|
+
return HTfindKey(Htable[type], id);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
//=============================================================================
|
|
277
|
+
|
|
278
|
+
char * MSXproj_getErrmsg(int errcode)
|
|
279
|
+
/*
|
|
280
|
+
** Purpose:
|
|
281
|
+
** gets the text of an error message.
|
|
282
|
+
**
|
|
283
|
+
** Input:
|
|
284
|
+
** errcode = error code.
|
|
285
|
+
**
|
|
286
|
+
** Returns:
|
|
287
|
+
** text of error message.
|
|
288
|
+
*/
|
|
289
|
+
{
|
|
290
|
+
if ( errcode <= ERR_FIRST || errcode >= ERR_MAX ) return Errmsg[0];
|
|
291
|
+
else return Errmsg[errcode - ERR_FIRST];
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
//=============================================================================
|
|
295
|
+
|
|
296
|
+
void setDefaults()
|
|
297
|
+
/*
|
|
298
|
+
** Purpose:
|
|
299
|
+
** assigns default values to project variables.
|
|
300
|
+
**
|
|
301
|
+
** Input:
|
|
302
|
+
** none.
|
|
303
|
+
*/
|
|
304
|
+
{
|
|
305
|
+
int i;
|
|
306
|
+
MSX.RptFile.file = NULL; //(LR-11/20/07)
|
|
307
|
+
MSX.HydFile.file = NULL;
|
|
308
|
+
MSX.HydFile.mode = USED_FILE;
|
|
309
|
+
MSX.OutFile.file = NULL;
|
|
310
|
+
MSX.OutFile.mode = SCRATCH_FILE;
|
|
311
|
+
MSX.TmpOutFile.file = NULL;
|
|
312
|
+
MSXutils_getTempName(MSX.OutFile.name);
|
|
313
|
+
MSXutils_getTempName(MSX.TmpOutFile.name);
|
|
314
|
+
strcpy(MSX.RptFile.name, "");
|
|
315
|
+
strcpy(MSX.Title, "");
|
|
316
|
+
MSX.Rptflag = 0;
|
|
317
|
+
for (i=0; i<MAX_OBJECTS; i++) MSX.Nobjects[i] = 0;
|
|
318
|
+
MSX.Unitsflag = US;
|
|
319
|
+
MSX.Flowflag = GPM;
|
|
320
|
+
MSX.Statflag = SERIES;
|
|
321
|
+
MSX.DefRtol = 0.001;
|
|
322
|
+
MSX.DefAtol = 0.01;
|
|
323
|
+
MSX.Solver = EUL;
|
|
324
|
+
MSX.Coupling = NO_COUPLING;
|
|
325
|
+
MSX.Compiler = NO_COMPILER;
|
|
326
|
+
MSX.ErrCode = 0;
|
|
327
|
+
MSX.AreaUnits = FT2;
|
|
328
|
+
MSX.RateUnits = DAYS;
|
|
329
|
+
MSX.Qstep = 300*1000; // 300,000 millisec = 5 minutes
|
|
330
|
+
MSX.Rstep = 3600;
|
|
331
|
+
MSX.Rstart = 0;
|
|
332
|
+
MSX.Dur = 0;
|
|
333
|
+
MSX.Node = NULL;
|
|
334
|
+
MSX.Link = NULL;
|
|
335
|
+
MSX.Tank = NULL;
|
|
336
|
+
MSX.D = NULL;
|
|
337
|
+
MSX.Q = NULL;
|
|
338
|
+
MSX.H = NULL;
|
|
339
|
+
MSX.S = NULL;
|
|
340
|
+
MSX.Species = NULL;
|
|
341
|
+
MSX.Term = NULL;
|
|
342
|
+
MSX.Const = NULL;
|
|
343
|
+
MSX.Pattern = NULL;
|
|
344
|
+
MSX.K = NULL;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
//=============================================================================
|
|
348
|
+
|
|
349
|
+
int convertUnits()
|
|
350
|
+
/*
|
|
351
|
+
** Purpose:
|
|
352
|
+
** converts user's units to internal EPANET units.
|
|
353
|
+
**
|
|
354
|
+
** Input:
|
|
355
|
+
** none.
|
|
356
|
+
**
|
|
357
|
+
** Returns:
|
|
358
|
+
** an error code (0 if no error).
|
|
359
|
+
*/
|
|
360
|
+
{
|
|
361
|
+
// --- flow conversion factors (to cfs)
|
|
362
|
+
double fcf[] = {1.0, GPMperCFS, MGDperCFS, IMGDperCFS, AFDperCFS,
|
|
363
|
+
LPSperCFS, LPMperCFS, MLDperCFS, CMHperCFS, CMDperCFS};
|
|
364
|
+
|
|
365
|
+
// --- rate time units conversion factors (to sec)
|
|
366
|
+
double rcf[] = {1.0, 60.0, 3600.0, 86400.0};
|
|
367
|
+
|
|
368
|
+
int i, m, errcode = 0;
|
|
369
|
+
|
|
370
|
+
// --- conversions for length & tank volume
|
|
371
|
+
|
|
372
|
+
if ( MSX.Unitsflag == US )
|
|
373
|
+
{
|
|
374
|
+
MSX.Ucf[LENGTH_UNITS] = 1.0;
|
|
375
|
+
MSX.Ucf[DIAM_UNITS] = 12.0;
|
|
376
|
+
MSX.Ucf[VOL_UNITS] = 1.0;
|
|
377
|
+
}
|
|
378
|
+
else
|
|
379
|
+
{
|
|
380
|
+
MSX.Ucf[LENGTH_UNITS] = MperFT;
|
|
381
|
+
MSX.Ucf[DIAM_UNITS] = 1000.0*MperFT;
|
|
382
|
+
MSX.Ucf[VOL_UNITS] = M3perFT3;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// --- conversion for surface area
|
|
386
|
+
|
|
387
|
+
MSX.Ucf[AREA_UNITS] = 1.0;
|
|
388
|
+
switch (MSX.AreaUnits)
|
|
389
|
+
{
|
|
390
|
+
case M2: MSX.Ucf[AREA_UNITS] = M2perFT2; break;
|
|
391
|
+
case CM2: MSX.Ucf[AREA_UNITS] = CM2perFT2; break;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// --- conversion for flow rate
|
|
395
|
+
|
|
396
|
+
MSX.Ucf[FLOW_UNITS] = fcf[MSX.Flowflag];
|
|
397
|
+
MSX.Ucf[CONC_UNITS] = LperFT3;
|
|
398
|
+
|
|
399
|
+
// --- conversion for reaction rate time
|
|
400
|
+
|
|
401
|
+
MSX.Ucf[RATE_UNITS] = rcf[MSX.RateUnits];
|
|
402
|
+
|
|
403
|
+
// --- convert pipe diameter & length
|
|
404
|
+
|
|
405
|
+
for (i=1; i<=MSX.Nobjects[LINK]; i++)
|
|
406
|
+
{
|
|
407
|
+
MSX.Link[i].diam /= MSX.Ucf[DIAM_UNITS];
|
|
408
|
+
MSX.Link[i].len /= MSX.Ucf[LENGTH_UNITS];
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// --- convert initial tank volumes
|
|
412
|
+
|
|
413
|
+
for (i=1; i<=MSX.Nobjects[TANK]; i++)
|
|
414
|
+
{
|
|
415
|
+
MSX.Tank[i].v0 /= MSX.Ucf[VOL_UNITS];
|
|
416
|
+
MSX.Tank[i].vMix /= MSX.Ucf[VOL_UNITS];
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// --- assign default tolerances to species
|
|
420
|
+
|
|
421
|
+
for (m=1; m<=MSX.Nobjects[SPECIES]; m++)
|
|
422
|
+
{
|
|
423
|
+
if ( MSX.Species[m].rTol == 0.0 ) MSX.Species[m].rTol = MSX.DefRtol;
|
|
424
|
+
if ( MSX.Species[m].aTol == 0.0 ) MSX.Species[m].aTol = MSX.DefAtol;
|
|
425
|
+
}
|
|
426
|
+
return errcode;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
//=============================================================================
|
|
431
|
+
|
|
432
|
+
int createObjects()
|
|
433
|
+
/*
|
|
434
|
+
** Purpose:
|
|
435
|
+
** creates multi-species data objects.
|
|
436
|
+
**
|
|
437
|
+
** Input:
|
|
438
|
+
** none.
|
|
439
|
+
**
|
|
440
|
+
** Returns:
|
|
441
|
+
** an error code (0 if no error).
|
|
442
|
+
*/
|
|
443
|
+
{
|
|
444
|
+
int i;
|
|
445
|
+
|
|
446
|
+
// --- create nodes, links, & tanks
|
|
447
|
+
|
|
448
|
+
MSX.Node = (Snode *) calloc(MSX.Nobjects[NODE]+1, sizeof(Snode));
|
|
449
|
+
MSX.Link = (Slink *) calloc(MSX.Nobjects[LINK]+1, sizeof(Slink));
|
|
450
|
+
MSX.Tank = (Stank *) calloc(MSX.Nobjects[TANK]+1, sizeof(Stank));
|
|
451
|
+
|
|
452
|
+
// --- create species, terms, parameters, constants & time patterns
|
|
453
|
+
|
|
454
|
+
MSX.Species = (Sspecies *) calloc(MSX.Nobjects[SPECIES]+1, sizeof(Sspecies));
|
|
455
|
+
MSX.Term = (Sterm *) calloc(MSX.Nobjects[TERM]+1, sizeof(Sterm));
|
|
456
|
+
MSX.Param = (Sparam *) calloc(MSX.Nobjects[PARAMETER]+1, sizeof(Sparam));
|
|
457
|
+
MSX.Const = (Sconst *) calloc(MSX.Nobjects[CONSTANT]+1, sizeof(Sconst));
|
|
458
|
+
MSX.Pattern = (Spattern *) calloc(MSX.Nobjects[PATTERN]+1, sizeof(Spattern));
|
|
459
|
+
MSX.K = (double *) calloc(MSX.Nobjects[CONSTANT]+1, sizeof(double));
|
|
460
|
+
|
|
461
|
+
// --- create arrays for demands, heads, & flows
|
|
462
|
+
|
|
463
|
+
MSX.D = (float *) calloc(MSX.Nobjects[NODE]+1, sizeof(float));
|
|
464
|
+
MSX.H = (float *) calloc(MSX.Nobjects[NODE]+1, sizeof(float));
|
|
465
|
+
MSX.Q = (float *) calloc(MSX.Nobjects[LINK]+1, sizeof(float));
|
|
466
|
+
MSX.S = (float *) calloc(MSX.Nobjects[LINK] + 1, sizeof(float));
|
|
467
|
+
|
|
468
|
+
// --- create arrays for current & initial concen. of each species for each node
|
|
469
|
+
|
|
470
|
+
MSX.C0 = (double *) calloc(MSX.Nobjects[SPECIES]+1, sizeof(double));
|
|
471
|
+
for (i=1; i<=MSX.Nobjects[NODE]; i++)
|
|
472
|
+
{
|
|
473
|
+
MSX.Node[i].c = (double *) calloc(MSX.Nobjects[SPECIES]+1, sizeof(double));
|
|
474
|
+
MSX.Node[i].c0 = (double *) calloc(MSX.Nobjects[SPECIES]+1, sizeof(double));
|
|
475
|
+
MSX.Node[i].rpt = 0;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// --- create arrays for init. concen. & kinetic parameter values for each link
|
|
479
|
+
|
|
480
|
+
for (i=1; i<=MSX.Nobjects[LINK]; i++)
|
|
481
|
+
{
|
|
482
|
+
MSX.Link[i].c0 = (double *)
|
|
483
|
+
calloc(MSX.Nobjects[SPECIES]+1, sizeof(double));
|
|
484
|
+
MSX.Link[i].reacted = (double *)
|
|
485
|
+
calloc(MSX.Nobjects[SPECIES] + 1, sizeof(double));
|
|
486
|
+
MSX.Link[i].param = (double *)
|
|
487
|
+
calloc(MSX.Nobjects[PARAMETER]+1, sizeof(double));
|
|
488
|
+
MSX.Link[i].rpt = 0;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// --- create arrays for kinetic parameter values & current concen. for each tank
|
|
492
|
+
|
|
493
|
+
for (i=1; i<=MSX.Nobjects[TANK]; i++)
|
|
494
|
+
{
|
|
495
|
+
MSX.Tank[i].param = (double *)
|
|
496
|
+
calloc(MSX.Nobjects[PARAMETER]+1, sizeof(double));
|
|
497
|
+
MSX.Tank[i].c = (double *)
|
|
498
|
+
calloc(MSX.Nobjects[SPECIES]+1, sizeof(double));
|
|
499
|
+
MSX.Tank[i].reacted = (double*)
|
|
500
|
+
calloc(MSX.Nobjects[SPECIES] + 1, sizeof(double));
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// --- initialize contents of each time pattern object
|
|
504
|
+
|
|
505
|
+
for (i=1; i<=MSX.Nobjects[PATTERN]; i++)
|
|
506
|
+
{
|
|
507
|
+
MSX.Pattern[i].length = 0;
|
|
508
|
+
MSX.Pattern[i].first = NULL;
|
|
509
|
+
MSX.Pattern[i].current = NULL;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// --- initialize reaction rate & equil. formulas for each species
|
|
513
|
+
|
|
514
|
+
for (i=1; i<=MSX.Nobjects[SPECIES]; i++)
|
|
515
|
+
{
|
|
516
|
+
MSX.Species[i].pipeExpr = NULL;
|
|
517
|
+
MSX.Species[i].tankExpr = NULL;
|
|
518
|
+
MSX.Species[i].pipeExprType = NO_EXPR;
|
|
519
|
+
MSX.Species[i].tankExprType = NO_EXPR;
|
|
520
|
+
MSX.Species[i].precision = 2;
|
|
521
|
+
MSX.Species[i].rpt = 0;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// --- initialize math expressions for each intermediate term
|
|
525
|
+
|
|
526
|
+
for (i=1; i<=MSX.Nobjects[TERM]; i++) MSX.Term[i].expr = NULL;
|
|
527
|
+
|
|
528
|
+
MSX.MaxSegments = MAXSEGMENTS;
|
|
529
|
+
MSX.Dispersion.PecletLimit = 1000.00;
|
|
530
|
+
MSX.Dispersion.DIFFUS = 1.29E-8;
|
|
531
|
+
MSX.Dispersion.md = (double*)
|
|
532
|
+
calloc(MSX.Nobjects[SPECIES] + 1, sizeof(double));
|
|
533
|
+
MSX.Dispersion.ld = (double*)
|
|
534
|
+
calloc(MSX.Nobjects[SPECIES] + 1, sizeof(double));
|
|
535
|
+
|
|
536
|
+
for (int m = 1; m <= MSX.Nobjects[SPECIES]; m++)
|
|
537
|
+
{
|
|
538
|
+
MSX.Dispersion.md[m] = -1.0;
|
|
539
|
+
MSX.Dispersion.ld[m] = -1.0;
|
|
540
|
+
}
|
|
541
|
+
return 0;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
//=============================================================================
|
|
545
|
+
|
|
546
|
+
void deleteObjects()
|
|
547
|
+
/*
|
|
548
|
+
** Purpose:
|
|
549
|
+
** deletes multi-species data objects.
|
|
550
|
+
**
|
|
551
|
+
** Input:
|
|
552
|
+
** none.
|
|
553
|
+
*/
|
|
554
|
+
{
|
|
555
|
+
int i;
|
|
556
|
+
SnumList *listItem;
|
|
557
|
+
|
|
558
|
+
// --- free memory used by nodes, links, and tanks
|
|
559
|
+
|
|
560
|
+
if (MSX.Node) for (i=1; i<=MSX.Nobjects[NODE]; i++)
|
|
561
|
+
{
|
|
562
|
+
FREE(MSX.Node[i].c);
|
|
563
|
+
FREE(MSX.Node[i].c0);
|
|
564
|
+
if(MSX.Node[i].sources)
|
|
565
|
+
{
|
|
566
|
+
struct Ssource *p=MSX.Node[i].sources;
|
|
567
|
+
while(p != NULL)
|
|
568
|
+
{
|
|
569
|
+
MSX.Node[i].sources=p->next;
|
|
570
|
+
FREE(p);
|
|
571
|
+
p=MSX.Node[i].sources;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
if (MSX.Link) for (i=1; i<=MSX.Nobjects[LINK]; i++)
|
|
576
|
+
{
|
|
577
|
+
FREE(MSX.Link[i].c0);
|
|
578
|
+
FREE(MSX.Link[i].param);
|
|
579
|
+
FREE(MSX.Link[i].reacted);
|
|
580
|
+
}
|
|
581
|
+
if (MSX.Tank) for (i=1; i<=MSX.Nobjects[TANK]; i++)
|
|
582
|
+
{
|
|
583
|
+
FREE(MSX.Tank[i].param);
|
|
584
|
+
FREE(MSX.Tank[i].c);
|
|
585
|
+
FREE(MSX.Tank[i].reacted);
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
freeadjlists();
|
|
589
|
+
|
|
590
|
+
// --- free memory used by time patterns
|
|
591
|
+
if (MSX.Pattern) for (i=1; i<=MSX.Nobjects[PATTERN]; i++)
|
|
592
|
+
{
|
|
593
|
+
listItem = MSX.Pattern[i].first;
|
|
594
|
+
while (listItem)
|
|
595
|
+
{
|
|
596
|
+
MSX.Pattern[i].first = listItem->next;
|
|
597
|
+
free(listItem);
|
|
598
|
+
listItem = MSX.Pattern[i].first;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
FREE(MSX.Pattern);
|
|
602
|
+
|
|
603
|
+
// --- free memory used for hydraulics results
|
|
604
|
+
|
|
605
|
+
FREE(MSX.D);
|
|
606
|
+
FREE(MSX.H);
|
|
607
|
+
FREE(MSX.Q);
|
|
608
|
+
FREE(MSX.S);
|
|
609
|
+
FREE(MSX.C0);
|
|
610
|
+
|
|
611
|
+
// --- delete all nodes, links, and tanks
|
|
612
|
+
|
|
613
|
+
FREE(MSX.Node);
|
|
614
|
+
FREE(MSX.Link);
|
|
615
|
+
FREE(MSX.Tank);
|
|
616
|
+
|
|
617
|
+
// --- free memory used by reaction rate & equilibrium expressions
|
|
618
|
+
|
|
619
|
+
if (MSX.Species) for (i=1; i<=MSX.Nobjects[SPECIES]; i++)
|
|
620
|
+
{
|
|
621
|
+
// --- free the species tank expression only if it doesn't
|
|
622
|
+
// already point to the species pipe expression
|
|
623
|
+
if ( MSX.Species[i].tankExpr != MSX.Species[i].pipeExpr )
|
|
624
|
+
{
|
|
625
|
+
mathexpr_delete(MSX.Species[i].tankExpr);
|
|
626
|
+
}
|
|
627
|
+
mathexpr_delete(MSX.Species[i].pipeExpr);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
// --- delete all species, parameters, and constants
|
|
631
|
+
|
|
632
|
+
FREE(MSX.Species);
|
|
633
|
+
FREE(MSX.Param);
|
|
634
|
+
FREE(MSX.Const);
|
|
635
|
+
FREE(MSX.K);
|
|
636
|
+
|
|
637
|
+
// --- free memory used by intermediate terms
|
|
638
|
+
|
|
639
|
+
if (MSX.Term) for (i=1; i<=MSX.Nobjects[TERM]; i++)
|
|
640
|
+
mathexpr_delete(MSX.Term[i].expr);
|
|
641
|
+
FREE(MSX.Term);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
//=============================================================================
|
|
645
|
+
|
|
646
|
+
int createHashTables()
|
|
647
|
+
/*
|
|
648
|
+
** Purpose:
|
|
649
|
+
** allocates memory for object ID hash tables.
|
|
650
|
+
**
|
|
651
|
+
** Input:
|
|
652
|
+
** none.
|
|
653
|
+
**
|
|
654
|
+
** Returns:
|
|
655
|
+
** an error code (0 if no error).
|
|
656
|
+
*/
|
|
657
|
+
{ int j;
|
|
658
|
+
|
|
659
|
+
// --- create a hash table for each type of object
|
|
660
|
+
|
|
661
|
+
for (j = 0; j < MAX_OBJECTS ; j++)
|
|
662
|
+
{
|
|
663
|
+
Htable[j] = HTcreate();
|
|
664
|
+
if ( Htable[j] == NULL ) return ERR_MEMORY;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
// --- initialize the memory pool used to store object ID's
|
|
668
|
+
|
|
669
|
+
HashPool = AllocInit();
|
|
670
|
+
if ( HashPool == NULL ) return ERR_MEMORY;
|
|
671
|
+
return 0;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
//=============================================================================
|
|
675
|
+
|
|
676
|
+
void deleteHashTables()
|
|
677
|
+
/*
|
|
678
|
+
** Purpose:
|
|
679
|
+
** frees memory allocated for object ID hash tables.
|
|
680
|
+
**
|
|
681
|
+
** Input:
|
|
682
|
+
** none.
|
|
683
|
+
*/
|
|
684
|
+
{
|
|
685
|
+
int j;
|
|
686
|
+
|
|
687
|
+
// --- free the hash tables
|
|
688
|
+
|
|
689
|
+
for (j = 0; j < MAX_OBJECTS; j++)
|
|
690
|
+
{
|
|
691
|
+
if ( Htable[j] != NULL ) HTfree(Htable[j]);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// --- free the object ID memory pool
|
|
695
|
+
|
|
696
|
+
if ( HashPool )
|
|
697
|
+
{
|
|
698
|
+
AllocSetPool(HashPool);
|
|
699
|
+
AllocFreePool();
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// New function added (LR-11/20/07, to fix bug 08)
|
|
704
|
+
int openRptFile()
|
|
705
|
+
{
|
|
706
|
+
if ( MSX.RptFile.file ) fclose(MSX.RptFile.file);
|
|
707
|
+
MSX.RptFile.file = fopen(MSX.RptFile.name, "wt");
|
|
708
|
+
if ( MSX.RptFile.file == NULL ) return ERR_OPEN_RPT_FILE;
|
|
709
|
+
return 0;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
int buildadjlists() //from epanet for node sorting in WQ routing
|
|
713
|
+
/*
|
|
714
|
+
**--------------------------------------------------------------
|
|
715
|
+
** Input: none
|
|
716
|
+
** Output: returns error code
|
|
717
|
+
** Purpose: builds linked list of links adjacent to each node
|
|
718
|
+
**--------------------------------------------------------------
|
|
719
|
+
*/
|
|
720
|
+
{
|
|
721
|
+
int i, j, k;
|
|
722
|
+
int errcode = 0;
|
|
723
|
+
Padjlist alink;
|
|
724
|
+
|
|
725
|
+
// Create an array of adjacency lists
|
|
726
|
+
freeadjlists();
|
|
727
|
+
MSX.Adjlist = (Padjlist*)calloc(MSX.Nobjects[NODE]+1, sizeof(Padjlist));
|
|
728
|
+
if (MSX.Adjlist == NULL) return 101;
|
|
729
|
+
for (i = 0; i <= MSX.Nobjects[NODE]; i++)
|
|
730
|
+
MSX.Adjlist[i] = NULL;
|
|
731
|
+
|
|
732
|
+
// For each link, update adjacency lists of its end nodes
|
|
733
|
+
for (k = 1; k <= MSX.Nobjects[LINK]; k++)
|
|
734
|
+
{
|
|
735
|
+
i = MSX.Link[k].n1;
|
|
736
|
+
j = MSX.Link[k].n2;
|
|
737
|
+
|
|
738
|
+
// Include link in start node i's list
|
|
739
|
+
alink = (struct Sadjlist*) malloc(sizeof(struct Sadjlist));
|
|
740
|
+
if (alink == NULL)
|
|
741
|
+
{
|
|
742
|
+
errcode = 101;
|
|
743
|
+
break;
|
|
744
|
+
}
|
|
745
|
+
alink->node = j;
|
|
746
|
+
alink->link = k;
|
|
747
|
+
alink->next = MSX.Adjlist[i];
|
|
748
|
+
MSX.Adjlist[i] = alink;
|
|
749
|
+
|
|
750
|
+
// Include link in end node j's list
|
|
751
|
+
alink = (struct Sadjlist*) malloc(sizeof(struct Sadjlist));
|
|
752
|
+
if (alink == NULL)
|
|
753
|
+
{
|
|
754
|
+
errcode = 101;
|
|
755
|
+
break;
|
|
756
|
+
}
|
|
757
|
+
alink->node = i;
|
|
758
|
+
alink->link = k;
|
|
759
|
+
alink->next = MSX.Adjlist[j];
|
|
760
|
+
MSX.Adjlist[j] = alink;
|
|
761
|
+
}
|
|
762
|
+
if (errcode) freeadjlists();
|
|
763
|
+
return errcode;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
|
|
767
|
+
void freeadjlists() //from epanet for node sorting in WQ routing
|
|
768
|
+
/*
|
|
769
|
+
**--------------------------------------------------------------
|
|
770
|
+
** Input: none
|
|
771
|
+
** Output: none
|
|
772
|
+
** Purpose: frees memory used for nodal adjacency lists
|
|
773
|
+
**--------------------------------------------------------------
|
|
774
|
+
*/
|
|
775
|
+
{
|
|
776
|
+
int i;
|
|
777
|
+
Padjlist alink;
|
|
778
|
+
|
|
779
|
+
if (MSX.Adjlist == NULL) return;
|
|
780
|
+
for (i = 0; i <= MSX.Nobjects[NODE]; i++)
|
|
781
|
+
{
|
|
782
|
+
for (alink = MSX.Adjlist[i]; alink != NULL; alink = MSX.Adjlist[i])
|
|
783
|
+
{
|
|
784
|
+
MSX.Adjlist[i] = alink->next;
|
|
785
|
+
free(alink);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
free(MSX.Adjlist);
|
|
789
|
+
MSX.Adjlist = NULL;
|
|
790
|
+
}
|
|
791
|
+
|