epanet-plus 0.0.1__cp312-cp312-macosx_10_13_x86_64.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.cpython-312-darwin.so +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 +6 -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
|
@@ -0,0 +1,1164 @@
|
|
|
1
|
+
/*******************************************************************************
|
|
2
|
+
** MODULE: MSXTOOLKIT.C
|
|
3
|
+
** PROJECT: EPANET-MSX
|
|
4
|
+
** DESCRIPTION: Contains the exportable set of functions that comprise the
|
|
5
|
+
** EPANET Multi-Species Extension toolkit.
|
|
6
|
+
** AUTHORS: see AUTHORS
|
|
7
|
+
** Copyright: see AUTHORS
|
|
8
|
+
** License: see LICENSE
|
|
9
|
+
** VERSION: 2.0.00
|
|
10
|
+
** LAST UPDATE: 04/14/2021
|
|
11
|
+
**
|
|
12
|
+
** These functions can be used in conjunction with the original EPANET
|
|
13
|
+
** toolkit functions to model water quality fate and transport of
|
|
14
|
+
** multiple interacting chemcial species within piping networks. See the
|
|
15
|
+
** MSXMAIN.C module for an example of how these functions were used to
|
|
16
|
+
** extend the original command line version of EPANET to include multiple
|
|
17
|
+
** chemical species. Consult the EPANET and EPANET-MSX Users Manuals for
|
|
18
|
+
** detailed descriptions of the input data file formats required by both
|
|
19
|
+
** the original EPANET and its multi-species extension.
|
|
20
|
+
*******************************************************************************/
|
|
21
|
+
|
|
22
|
+
#include <stdio.h>
|
|
23
|
+
#include <string.h>
|
|
24
|
+
#include <float.h>
|
|
25
|
+
#include <stdlib.h>
|
|
26
|
+
|
|
27
|
+
#include "msxtypes.h"
|
|
28
|
+
#include "msxutils.h"
|
|
29
|
+
#include "epanet2.h"
|
|
30
|
+
#include "epanetmsx.h"
|
|
31
|
+
|
|
32
|
+
// External variables
|
|
33
|
+
//--------------------
|
|
34
|
+
extern MSXproject MSX; // MSX project data
|
|
35
|
+
|
|
36
|
+
// Imported functions
|
|
37
|
+
//--------------------
|
|
38
|
+
int MSXproj_open(char *fname);
|
|
39
|
+
int MSXproj_close(void);
|
|
40
|
+
int MSXproj_addObject(int type, char *id, int n);
|
|
41
|
+
int MSXproj_findObject(int type, char *id);
|
|
42
|
+
char * MSXproj_findID(int type, char *id);
|
|
43
|
+
char * MSXproj_getErrmsg(int errcode);
|
|
44
|
+
int MSXqual_open(void);
|
|
45
|
+
int MSXqual_init(void);
|
|
46
|
+
int MSXqual_step(double *t, double *tleft);
|
|
47
|
+
int MSXqual_close(void);
|
|
48
|
+
double MSXqual_getNodeQual(int j, int m);
|
|
49
|
+
double MSXqual_getLinkQual(int k, int m);
|
|
50
|
+
int MSXrpt_write(void);
|
|
51
|
+
int MSXfile_save(FILE *f);
|
|
52
|
+
|
|
53
|
+
//=============================================================================
|
|
54
|
+
|
|
55
|
+
int MSXDLLEXPORT MSXENopen(const char *inpFile, const char *rptFile, const char *outFile)
|
|
56
|
+
/*
|
|
57
|
+
** Purpose:
|
|
58
|
+
** pass-thru to open the EPANET toolkit system
|
|
59
|
+
**
|
|
60
|
+
** Input:
|
|
61
|
+
** inpFile = name of the EPANET input file
|
|
62
|
+
** rptFile = name of the EPANET report file
|
|
63
|
+
** outFile = name of the EPANET binary file
|
|
64
|
+
**
|
|
65
|
+
** Returns:
|
|
66
|
+
** an error code (or 0 for no error);
|
|
67
|
+
*/
|
|
68
|
+
{
|
|
69
|
+
int err = 0;
|
|
70
|
+
err = ENopen(inpFile, rptFile, outFile);
|
|
71
|
+
return err;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
int MSXDLLEXPORT MSXENclose(void)
|
|
75
|
+
/*
|
|
76
|
+
** Purpose:
|
|
77
|
+
** pass-thru to open the EPANET toolkit system
|
|
78
|
+
**
|
|
79
|
+
*/
|
|
80
|
+
{
|
|
81
|
+
int err = 0;
|
|
82
|
+
err = ENclose();
|
|
83
|
+
return err;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
int MSXDLLEXPORT MSXopen(char *fname)
|
|
88
|
+
/*
|
|
89
|
+
** Purpose:
|
|
90
|
+
** opens the EPANET-MSX toolkit system.
|
|
91
|
+
**
|
|
92
|
+
** Input:
|
|
93
|
+
** fname = name of an MSX input file.
|
|
94
|
+
**
|
|
95
|
+
** Returns:
|
|
96
|
+
** an error code (or 0 for no error).
|
|
97
|
+
*/
|
|
98
|
+
{
|
|
99
|
+
int err = 0;
|
|
100
|
+
if (MSX.ProjectOpened) return(ERR_MSX_OPENED);
|
|
101
|
+
CALL(err, MSXproj_open(fname));
|
|
102
|
+
CALL(err, MSXqual_open());
|
|
103
|
+
|
|
104
|
+
if ( err )
|
|
105
|
+
{
|
|
106
|
+
ENwriteline(MSXproj_getErrmsg(err));
|
|
107
|
+
ENwriteline("");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return err;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
//=============================================================================
|
|
114
|
+
|
|
115
|
+
int MSXDLLEXPORT MSXsolveH()
|
|
116
|
+
/*
|
|
117
|
+
** Purpose:
|
|
118
|
+
** solves for system hydraulics which are written to a temporary file.
|
|
119
|
+
**
|
|
120
|
+
** Input:
|
|
121
|
+
** none.
|
|
122
|
+
**
|
|
123
|
+
** Returns:
|
|
124
|
+
** an error code (or 0 for no error).
|
|
125
|
+
*/
|
|
126
|
+
{
|
|
127
|
+
int err = 0;
|
|
128
|
+
|
|
129
|
+
// --- check that an MSX project was opened
|
|
130
|
+
|
|
131
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
132
|
+
|
|
133
|
+
// --- close & remove any existing hydraulics file
|
|
134
|
+
|
|
135
|
+
if ( MSX.HydFile.file )
|
|
136
|
+
{
|
|
137
|
+
fclose(MSX.HydFile.file);
|
|
138
|
+
MSX.HydFile.file = NULL;
|
|
139
|
+
}
|
|
140
|
+
if ( MSX.HydFile.mode == SCRATCH_FILE ) remove(MSX.HydFile.name);
|
|
141
|
+
|
|
142
|
+
// --- create a temporary hydraulics file
|
|
143
|
+
|
|
144
|
+
MSXutils_getTempName(MSX.HydFile.name);
|
|
145
|
+
MSX.HydFile.mode = SCRATCH_FILE; //(LR-10/05/08)
|
|
146
|
+
|
|
147
|
+
// --- use EPANET to solve for & save hydraulics results
|
|
148
|
+
|
|
149
|
+
CALL(err, ENsolveH());
|
|
150
|
+
CALL(err, ENsavehydfile(MSX.HydFile.name));
|
|
151
|
+
CALL(err, MSXusehydfile(MSX.HydFile.name));
|
|
152
|
+
return err;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
//=============================================================================
|
|
156
|
+
|
|
157
|
+
int MSXDLLEXPORT MSXusehydfile(char *fname)
|
|
158
|
+
/*
|
|
159
|
+
** Purpose:
|
|
160
|
+
** registers a hydraulics solution file with the MSX system.
|
|
161
|
+
**
|
|
162
|
+
** Input:
|
|
163
|
+
** fname = name of binary hydraulics results file.
|
|
164
|
+
**
|
|
165
|
+
** Returns:
|
|
166
|
+
** an error code (or 0 for no error).
|
|
167
|
+
*/
|
|
168
|
+
{
|
|
169
|
+
INT4 magic;
|
|
170
|
+
INT4 version;
|
|
171
|
+
INT4 n;
|
|
172
|
+
|
|
173
|
+
// --- check that an MSX project was opened
|
|
174
|
+
|
|
175
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
176
|
+
|
|
177
|
+
// --- close any existing hydraulics file
|
|
178
|
+
|
|
179
|
+
if ( MSX.HydFile.file )
|
|
180
|
+
{
|
|
181
|
+
fclose(MSX.HydFile.file);
|
|
182
|
+
if ( MSX.HydFile.mode == SCRATCH_FILE ) remove(MSX.HydFile.name); //(LR-10/05/08)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
// --- open hydraulics file
|
|
187
|
+
|
|
188
|
+
//MSX.HydFile.mode = USED_FILE;
|
|
189
|
+
MSX.HydFile.file = fopen(fname, "rb");
|
|
190
|
+
if (!MSX.HydFile.file) return ERR_OPEN_HYD_FILE;
|
|
191
|
+
|
|
192
|
+
// --- check that file is really a hydraulics file for current project
|
|
193
|
+
|
|
194
|
+
fread(&magic, sizeof(INT4), 1, MSX.HydFile.file);
|
|
195
|
+
if ( magic != MAGICNUMBER ) return ERR_READ_HYD_FILE;
|
|
196
|
+
fread(&version, sizeof(INT4), 1, MSX.HydFile.file);
|
|
197
|
+
fread(&n, sizeof(INT4), 1, MSX.HydFile.file);
|
|
198
|
+
if ( n != MSX.Nobjects[NODE] ) return ERR_READ_HYD_FILE;
|
|
199
|
+
fread(&n, sizeof(INT4), 1, MSX.HydFile.file);
|
|
200
|
+
if ( n != MSX.Nobjects[LINK] ) return ERR_READ_HYD_FILE;
|
|
201
|
+
fseek(MSX.HydFile.file, 3*sizeof(INT4), SEEK_CUR);
|
|
202
|
+
|
|
203
|
+
// --- read length of simulation period covered by file
|
|
204
|
+
|
|
205
|
+
fread(&n, sizeof(INT4), 1, MSX.HydFile.file);
|
|
206
|
+
MSX.Dur = INT64_C(1000) * n;
|
|
207
|
+
MSX.HydOffset = ftell(MSX.HydFile.file);
|
|
208
|
+
return 0;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
//=============================================================================
|
|
212
|
+
|
|
213
|
+
int MSXDLLEXPORT MSXsolveQ()
|
|
214
|
+
/*
|
|
215
|
+
** Purpose:
|
|
216
|
+
** runs a MSX water quality analysis over the entire simulation period.
|
|
217
|
+
**
|
|
218
|
+
** Input:
|
|
219
|
+
** none.
|
|
220
|
+
**
|
|
221
|
+
** Returns:
|
|
222
|
+
** an error code (or 0 for no error).
|
|
223
|
+
*/
|
|
224
|
+
{
|
|
225
|
+
double t, tleft = 0;
|
|
226
|
+
int err = 0;
|
|
227
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
228
|
+
CALL(err, MSXinit(1));
|
|
229
|
+
do CALL(err, MSXstep(&t, &tleft));
|
|
230
|
+
while (tleft > 0 && err == 0);
|
|
231
|
+
return err;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
//=============================================================================
|
|
235
|
+
|
|
236
|
+
int MSXDLLEXPORT MSXinit(int saveFlag)
|
|
237
|
+
/*
|
|
238
|
+
** Purpose:
|
|
239
|
+
** initializes a MSX water quality analysis.
|
|
240
|
+
**
|
|
241
|
+
** Input:
|
|
242
|
+
** saveFlag = 1 if results saved to binary file, 0 if not.
|
|
243
|
+
**
|
|
244
|
+
** Returns:
|
|
245
|
+
** an error code (or 0 for no error).
|
|
246
|
+
*/
|
|
247
|
+
{
|
|
248
|
+
int err= 0;
|
|
249
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
250
|
+
MSX.Saveflag = saveFlag;
|
|
251
|
+
err = MSXqual_init();
|
|
252
|
+
return err;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
//=============================================================================
|
|
256
|
+
|
|
257
|
+
int MSXDLLEXPORT MSXstep(double *t, double *tleft)
|
|
258
|
+
/*
|
|
259
|
+
** Purpose:
|
|
260
|
+
** advances the WQ simulation over a single time step.
|
|
261
|
+
**
|
|
262
|
+
** Input:
|
|
263
|
+
** none
|
|
264
|
+
**
|
|
265
|
+
** Output:
|
|
266
|
+
** *t = current simulation time at the end of the step (sec)
|
|
267
|
+
** *tleft = time left in the simulation (sec)
|
|
268
|
+
**
|
|
269
|
+
** Returns:
|
|
270
|
+
** an error code (or 0 for no error).
|
|
271
|
+
*/
|
|
272
|
+
{
|
|
273
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
274
|
+
return MSXqual_step(t, tleft);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
//=============================================================================
|
|
278
|
+
|
|
279
|
+
int MSXDLLEXPORT MSXsaveoutfile(char *fname)
|
|
280
|
+
/*
|
|
281
|
+
** Purpose:
|
|
282
|
+
** saves all results of the WQ simulation to a binary file.
|
|
283
|
+
**
|
|
284
|
+
** Input:
|
|
285
|
+
** fname = name of the binary results file.
|
|
286
|
+
**
|
|
287
|
+
** Returns:
|
|
288
|
+
** an error code (or 0 for no error).
|
|
289
|
+
*/
|
|
290
|
+
{
|
|
291
|
+
FILE *f;
|
|
292
|
+
int c;
|
|
293
|
+
|
|
294
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
295
|
+
if ( !MSX.OutFile.file ) return ERR_OPEN_OUT_FILE;
|
|
296
|
+
if ( (f = fopen(fname,"w+b") ) == NULL) return ERR_OPEN_OUT_FILE;
|
|
297
|
+
fseek(MSX.OutFile.file, 0, SEEK_SET);
|
|
298
|
+
while ( (c = fgetc(MSX.OutFile.file)) != EOF) fputc(c, f);
|
|
299
|
+
fclose(f);
|
|
300
|
+
return 0;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
//=============================================================================
|
|
304
|
+
|
|
305
|
+
int MSXDLLEXPORT MSXreport()
|
|
306
|
+
/*
|
|
307
|
+
** Purpose:
|
|
308
|
+
** writes requested WQ simulation results to a text file.
|
|
309
|
+
**
|
|
310
|
+
** Input:
|
|
311
|
+
** none
|
|
312
|
+
**
|
|
313
|
+
** Returns:
|
|
314
|
+
** an error code (or 0 for no error).
|
|
315
|
+
**
|
|
316
|
+
** Notes:
|
|
317
|
+
** Results are written to the EPANET report file unless a specific
|
|
318
|
+
** water quality report file is named in the [REPORT] section of
|
|
319
|
+
** the MSX input file.
|
|
320
|
+
*/
|
|
321
|
+
{
|
|
322
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
323
|
+
if ( MSX.Rptflag ) return MSXrpt_write();
|
|
324
|
+
else return 0;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
//=============================================================================
|
|
328
|
+
|
|
329
|
+
int MSXDLLEXPORT MSXclose()
|
|
330
|
+
/*
|
|
331
|
+
** Purpose:
|
|
332
|
+
** closes the EPANET-MSX toolkit system.
|
|
333
|
+
**
|
|
334
|
+
** Input:
|
|
335
|
+
** none
|
|
336
|
+
**
|
|
337
|
+
** Returns:
|
|
338
|
+
** an error code (or 0 for no error).
|
|
339
|
+
*/
|
|
340
|
+
{
|
|
341
|
+
MSXqual_close();
|
|
342
|
+
MSXproj_close();
|
|
343
|
+
return 0;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
//=============================================================================
|
|
347
|
+
|
|
348
|
+
int MSXDLLEXPORT MSXgetindex(int type, char *id, int *index)
|
|
349
|
+
/*
|
|
350
|
+
** Purpose:
|
|
351
|
+
** retrieves the index of a named MSX object.
|
|
352
|
+
**
|
|
353
|
+
** Input:
|
|
354
|
+
** type = object type code
|
|
355
|
+
** id = name of water quality species.
|
|
356
|
+
**
|
|
357
|
+
** Output:
|
|
358
|
+
** index = index (base 1) in the list of all objects of the given type.
|
|
359
|
+
**
|
|
360
|
+
** Returns:
|
|
361
|
+
** an error code (or 0 for no error).
|
|
362
|
+
*/
|
|
363
|
+
{
|
|
364
|
+
int i;
|
|
365
|
+
*index = 0;
|
|
366
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
367
|
+
switch(type)
|
|
368
|
+
{
|
|
369
|
+
case MSX_SPECIES: i = MSXproj_findObject(SPECIES, id); break;
|
|
370
|
+
case MSX_CONSTANT: i = MSXproj_findObject(CONSTANT, id); break;
|
|
371
|
+
case MSX_PARAMETER: i = MSXproj_findObject(PARAMETER, id); break;
|
|
372
|
+
case MSX_PATTERN: i = MSXproj_findObject(PATTERN, id); break;
|
|
373
|
+
default: return ERR_INVALID_OBJECT_TYPE;
|
|
374
|
+
}
|
|
375
|
+
if ( i < 1 ) return ERR_UNDEFINED_OBJECT_ID;
|
|
376
|
+
*index = i;
|
|
377
|
+
return 0;
|
|
378
|
+
}
|
|
379
|
+
//=============================================================================
|
|
380
|
+
|
|
381
|
+
int MSXDLLEXPORT MSXgetIDlen(int type, int index, int *len)
|
|
382
|
+
/*
|
|
383
|
+
** Purpose:
|
|
384
|
+
** retrieves the number of characters in the ID name of an MSX object.
|
|
385
|
+
**
|
|
386
|
+
** Input:
|
|
387
|
+
** type = object type code
|
|
388
|
+
** index = index (base 1) of the object in list of all objects of the
|
|
389
|
+
** given type.
|
|
390
|
+
**
|
|
391
|
+
** Output:
|
|
392
|
+
** len = number of characters in the object's ID name.
|
|
393
|
+
**
|
|
394
|
+
** Returns:
|
|
395
|
+
** an error code (or 0 for no error).
|
|
396
|
+
*/
|
|
397
|
+
{
|
|
398
|
+
int i;
|
|
399
|
+
*len = 0;
|
|
400
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
401
|
+
switch(type)
|
|
402
|
+
{
|
|
403
|
+
case MSX_SPECIES: i = SPECIES; break;
|
|
404
|
+
case MSX_CONSTANT: i = CONSTANT; break;
|
|
405
|
+
case MSX_PARAMETER: i = PARAMETER; break;
|
|
406
|
+
case MSX_PATTERN: i = PATTERN; break;
|
|
407
|
+
default: return ERR_INVALID_OBJECT_TYPE;
|
|
408
|
+
}
|
|
409
|
+
if ( index < 1 || index > MSX.Nobjects[i] ) return ERR_INVALID_OBJECT_INDEX;
|
|
410
|
+
switch(i)
|
|
411
|
+
{
|
|
412
|
+
case SPECIES: *len = (int) strlen(MSX.Species[index].id); break;
|
|
413
|
+
case CONSTANT: *len = (int) strlen(MSX.Const[index].id); break;
|
|
414
|
+
case PARAMETER: *len = (int) strlen(MSX.Param[index].id); break;
|
|
415
|
+
case PATTERN: *len = (int) strlen(MSX.Pattern[index].id); break;
|
|
416
|
+
}
|
|
417
|
+
return 0;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
//=============================================================================
|
|
421
|
+
|
|
422
|
+
int MSXDLLEXPORT MSXgetID(int type, int index, char *id, int len)
|
|
423
|
+
/*
|
|
424
|
+
** Purpose:
|
|
425
|
+
** retrieves the name of an object given its index.
|
|
426
|
+
**
|
|
427
|
+
** Input:
|
|
428
|
+
** type = object type code
|
|
429
|
+
** index = index (base 1) of the object in list of all objects of the
|
|
430
|
+
** given type
|
|
431
|
+
** len = maximum number of characters that id can hold.
|
|
432
|
+
**
|
|
433
|
+
** Output:
|
|
434
|
+
** id = name of the object.
|
|
435
|
+
**
|
|
436
|
+
** Returns:
|
|
437
|
+
** an error code (or 0 for no error).
|
|
438
|
+
*/
|
|
439
|
+
{
|
|
440
|
+
int i;
|
|
441
|
+
strcpy(id, "");
|
|
442
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
443
|
+
switch(type)
|
|
444
|
+
{
|
|
445
|
+
case MSX_SPECIES: i = SPECIES; break;
|
|
446
|
+
case MSX_CONSTANT: i = CONSTANT; break;
|
|
447
|
+
case MSX_PARAMETER: i = PARAMETER; break;
|
|
448
|
+
case MSX_PATTERN: i = PATTERN; break;
|
|
449
|
+
default: return ERR_INVALID_OBJECT_TYPE;
|
|
450
|
+
}
|
|
451
|
+
if ( index < 1 || index > MSX.Nobjects[i] ) return ERR_INVALID_OBJECT_INDEX;
|
|
452
|
+
switch(i)
|
|
453
|
+
{
|
|
454
|
+
case SPECIES: strncpy(id, MSX.Species[index].id, len); break;
|
|
455
|
+
case CONSTANT: strncpy(id, MSX.Const[index].id, len); break;
|
|
456
|
+
case PARAMETER: strncpy(id, MSX.Param[index].id, len); break;
|
|
457
|
+
case PATTERN: strncpy(id, MSX.Pattern[index].id, len); break;
|
|
458
|
+
}
|
|
459
|
+
id[len] = '\0'; //(L. Rossman - 11/01/10)
|
|
460
|
+
return 0;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
//=============================================================================
|
|
464
|
+
|
|
465
|
+
int MSXDLLEXPORT MSXgetcount(int type, int *count)
|
|
466
|
+
/*
|
|
467
|
+
** Purpose:
|
|
468
|
+
** retrieves the number of objects of a specific type.
|
|
469
|
+
**
|
|
470
|
+
** Input:
|
|
471
|
+
** type = object type code
|
|
472
|
+
**
|
|
473
|
+
** Output:
|
|
474
|
+
** count = number of objects of the given type.
|
|
475
|
+
**
|
|
476
|
+
** Returns:
|
|
477
|
+
** an error code (or 0 for no error).
|
|
478
|
+
*/
|
|
479
|
+
{
|
|
480
|
+
*count = 0;
|
|
481
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
482
|
+
switch(type)
|
|
483
|
+
{
|
|
484
|
+
case MSX_SPECIES: *count = MSX.Nobjects[SPECIES]; break;
|
|
485
|
+
case MSX_CONSTANT: *count = MSX.Nobjects[CONSTANT]; break;
|
|
486
|
+
case MSX_PARAMETER: *count = MSX.Nobjects[PARAMETER]; break;
|
|
487
|
+
case MSX_PATTERN: *count = MSX.Nobjects[PATTERN]; break;
|
|
488
|
+
default: return ERR_INVALID_OBJECT_TYPE;
|
|
489
|
+
}
|
|
490
|
+
return 0;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
//=============================================================================
|
|
494
|
+
|
|
495
|
+
int MSXDLLEXPORT MSXgetspecies(int index, int *type, char *units,
|
|
496
|
+
double *aTol, double * rTol)
|
|
497
|
+
/*
|
|
498
|
+
** Purpose:
|
|
499
|
+
** retrieves the attributes of a chemical species.
|
|
500
|
+
**
|
|
501
|
+
** Input:
|
|
502
|
+
** index = index (base 1) of the species in the list of all species.
|
|
503
|
+
**
|
|
504
|
+
** Output:
|
|
505
|
+
** type = MSX_BULK (0) for a bulk flow species or MSX_WALL (1) for a
|
|
506
|
+
** surface species;
|
|
507
|
+
** units = character string containing the mass units defined for the species -
|
|
508
|
+
** must be sized in the calling program to accept up to 15 bytes
|
|
509
|
+
** plus a null termination character
|
|
510
|
+
** aTol = absolute concentration tolerance (concentration units);
|
|
511
|
+
** rTol = relative concentration tolerance (unitless)
|
|
512
|
+
**
|
|
513
|
+
** Returns:
|
|
514
|
+
** an error code (or 0 for no error).
|
|
515
|
+
*/
|
|
516
|
+
{
|
|
517
|
+
*type = 0;
|
|
518
|
+
strcpy(units, "");
|
|
519
|
+
*aTol = 0.0;
|
|
520
|
+
*rTol = 0.0;
|
|
521
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
522
|
+
if ( index < 1 || index > MSX.Nobjects[SPECIES] ) return ERR_INVALID_OBJECT_INDEX;
|
|
523
|
+
*type = MSX.Species[index].type;
|
|
524
|
+
strncpy(units, MSX.Species[index].units, MAXUNITS);
|
|
525
|
+
*aTol = MSX.Species[index].aTol;
|
|
526
|
+
*rTol = MSX.Species[index].rTol;
|
|
527
|
+
return 0;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
//=============================================================================
|
|
531
|
+
|
|
532
|
+
int MSXDLLEXPORT MSXgetconstant(int index, double *value)
|
|
533
|
+
/*
|
|
534
|
+
** Purpose:
|
|
535
|
+
** retrieves the value of a particular reaction constant.
|
|
536
|
+
**
|
|
537
|
+
** Input:
|
|
538
|
+
** index = index (base 1) of the constant in the list of all constants.
|
|
539
|
+
**
|
|
540
|
+
** Output:
|
|
541
|
+
** value = value assigned to the constant.
|
|
542
|
+
**
|
|
543
|
+
** Returns:
|
|
544
|
+
** an error code (or 0 for no error).
|
|
545
|
+
*/
|
|
546
|
+
{
|
|
547
|
+
*value = 0.0;
|
|
548
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
549
|
+
if ( index < 1 || index > MSX.Nobjects[CONSTANT] ) return ERR_INVALID_OBJECT_INDEX;
|
|
550
|
+
*value = MSX.Const[index].value;
|
|
551
|
+
return 0;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
//=============================================================================
|
|
555
|
+
|
|
556
|
+
int MSXDLLEXPORT MSXgetparameter(int type, int index, int param, double *value)
|
|
557
|
+
/*
|
|
558
|
+
** Purpose:
|
|
559
|
+
** retrieves the value of a particular reaction parameter for a given pipe
|
|
560
|
+
** or tank within the pipe network.
|
|
561
|
+
**
|
|
562
|
+
** Input:
|
|
563
|
+
** type = MSX_NODE (0) for a node or MSX_LINK (1) for a link;
|
|
564
|
+
** index = index (base 1) assigned to the node or link;
|
|
565
|
+
** param = index (base 1) assigned to the reaction parameter.
|
|
566
|
+
**
|
|
567
|
+
** Output:
|
|
568
|
+
** value = value assigned to the parameter.
|
|
569
|
+
**
|
|
570
|
+
** Returns:
|
|
571
|
+
** an error code (or 0 for no error).
|
|
572
|
+
*/
|
|
573
|
+
{
|
|
574
|
+
int j;
|
|
575
|
+
*value = 0.0;
|
|
576
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
577
|
+
if ( param < 1 || param > MSX.Nobjects[PARAMETER] ) return ERR_INVALID_OBJECT_INDEX;
|
|
578
|
+
if ( type == MSX_NODE )
|
|
579
|
+
{
|
|
580
|
+
if ( index < 1 || index > MSX.Nobjects[NODE] ) return ERR_INVALID_OBJECT_INDEX;
|
|
581
|
+
j = MSX.Node[index].tank;
|
|
582
|
+
if ( j > 0 ) *value = MSX.Tank[j].param[param];
|
|
583
|
+
}
|
|
584
|
+
else if ( type == MSX_LINK )
|
|
585
|
+
{
|
|
586
|
+
if ( index < 1 || index > MSX.Nobjects[LINK] ) return ERR_INVALID_OBJECT_INDEX;
|
|
587
|
+
*value = MSX.Link[index].param[param];
|
|
588
|
+
}
|
|
589
|
+
else return ERR_INVALID_OBJECT_TYPE;
|
|
590
|
+
return 0;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
//=============================================================================
|
|
594
|
+
|
|
595
|
+
int MSXDLLEXPORT MSXgetsource(int node, int species, int *type, double *level,
|
|
596
|
+
int *pat)
|
|
597
|
+
/*
|
|
598
|
+
** Purpose:
|
|
599
|
+
** retrieves information on any external source of a particular chemical
|
|
600
|
+
** species assigned to a specific node of the pipe network.
|
|
601
|
+
**
|
|
602
|
+
** Input:
|
|
603
|
+
** node = index number (base 1) assigned to the node of interest;
|
|
604
|
+
** species = index number (base 1) of the species of interest;
|
|
605
|
+
**
|
|
606
|
+
** Output:
|
|
607
|
+
** type = one of the following of external source type codes:
|
|
608
|
+
** MSX_NOSOURCE = -1 for no source,
|
|
609
|
+
** MSX_CONCEN = 0 for a concentration source,
|
|
610
|
+
** MSX_MASS = 1 for a mass booster source,
|
|
611
|
+
** MSX_SETPOINT = 2 for a setpoint source,
|
|
612
|
+
** MSX_FLOWPACED = 3 for a flow paced source;
|
|
613
|
+
** level = the baseline concentration (or mass flow rate) of the species
|
|
614
|
+
** in the source;
|
|
615
|
+
** pat = the index of the time pattern assigned to the species at the source
|
|
616
|
+
**
|
|
617
|
+
** Returns:
|
|
618
|
+
** an error code (or 0 for no error).
|
|
619
|
+
*/
|
|
620
|
+
{
|
|
621
|
+
Psource source;
|
|
622
|
+
*type = MSX_NOSOURCE;
|
|
623
|
+
*level = 0.0;
|
|
624
|
+
*pat = 0;
|
|
625
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
626
|
+
if ( node < 1 || node > MSX.Nobjects[NODE] ) return ERR_INVALID_OBJECT_INDEX;
|
|
627
|
+
if ( species < 1 || species > MSX.Nobjects[SPECIES] ) return ERR_INVALID_OBJECT_INDEX;
|
|
628
|
+
source = MSX.Node[node].sources;
|
|
629
|
+
while ( source )
|
|
630
|
+
{
|
|
631
|
+
if ( source->species == species )
|
|
632
|
+
{
|
|
633
|
+
*type = source->type;
|
|
634
|
+
*level = source->c0;
|
|
635
|
+
*pat = source->pat;
|
|
636
|
+
break;
|
|
637
|
+
}
|
|
638
|
+
source = source->next;
|
|
639
|
+
}
|
|
640
|
+
return 0;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
//=============================================================================
|
|
644
|
+
|
|
645
|
+
int MSXDLLEXPORT MSXgetpatternlen(int pat, int *len)
|
|
646
|
+
/*
|
|
647
|
+
** Purpose:
|
|
648
|
+
** retrieves the number of time periods within a source time pattern.
|
|
649
|
+
**
|
|
650
|
+
** Input:
|
|
651
|
+
** pat = the index number (base 1) of the time pattern;
|
|
652
|
+
**
|
|
653
|
+
** Output:
|
|
654
|
+
** len = the number of time periods that appear in the pattern.
|
|
655
|
+
**
|
|
656
|
+
** Returns:
|
|
657
|
+
** an error code (or 0 for no error).
|
|
658
|
+
*/
|
|
659
|
+
{
|
|
660
|
+
*len = 0;
|
|
661
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
662
|
+
if ( pat < 1 || pat > MSX.Nobjects[PATTERN] ) return ERR_INVALID_OBJECT_INDEX;
|
|
663
|
+
*len = MSX.Pattern[pat].length;
|
|
664
|
+
return 0;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
//=============================================================================
|
|
668
|
+
|
|
669
|
+
int MSXDLLEXPORT MSXgetpatternvalue(int pat, int period, double *value)
|
|
670
|
+
/*
|
|
671
|
+
** Purpose:
|
|
672
|
+
** retrieves the multiplier at a specific time period for a given
|
|
673
|
+
** source time pattern.
|
|
674
|
+
**
|
|
675
|
+
** Input:
|
|
676
|
+
** pat = the index number (base 1) of the time pattern;
|
|
677
|
+
** period = the index of the time period (starting from 1) whose
|
|
678
|
+
** multiplier is being sought;
|
|
679
|
+
**
|
|
680
|
+
** Output:
|
|
681
|
+
** value = the value of the pattern's multiplier in the desired period.
|
|
682
|
+
**
|
|
683
|
+
** Returns:
|
|
684
|
+
** an error code (or 0 for no error).
|
|
685
|
+
*/
|
|
686
|
+
{
|
|
687
|
+
int n = 1;
|
|
688
|
+
*value = 0.0;
|
|
689
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
690
|
+
if ( pat < 1 || pat > MSX.Nobjects[PATTERN] ) return ERR_INVALID_OBJECT_INDEX;
|
|
691
|
+
if ( period <= MSX.Pattern[pat].length )
|
|
692
|
+
{
|
|
693
|
+
MSX.Pattern[pat].current = MSX.Pattern[pat].first;
|
|
694
|
+
while ( MSX.Pattern[pat].current )
|
|
695
|
+
{
|
|
696
|
+
if ( n == period )
|
|
697
|
+
{
|
|
698
|
+
*value = MSX.Pattern[pat].current->value;
|
|
699
|
+
return 0;
|
|
700
|
+
}
|
|
701
|
+
MSX.Pattern[pat].current = MSX.Pattern[pat].current->next;
|
|
702
|
+
n++;
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
return 0;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
//=============================================================================
|
|
709
|
+
|
|
710
|
+
int MSXDLLEXPORT MSXgetinitqual(int type, int index, int species, double *value)
|
|
711
|
+
/*
|
|
712
|
+
** Purpose:
|
|
713
|
+
** retrieves the initial concentration of a particular chemical species
|
|
714
|
+
** assigned to a specific node or link of the pipe network.
|
|
715
|
+
**
|
|
716
|
+
** Input:
|
|
717
|
+
** type = MSX_NODE (0) for a node or MSX_LINK (1) for a link;
|
|
718
|
+
** index = index (base 1) of the node or link of interest;
|
|
719
|
+
** species = index (base 1) of the species of interest.
|
|
720
|
+
**
|
|
721
|
+
** Output:
|
|
722
|
+
** value = initial concentration of the species at the node or link.
|
|
723
|
+
**
|
|
724
|
+
** Returns:
|
|
725
|
+
** an error code (or 0 for no error).
|
|
726
|
+
*/
|
|
727
|
+
{
|
|
728
|
+
*value = 0.0;
|
|
729
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
730
|
+
if ( species < 1 || species > MSX.Nobjects[SPECIES] ) return ERR_INVALID_OBJECT_INDEX;
|
|
731
|
+
if ( type == MSX_NODE )
|
|
732
|
+
{
|
|
733
|
+
if ( index < 1 || index > MSX.Nobjects[NODE] ) return ERR_INVALID_OBJECT_INDEX;
|
|
734
|
+
*value = MSX.Node[index].c0[species];
|
|
735
|
+
}
|
|
736
|
+
else if ( type == MSX_LINK )
|
|
737
|
+
{
|
|
738
|
+
if ( index < 1 || index > MSX.Nobjects[LINK] ) return ERR_INVALID_OBJECT_INDEX;
|
|
739
|
+
*value = MSX.Link[index].c0[species];
|
|
740
|
+
}
|
|
741
|
+
else return ERR_INVALID_OBJECT_TYPE;
|
|
742
|
+
return 0;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
//=============================================================================
|
|
746
|
+
|
|
747
|
+
int MSXDLLEXPORT MSXgetqual(int type, int index, int species, double *value)
|
|
748
|
+
/*
|
|
749
|
+
** Purpose:
|
|
750
|
+
** retrieves the current concentration of a species at a particular node
|
|
751
|
+
** or link of the pipe network.
|
|
752
|
+
**
|
|
753
|
+
** Input:
|
|
754
|
+
** type = MSX_NODE (0) for a node or MSX_LINK (1) for a link;
|
|
755
|
+
** index = index (base 1) of the node or link of interest;.
|
|
756
|
+
** species = index (base 1) of the species of interest.
|
|
757
|
+
**
|
|
758
|
+
** Output:
|
|
759
|
+
** value = species concentration at the node or link.
|
|
760
|
+
**
|
|
761
|
+
** Returns:
|
|
762
|
+
** an error code (or 0 for no error).
|
|
763
|
+
*/
|
|
764
|
+
{
|
|
765
|
+
*value = 0.0;
|
|
766
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
767
|
+
if ( species < 1 || species > MSX.Nobjects[SPECIES] ) return ERR_INVALID_OBJECT_INDEX;
|
|
768
|
+
if ( type == MSX_NODE )
|
|
769
|
+
{
|
|
770
|
+
if ( index < 1 || index > MSX.Nobjects[NODE] ) return ERR_INVALID_OBJECT_INDEX;
|
|
771
|
+
*value = MSXqual_getNodeQual(index, species);
|
|
772
|
+
}
|
|
773
|
+
else if ( type == MSX_LINK )
|
|
774
|
+
{
|
|
775
|
+
if ( index < 1 || index > MSX.Nobjects[LINK] ) return ERR_INVALID_OBJECT_INDEX;
|
|
776
|
+
*value = MSXqual_getLinkQual(index, species);
|
|
777
|
+
}
|
|
778
|
+
else return ERR_INVALID_OBJECT_TYPE;
|
|
779
|
+
return 0;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
//=============================================================================
|
|
783
|
+
|
|
784
|
+
int MSXDLLEXPORT MSXgeterror(int code, char *msg, int len)
|
|
785
|
+
/*
|
|
786
|
+
** Purpose:
|
|
787
|
+
** retrieves text of an error message.
|
|
788
|
+
**
|
|
789
|
+
** Input:
|
|
790
|
+
** code = error code number
|
|
791
|
+
** len = maximum length of string errmsg.
|
|
792
|
+
**
|
|
793
|
+
** Output:
|
|
794
|
+
** msg = text of error message.
|
|
795
|
+
**
|
|
796
|
+
** Returns:
|
|
797
|
+
** an error code which is always 0.
|
|
798
|
+
*/
|
|
799
|
+
{
|
|
800
|
+
strncpy(msg, MSXproj_getErrmsg(code), len);
|
|
801
|
+
return 0;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
//=============================================================================
|
|
805
|
+
|
|
806
|
+
int MSXDLLEXPORT MSXsetconstant(int index, double value)
|
|
807
|
+
/*
|
|
808
|
+
** Purpose:
|
|
809
|
+
** assigns a new value to a specific reaction constant.
|
|
810
|
+
**
|
|
811
|
+
** Input:
|
|
812
|
+
** index = index (base 1) of the constant in the list of all constants;
|
|
813
|
+
** value = the new value to be assigned to the constant.
|
|
814
|
+
**
|
|
815
|
+
** Output:
|
|
816
|
+
** none.
|
|
817
|
+
**
|
|
818
|
+
** Returns:
|
|
819
|
+
** an error code or 0 for no error.
|
|
820
|
+
*/
|
|
821
|
+
{
|
|
822
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
823
|
+
if ( index < 1 || index > MSX.Nobjects[CONSTANT] ) return ERR_INVALID_OBJECT_INDEX;
|
|
824
|
+
MSX.Const[index].value = value;
|
|
825
|
+
return 0;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
//=============================================================================
|
|
829
|
+
|
|
830
|
+
int MSXDLLEXPORT MSXsetparameter(int type, int index, int param, double value)
|
|
831
|
+
/*
|
|
832
|
+
** Purpose:
|
|
833
|
+
** assigns a value to a particular reaction parameter for a given pipe
|
|
834
|
+
** or tank within the pipe network.
|
|
835
|
+
**
|
|
836
|
+
** Input:
|
|
837
|
+
** type = MSX_NODE (0) for a node or MSX_LINK (1) for a link;
|
|
838
|
+
** index = index (base 1) assigned to the node or link;
|
|
839
|
+
** param = index (base 1) assigned to the reaction parameter;
|
|
840
|
+
** value = value to be assigned to the parameter.
|
|
841
|
+
**
|
|
842
|
+
** Output:
|
|
843
|
+
** none.
|
|
844
|
+
**
|
|
845
|
+
** Returns:
|
|
846
|
+
** an error code or 0 for no error.
|
|
847
|
+
*/
|
|
848
|
+
{
|
|
849
|
+
int j;
|
|
850
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
851
|
+
if ( param < 1 || param > MSX.Nobjects[PARAMETER] ) return ERR_INVALID_OBJECT_INDEX;
|
|
852
|
+
if ( type == MSX_NODE )
|
|
853
|
+
{
|
|
854
|
+
if ( index < 1 || index > MSX.Nobjects[NODE] ) return ERR_INVALID_OBJECT_INDEX;
|
|
855
|
+
j = MSX.Node[index].tank;
|
|
856
|
+
if ( j > 0 ) MSX.Tank[j].param[param] = value;
|
|
857
|
+
}
|
|
858
|
+
else if ( type == MSX_LINK )
|
|
859
|
+
{
|
|
860
|
+
if ( index < 1 || index > MSX.Nobjects[LINK] ) return ERR_INVALID_OBJECT_INDEX;
|
|
861
|
+
MSX.Link[index].param[param] = value;
|
|
862
|
+
}
|
|
863
|
+
else return ERR_INVALID_OBJECT_TYPE;
|
|
864
|
+
return 0;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
//=============================================================================
|
|
868
|
+
|
|
869
|
+
int MSXDLLEXPORT MSXsetinitqual(int type, int index, int species, double value)
|
|
870
|
+
/*
|
|
871
|
+
** Purpose:
|
|
872
|
+
** assigns an initial concentration of a particular chemical species
|
|
873
|
+
** to a specific node or link of the pipe network.
|
|
874
|
+
**
|
|
875
|
+
** Input:
|
|
876
|
+
** type = MSX_NODE (0) for a node or MSX_LINK (1) for a link;
|
|
877
|
+
** index = index (base 1) of the node or link of interest;
|
|
878
|
+
** species = index (base 1) of the species of interest.
|
|
879
|
+
** value = initial concentration of the species at the node or link.
|
|
880
|
+
**
|
|
881
|
+
** Output:
|
|
882
|
+
** none.
|
|
883
|
+
**
|
|
884
|
+
** Returns:
|
|
885
|
+
** an error code (or 0 for no error).
|
|
886
|
+
*/
|
|
887
|
+
{
|
|
888
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
889
|
+
if ( species < 1 || species > MSX.Nobjects[SPECIES] ) return ERR_INVALID_OBJECT_INDEX;
|
|
890
|
+
if ( type == MSX_NODE )
|
|
891
|
+
{
|
|
892
|
+
if ( index < 1 || index > MSX.Nobjects[NODE] ) return ERR_INVALID_OBJECT_INDEX;
|
|
893
|
+
if ( MSX.Species[species].type == BULK )
|
|
894
|
+
MSX.Node[index].c0[species] = value;
|
|
895
|
+
}
|
|
896
|
+
else if ( type == MSX_LINK )
|
|
897
|
+
{
|
|
898
|
+
if ( index < 1 || index > MSX.Nobjects[LINK] ) return ERR_INVALID_OBJECT_INDEX;
|
|
899
|
+
MSX.Link[index].c0[species] = value;
|
|
900
|
+
}
|
|
901
|
+
else return ERR_INVALID_OBJECT_TYPE;
|
|
902
|
+
return 0;
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
//=============================================================================
|
|
906
|
+
|
|
907
|
+
int MSXDLLEXPORT MSXsetsource(int node, int species, int type, double level,
|
|
908
|
+
int pat)
|
|
909
|
+
/*
|
|
910
|
+
** Purpose:
|
|
911
|
+
** sets the attributes of an external source of a particular chemical
|
|
912
|
+
** species to a specific node of the pipe network.
|
|
913
|
+
**
|
|
914
|
+
** Input:
|
|
915
|
+
** node = index number (base 1) assigned to the node of interest;
|
|
916
|
+
** species = index number (base 1) of the species of interest;
|
|
917
|
+
** type = one of the following of external source type codes:
|
|
918
|
+
** MSX_NOSOURCE = -1 for no source,
|
|
919
|
+
** MSX_CONCEN = 0 for a concentration source,
|
|
920
|
+
** MSX_MASS = 1 for a mass booster source,
|
|
921
|
+
** MSX_SETPOINT = 2 for a setpoint source,
|
|
922
|
+
** MSX_FLOWPACED = 3 for a flow paced source;
|
|
923
|
+
** level = the baseline concentration (or mass flow rate) of the species
|
|
924
|
+
** in the source;
|
|
925
|
+
** pat = the index of the time pattern assigned to the species at the source
|
|
926
|
+
**
|
|
927
|
+
** Output:
|
|
928
|
+
** none.
|
|
929
|
+
**
|
|
930
|
+
** Returns:
|
|
931
|
+
** an error code (or 0 for no error).
|
|
932
|
+
*/
|
|
933
|
+
{
|
|
934
|
+
Psource source;
|
|
935
|
+
|
|
936
|
+
// --- check for valid source parameters
|
|
937
|
+
|
|
938
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
939
|
+
if ( node < 1 || node > MSX.Nobjects[NODE] ) return ERR_INVALID_OBJECT_INDEX;
|
|
940
|
+
if ( species < 1 || species > MSX.Nobjects[SPECIES] ) return ERR_INVALID_OBJECT_INDEX;
|
|
941
|
+
if ( pat > MSX.Nobjects[PATTERN] ) return ERR_INVALID_OBJECT_INDEX;
|
|
942
|
+
if ( pat < 0 ) pat = 0;
|
|
943
|
+
if ( type < MSX_NOSOURCE ||
|
|
944
|
+
type > MSX_FLOWPACED ) return ERR_INVALID_OBJECT_PARAMS;
|
|
945
|
+
if ( MSX.Species[species].type != BULK ) return ERR_INVALID_OBJECT_PARAMS;
|
|
946
|
+
if ( level < 0.0 ) return ERR_INVALID_OBJECT_PARAMS;
|
|
947
|
+
|
|
948
|
+
// --- check if a source for this species already exists at the node
|
|
949
|
+
|
|
950
|
+
source = MSX.Node[node].sources;
|
|
951
|
+
while ( source )
|
|
952
|
+
{
|
|
953
|
+
if ( source->species == species ) break;
|
|
954
|
+
source = source->next;
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
// --- if no current source exists then create a new one
|
|
958
|
+
|
|
959
|
+
if ( source == NULL )
|
|
960
|
+
{
|
|
961
|
+
source = (struct Ssource *) malloc(sizeof(struct Ssource));
|
|
962
|
+
if ( source == NULL ) return ERR_MEMORY;
|
|
963
|
+
source->next = MSX.Node[node].sources;
|
|
964
|
+
MSX.Node[node].sources = source;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
// --- assign parameters to the source
|
|
968
|
+
|
|
969
|
+
source->type = (char)type;
|
|
970
|
+
source->species = species;
|
|
971
|
+
source->c0 = level;
|
|
972
|
+
source->pat = pat;
|
|
973
|
+
return 0;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
//=============================================================================
|
|
977
|
+
|
|
978
|
+
int MSXDLLEXPORT MSXsetpatternvalue(int pat, int period, double value)
|
|
979
|
+
/*
|
|
980
|
+
** Purpose:
|
|
981
|
+
** assigns a new value to the multiplier for a specific time period in
|
|
982
|
+
** a given time pattern.
|
|
983
|
+
**
|
|
984
|
+
** Input:
|
|
985
|
+
** pat = the index number (base 1) of the time pattern;
|
|
986
|
+
** period = the time period (starting from 1) whose multiplier is
|
|
987
|
+
** being replaced;
|
|
988
|
+
** value = the new value of the pattern's multiplier in the desired period.
|
|
989
|
+
**
|
|
990
|
+
** Output:
|
|
991
|
+
** none.
|
|
992
|
+
**
|
|
993
|
+
** Returns:
|
|
994
|
+
** an error code (or 0 for no error).
|
|
995
|
+
*/
|
|
996
|
+
{
|
|
997
|
+
int n = 1;
|
|
998
|
+
|
|
999
|
+
// --- check that pattern & period exists
|
|
1000
|
+
|
|
1001
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
1002
|
+
if ( pat < 1 || pat > MSX.Nobjects[PATTERN] ) return ERR_INVALID_OBJECT_INDEX;
|
|
1003
|
+
if ( period <= 0 || period > MSX.Pattern[pat].length )
|
|
1004
|
+
return ERR_INVALID_OBJECT_PARAMS;
|
|
1005
|
+
|
|
1006
|
+
// --- find desired time period in the pattern
|
|
1007
|
+
|
|
1008
|
+
MSX.Pattern[pat].current = MSX.Pattern[pat].first;
|
|
1009
|
+
while ( MSX.Pattern[pat].current )
|
|
1010
|
+
{
|
|
1011
|
+
if ( n == period )
|
|
1012
|
+
{
|
|
1013
|
+
MSX.Pattern[pat].current->value = value;
|
|
1014
|
+
return 0;
|
|
1015
|
+
}
|
|
1016
|
+
MSX.Pattern[pat].current = MSX.Pattern[pat].current->next;
|
|
1017
|
+
n++;
|
|
1018
|
+
}
|
|
1019
|
+
return 0;
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
//=============================================================================
|
|
1023
|
+
|
|
1024
|
+
int MSXDLLEXPORT MSXaddpattern(char *id)
|
|
1025
|
+
/*
|
|
1026
|
+
** Purpose:
|
|
1027
|
+
** adds a new MSX time pattern to the project.
|
|
1028
|
+
**
|
|
1029
|
+
** Input:
|
|
1030
|
+
** id = C-style character string with the ID name of the new pattern.
|
|
1031
|
+
**
|
|
1032
|
+
** Output:
|
|
1033
|
+
** none.
|
|
1034
|
+
**
|
|
1035
|
+
** Returns:
|
|
1036
|
+
** an error code (or 0 for no error).
|
|
1037
|
+
**
|
|
1038
|
+
** Notes:
|
|
1039
|
+
** the new pattern is appended to the end of the existing patterns.
|
|
1040
|
+
*/
|
|
1041
|
+
{
|
|
1042
|
+
int i, n;
|
|
1043
|
+
Spattern *tmpPat;
|
|
1044
|
+
|
|
1045
|
+
// --- check if a pattern with same id already exists
|
|
1046
|
+
|
|
1047
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
1048
|
+
if ( MSXproj_findObject(PATTERN, id) >= 1 ) return ERR_INVALID_OBJECT_PARAMS;
|
|
1049
|
+
|
|
1050
|
+
// --- allocate memory for a new array of patterns
|
|
1051
|
+
|
|
1052
|
+
n = MSX.Nobjects[PATTERN] + 1;
|
|
1053
|
+
tmpPat = (Spattern *) calloc((size_t)n+1, sizeof(Spattern));
|
|
1054
|
+
if ( tmpPat == NULL ) return ERR_MEMORY;
|
|
1055
|
+
|
|
1056
|
+
// --- copy contents of old pattern array to new one
|
|
1057
|
+
|
|
1058
|
+
for (i=1; i<=MSX.Nobjects[PATTERN]; i++)
|
|
1059
|
+
{
|
|
1060
|
+
tmpPat[i].id = MSX.Pattern[i].id;
|
|
1061
|
+
tmpPat[i].length = MSX.Pattern[i].length;
|
|
1062
|
+
tmpPat[i].first = MSX.Pattern[i].first;
|
|
1063
|
+
tmpPat[i].current = MSX.Pattern[i].current;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
// --- add info for the new pattern
|
|
1067
|
+
|
|
1068
|
+
if ( MSXproj_addObject(PATTERN, id, n) < 0 )
|
|
1069
|
+
{
|
|
1070
|
+
free(tmpPat);
|
|
1071
|
+
return ERR_MEMORY;
|
|
1072
|
+
}
|
|
1073
|
+
tmpPat[n].id = MSXproj_findID(PATTERN, id);
|
|
1074
|
+
tmpPat[n].length = 0;
|
|
1075
|
+
tmpPat[n].first = NULL;
|
|
1076
|
+
tmpPat[n].current = NULL;
|
|
1077
|
+
|
|
1078
|
+
// --- replace old pattern array with new one
|
|
1079
|
+
|
|
1080
|
+
FREE(MSX.Pattern);
|
|
1081
|
+
MSX.Pattern = tmpPat;
|
|
1082
|
+
MSX.Nobjects[PATTERN]++;
|
|
1083
|
+
return 0;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
//=============================================================================
|
|
1087
|
+
|
|
1088
|
+
int MSXDLLEXPORT MSXsetpattern(int pat, double mult[], int len)
|
|
1089
|
+
/*
|
|
1090
|
+
** Purpose:
|
|
1091
|
+
** Assigns a new set of multipliers to a given time pattern.
|
|
1092
|
+
**
|
|
1093
|
+
** Input:
|
|
1094
|
+
** pat = the index number (base 1) of the time pattern;
|
|
1095
|
+
** mult[] = an array of multiplier values (base 0) to replace those
|
|
1096
|
+
** previously used by the pattern;
|
|
1097
|
+
** len = the number of entries in the multiplier array mult.
|
|
1098
|
+
**
|
|
1099
|
+
** Output:
|
|
1100
|
+
** none.
|
|
1101
|
+
**
|
|
1102
|
+
** Returns:
|
|
1103
|
+
** an error code (or 0 for no error).
|
|
1104
|
+
*/
|
|
1105
|
+
{
|
|
1106
|
+
int i;
|
|
1107
|
+
SnumList *listItem;
|
|
1108
|
+
|
|
1109
|
+
// --- check that pattern exists
|
|
1110
|
+
|
|
1111
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
1112
|
+
if ( pat < 1 || pat > MSX.Nobjects[PATTERN] ) return ERR_INVALID_OBJECT_INDEX;
|
|
1113
|
+
if ( len < 0) len = 0;
|
|
1114
|
+
|
|
1115
|
+
// --- delete current multipliers
|
|
1116
|
+
|
|
1117
|
+
listItem = MSX.Pattern[pat].first;
|
|
1118
|
+
while (listItem)
|
|
1119
|
+
{
|
|
1120
|
+
MSX.Pattern[pat].first = listItem->next;
|
|
1121
|
+
free(listItem);
|
|
1122
|
+
listItem = MSX.Pattern[pat].first;
|
|
1123
|
+
}
|
|
1124
|
+
MSX.Pattern[pat].first = NULL;
|
|
1125
|
+
|
|
1126
|
+
// --- create a new set of multipliers
|
|
1127
|
+
|
|
1128
|
+
MSX.Pattern[pat].length = 0;
|
|
1129
|
+
for ( i = 0; i < len; i++ )
|
|
1130
|
+
{
|
|
1131
|
+
listItem = (SnumList *) malloc(sizeof(SnumList));
|
|
1132
|
+
if ( listItem == NULL ) return ERR_MEMORY;
|
|
1133
|
+
listItem->value = mult[i];
|
|
1134
|
+
listItem->next = NULL;
|
|
1135
|
+
if ( MSX.Pattern[pat].first == NULL )
|
|
1136
|
+
{
|
|
1137
|
+
MSX.Pattern[pat].current = listItem;
|
|
1138
|
+
MSX.Pattern[pat].first = listItem;
|
|
1139
|
+
}
|
|
1140
|
+
else
|
|
1141
|
+
{
|
|
1142
|
+
MSX.Pattern[pat].current->next = listItem;
|
|
1143
|
+
MSX.Pattern[pat].current = listItem;
|
|
1144
|
+
}
|
|
1145
|
+
MSX.Pattern[pat].length++;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
MSX.Pattern[pat].interval = 0; //Feng Shang 04/17/2008
|
|
1149
|
+
MSX.Pattern[pat].current = MSX.Pattern[pat].first; //Feng Shang 04/17/2008
|
|
1150
|
+
return 0;
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
//=============================================================================
|
|
1154
|
+
|
|
1155
|
+
int MSXDLLEXPORT MSXsavemsxfile(char *fname)
|
|
1156
|
+
{
|
|
1157
|
+
int errcode;
|
|
1158
|
+
FILE *f;
|
|
1159
|
+
if ( !MSX.ProjectOpened ) return ERR_MSX_NOT_OPENED;
|
|
1160
|
+
if ((f = fopen(fname,"wt")) == NULL) return ERR_OPEN_OUT_FILE;
|
|
1161
|
+
errcode = MSXfile_save(f);
|
|
1162
|
+
fclose(f);
|
|
1163
|
+
return errcode;
|
|
1164
|
+
}
|