epyt-flow 0.14.2__py3-none-any.whl → 0.15.0b1__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/VERSION +1 -1
- epyt_flow/__init__.py +0 -37
- epyt_flow/data/benchmarks/battledim.py +2 -2
- epyt_flow/data/benchmarks/leakdb.py +12 -9
- epyt_flow/gym/scenario_control_env.py +32 -33
- epyt_flow/simulation/events/actuator_events.py +24 -18
- epyt_flow/simulation/events/leakages.py +59 -57
- epyt_flow/simulation/events/quality_events.py +21 -30
- epyt_flow/simulation/events/system_event.py +3 -3
- epyt_flow/simulation/scada/complex_control.py +14 -12
- epyt_flow/simulation/scada/custom_control.py +22 -21
- epyt_flow/simulation/scada/scada_data.py +107 -104
- epyt_flow/simulation/scada/simple_control.py +38 -31
- epyt_flow/simulation/scenario_simulator.py +367 -395
- epyt_flow/simulation/sensor_config.py +31 -32
- epyt_flow/topology.py +11 -10
- epyt_flow/uncertainty/model_uncertainty.py +146 -122
- epyt_flow/utils.py +0 -66
- epyt_flow/visualization/visualization_utils.py +2 -4
- {epyt_flow-0.14.2.dist-info → epyt_flow-0.15.0b1.dist-info}/METADATA +12 -18
- epyt_flow-0.15.0b1.dist-info/RECORD +65 -0
- epyt_flow/EPANET/EPANET/SRC_engines/AUTHORS +0 -28
- epyt_flow/EPANET/EPANET/SRC_engines/LICENSE +0 -21
- epyt_flow/EPANET/EPANET/SRC_engines/Readme_SRC_Engines.txt +0 -18
- epyt_flow/EPANET/EPANET/SRC_engines/enumstxt.h +0 -134
- epyt_flow/EPANET/EPANET/SRC_engines/epanet.c +0 -5578
- epyt_flow/EPANET/EPANET/SRC_engines/epanet2.c +0 -865
- epyt_flow/EPANET/EPANET/SRC_engines/epanet2.def +0 -131
- epyt_flow/EPANET/EPANET/SRC_engines/errors.dat +0 -73
- epyt_flow/EPANET/EPANET/SRC_engines/funcs.h +0 -193
- epyt_flow/EPANET/EPANET/SRC_engines/genmmd.c +0 -1000
- epyt_flow/EPANET/EPANET/SRC_engines/hash.c +0 -177
- epyt_flow/EPANET/EPANET/SRC_engines/hash.h +0 -28
- epyt_flow/EPANET/EPANET/SRC_engines/hydcoeffs.c +0 -1151
- epyt_flow/EPANET/EPANET/SRC_engines/hydraul.c +0 -1117
- epyt_flow/EPANET/EPANET/SRC_engines/hydsolver.c +0 -720
- epyt_flow/EPANET/EPANET/SRC_engines/hydstatus.c +0 -476
- epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2.h +0 -431
- epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_2.h +0 -1786
- epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_enums.h +0 -468
- epyt_flow/EPANET/EPANET/SRC_engines/inpfile.c +0 -810
- epyt_flow/EPANET/EPANET/SRC_engines/input1.c +0 -707
- epyt_flow/EPANET/EPANET/SRC_engines/input2.c +0 -864
- epyt_flow/EPANET/EPANET/SRC_engines/input3.c +0 -2170
- epyt_flow/EPANET/EPANET/SRC_engines/main.c +0 -93
- epyt_flow/EPANET/EPANET/SRC_engines/mempool.c +0 -142
- epyt_flow/EPANET/EPANET/SRC_engines/mempool.h +0 -24
- epyt_flow/EPANET/EPANET/SRC_engines/output.c +0 -852
- epyt_flow/EPANET/EPANET/SRC_engines/project.c +0 -1359
- epyt_flow/EPANET/EPANET/SRC_engines/quality.c +0 -685
- epyt_flow/EPANET/EPANET/SRC_engines/qualreact.c +0 -743
- epyt_flow/EPANET/EPANET/SRC_engines/qualroute.c +0 -694
- epyt_flow/EPANET/EPANET/SRC_engines/report.c +0 -1489
- epyt_flow/EPANET/EPANET/SRC_engines/rules.c +0 -1362
- epyt_flow/EPANET/EPANET/SRC_engines/smatrix.c +0 -871
- epyt_flow/EPANET/EPANET/SRC_engines/text.h +0 -497
- epyt_flow/EPANET/EPANET/SRC_engines/types.h +0 -874
- epyt_flow/EPANET/EPANET-MSX/MSX_Updates.txt +0 -53
- epyt_flow/EPANET/EPANET-MSX/Src/dispersion.h +0 -27
- epyt_flow/EPANET/EPANET-MSX/Src/hash.c +0 -107
- epyt_flow/EPANET/EPANET-MSX/Src/hash.h +0 -28
- epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx.h +0 -102
- epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx_export.h +0 -42
- epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.c +0 -937
- epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.h +0 -39
- epyt_flow/EPANET/EPANET-MSX/Src/mempool.c +0 -204
- epyt_flow/EPANET/EPANET-MSX/Src/mempool.h +0 -24
- epyt_flow/EPANET/EPANET-MSX/Src/msxchem.c +0 -1285
- epyt_flow/EPANET/EPANET-MSX/Src/msxcompiler.c +0 -368
- epyt_flow/EPANET/EPANET-MSX/Src/msxdict.h +0 -42
- epyt_flow/EPANET/EPANET-MSX/Src/msxdispersion.c +0 -586
- epyt_flow/EPANET/EPANET-MSX/Src/msxerr.c +0 -116
- epyt_flow/EPANET/EPANET-MSX/Src/msxfile.c +0 -260
- epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.c +0 -175
- epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.h +0 -35
- epyt_flow/EPANET/EPANET-MSX/Src/msxinp.c +0 -1504
- epyt_flow/EPANET/EPANET-MSX/Src/msxout.c +0 -401
- epyt_flow/EPANET/EPANET-MSX/Src/msxproj.c +0 -791
- epyt_flow/EPANET/EPANET-MSX/Src/msxqual.c +0 -2010
- epyt_flow/EPANET/EPANET-MSX/Src/msxrpt.c +0 -400
- epyt_flow/EPANET/EPANET-MSX/Src/msxtank.c +0 -422
- epyt_flow/EPANET/EPANET-MSX/Src/msxtoolkit.c +0 -1164
- epyt_flow/EPANET/EPANET-MSX/Src/msxtypes.h +0 -551
- epyt_flow/EPANET/EPANET-MSX/Src/msxutils.c +0 -524
- epyt_flow/EPANET/EPANET-MSX/Src/msxutils.h +0 -56
- epyt_flow/EPANET/EPANET-MSX/Src/newton.c +0 -158
- epyt_flow/EPANET/EPANET-MSX/Src/newton.h +0 -34
- epyt_flow/EPANET/EPANET-MSX/Src/rk5.c +0 -287
- epyt_flow/EPANET/EPANET-MSX/Src/rk5.h +0 -39
- epyt_flow/EPANET/EPANET-MSX/Src/ros2.c +0 -293
- epyt_flow/EPANET/EPANET-MSX/Src/ros2.h +0 -35
- epyt_flow/EPANET/EPANET-MSX/Src/smatrix.c +0 -816
- epyt_flow/EPANET/EPANET-MSX/Src/smatrix.h +0 -29
- epyt_flow/EPANET/EPANET-MSX/readme.txt +0 -14
- epyt_flow/EPANET/compile_linux.sh +0 -4
- epyt_flow/EPANET/compile_macos.sh +0 -4
- epyt_flow/simulation/backend/__init__.py +0 -1
- epyt_flow/simulation/backend/my_epyt.py +0 -1101
- epyt_flow-0.14.2.dist-info/RECORD +0 -142
- {epyt_flow-0.14.2.dist-info → epyt_flow-0.15.0b1.dist-info}/WHEEL +0 -0
- {epyt_flow-0.14.2.dist-info → epyt_flow-0.15.0b1.dist-info}/licenses/LICENSE +0 -0
- {epyt_flow-0.14.2.dist-info → epyt_flow-0.15.0b1.dist-info}/top_level.txt +0 -0
|
@@ -1,1285 +0,0 @@
|
|
|
1
|
-
/*******************************************************************************
|
|
2
|
-
** MODULE: MSXCHEM.C
|
|
3
|
-
** PROJECT: EPANET-MSX
|
|
4
|
-
** DESCRIPTION: Water quality chemistry functions.
|
|
5
|
-
** AUTHORS: see AUTHORS
|
|
6
|
-
** Copyright: see AUTHORS
|
|
7
|
-
** License: see LICENSE
|
|
8
|
-
** VERSION: 2.0.00
|
|
9
|
-
** LAST UPDATE: 04/14/2021
|
|
10
|
-
*******************************************************************************/
|
|
11
|
-
|
|
12
|
-
#include <stdio.h>
|
|
13
|
-
#include <string.h>
|
|
14
|
-
#include <math.h>
|
|
15
|
-
#include <stdlib.h>
|
|
16
|
-
|
|
17
|
-
#include "msxtypes.h"
|
|
18
|
-
#include "rk5.h"
|
|
19
|
-
#include "ros2.h"
|
|
20
|
-
#include "newton.h"
|
|
21
|
-
#include "msxfuncs.h"
|
|
22
|
-
|
|
23
|
-
// External variables
|
|
24
|
-
//--------------------
|
|
25
|
-
extern MSXproject MSX; // MSX project data
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
// Constants
|
|
29
|
-
//-----------
|
|
30
|
-
int MAXIT = 20; // Max. number of iterations used
|
|
31
|
-
// in nonlinear equation solver
|
|
32
|
-
int NUMSIG = 3; // Number of significant digits in
|
|
33
|
-
// nonlinear equation solver error
|
|
34
|
-
|
|
35
|
-
// Local variables
|
|
36
|
-
//-----------------
|
|
37
|
-
static Pseg TheSeg; // Current water quality segment
|
|
38
|
-
static int TheLink; // Index of current link
|
|
39
|
-
static int TheNode; // Index of current node
|
|
40
|
-
static int TheTank; // Index of current tank
|
|
41
|
-
static int NumSpecies; // Total number of species
|
|
42
|
-
static int NumPipeRateSpecies; // Number of species with pipe rates
|
|
43
|
-
static int NumTankRateSpecies; // Number of species with tank rates
|
|
44
|
-
static int NumPipeFormulaSpecies; // Number of species with pipe formulas
|
|
45
|
-
static int NumTankFormulaSpecies; // Number of species with tank formulas
|
|
46
|
-
static int NumPipeEquilSpecies; // Number of species with pipe equilibria
|
|
47
|
-
static int NumTankEquilSpecies; // Number of species with tank equilibria
|
|
48
|
-
static int *PipeRateSpecies; // Species governed by pipe reactions
|
|
49
|
-
static int *TankRateSpecies; // Species governed by tank reactions
|
|
50
|
-
static int *PipeEquilSpecies; // Species governed by pipe equilibria
|
|
51
|
-
static int *TankEquilSpecies; // Species governed by tank equilibria
|
|
52
|
-
static int LastIndex[MAX_OBJECTS]; // Last index of given type of variable
|
|
53
|
-
static double *Atol; // Absolute concentration tolerances
|
|
54
|
-
static double *Rtol; // Relative concentration tolerances
|
|
55
|
-
static double *Yrate; // Rate species concentrations
|
|
56
|
-
static double *Yequil; // Equilibrium species concentrations
|
|
57
|
-
static double HydVar[MAX_HYD_VARS]; // Values of hydraulic variables
|
|
58
|
-
static double *F; // Function values
|
|
59
|
-
static double *ChemC1;
|
|
60
|
-
|
|
61
|
-
#pragma omp threadprivate(TheSeg, TheLink, TheNode, TheTank, Yrate, Yequil, HydVar, F, ChemC1)
|
|
62
|
-
|
|
63
|
-
// Exported functions
|
|
64
|
-
//--------------------
|
|
65
|
-
int MSXchem_open(void);
|
|
66
|
-
int MSXchem_react(double dt);
|
|
67
|
-
int MSXchem_equil(int zone, int k, double *c);
|
|
68
|
-
char* MSXchem_getVariableStr(int i, char *s);
|
|
69
|
-
void MSXchem_close(void);
|
|
70
|
-
|
|
71
|
-
// Imported functions
|
|
72
|
-
//-------------------
|
|
73
|
-
int MSXcompiler_open(void);
|
|
74
|
-
void MSXcompiler_close(void);
|
|
75
|
-
double MSXerr_validate(double x, int index, int element, int exprType);
|
|
76
|
-
|
|
77
|
-
// Local functions
|
|
78
|
-
//-----------------
|
|
79
|
-
static void setSpeciesChemistry(void);
|
|
80
|
-
static void setTankChemistry(void);
|
|
81
|
-
//static void evalHydVariables(int k);
|
|
82
|
-
static int evalPipeReactions(int k, double dt);
|
|
83
|
-
static int evalTankReactions(int k, double dt);
|
|
84
|
-
static int evalPipeEquil(double *c);
|
|
85
|
-
static int evalTankEquil(double *c);
|
|
86
|
-
static void evalPipeFormulas(double *c);
|
|
87
|
-
static void evalTankFormulas(double *c);
|
|
88
|
-
static double getPipeVariableValue(int i);
|
|
89
|
-
static double getTankVariableValue(int i);
|
|
90
|
-
static void getPipeDcDt(double t, double y[], int n, double deriv[]);
|
|
91
|
-
static void getTankDcDt(double t, double y[], int n, double deriv[]);
|
|
92
|
-
static void getPipeEquil(double t, double y[], int n, double f[]);
|
|
93
|
-
static void getTankEquil(double t, double y[], int n, double f[]);
|
|
94
|
-
static int isValidNumber(double x); //(L.Rossman - 11/03/10)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
//=============================================================================
|
|
98
|
-
|
|
99
|
-
int MSXchem_open()
|
|
100
|
-
/*
|
|
101
|
-
** Purpose:
|
|
102
|
-
** opens the multi-species chemistry system.
|
|
103
|
-
**
|
|
104
|
-
** Input:
|
|
105
|
-
** none.
|
|
106
|
-
**
|
|
107
|
-
** Returns:
|
|
108
|
-
** an error code (0 if no error).
|
|
109
|
-
*/
|
|
110
|
-
{
|
|
111
|
-
int m;
|
|
112
|
-
int numWallSpecies;
|
|
113
|
-
int numBulkSpecies;
|
|
114
|
-
int numTankExpr;
|
|
115
|
-
int numPipeExpr;
|
|
116
|
-
int errcode = 0;
|
|
117
|
-
|
|
118
|
-
// --- allocate memory
|
|
119
|
-
|
|
120
|
-
PipeRateSpecies = NULL;
|
|
121
|
-
TankRateSpecies = NULL;
|
|
122
|
-
PipeEquilSpecies = NULL;
|
|
123
|
-
TankEquilSpecies = NULL;
|
|
124
|
-
Atol = NULL;
|
|
125
|
-
Rtol = NULL;
|
|
126
|
-
Yrate = NULL;
|
|
127
|
-
Yequil = NULL;
|
|
128
|
-
NumSpecies = MSX.Nobjects[SPECIES];
|
|
129
|
-
m = NumSpecies + 1;
|
|
130
|
-
PipeRateSpecies = (int*)calloc(m, sizeof(int));
|
|
131
|
-
TankRateSpecies = (int*)calloc(m, sizeof(int));
|
|
132
|
-
PipeEquilSpecies = (int*)calloc(m, sizeof(int));
|
|
133
|
-
TankEquilSpecies = (int*)calloc(m, sizeof(int));
|
|
134
|
-
Atol = (double*)calloc(m, sizeof(double));
|
|
135
|
-
Rtol = (double*)calloc(m, sizeof(double));
|
|
136
|
-
CALL(errcode, MEMCHECK(PipeRateSpecies));
|
|
137
|
-
CALL(errcode, MEMCHECK(TankRateSpecies));
|
|
138
|
-
CALL(errcode, MEMCHECK(PipeEquilSpecies));
|
|
139
|
-
CALL(errcode, MEMCHECK(TankEquilSpecies));
|
|
140
|
-
CALL(errcode, MEMCHECK(Atol));
|
|
141
|
-
CALL(errcode, MEMCHECK(Rtol));
|
|
142
|
-
|
|
143
|
-
#pragma omp parallel
|
|
144
|
-
{
|
|
145
|
-
Yrate = (double*)calloc(m, sizeof(double));
|
|
146
|
-
Yequil = (double*)calloc(m, sizeof(double));
|
|
147
|
-
F = (double*)calloc(m, sizeof(double));
|
|
148
|
-
ChemC1 = (double*)calloc(m, sizeof(double));
|
|
149
|
-
#pragma omp critical
|
|
150
|
-
{
|
|
151
|
-
CALL(errcode, MEMCHECK(Yrate));
|
|
152
|
-
CALL(errcode, MEMCHECK(Yequil));
|
|
153
|
-
CALL(errcode, MEMCHECK(F));
|
|
154
|
-
CALL(errcode, MEMCHECK(ChemC1));
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
if ( errcode ) return errcode;
|
|
158
|
-
|
|
159
|
-
// --- assign species to each type of chemical expression
|
|
160
|
-
|
|
161
|
-
setSpeciesChemistry();
|
|
162
|
-
numPipeExpr = NumPipeRateSpecies + NumPipeFormulaSpecies + NumPipeEquilSpecies;
|
|
163
|
-
numTankExpr = NumTankRateSpecies + NumTankFormulaSpecies + NumTankEquilSpecies;
|
|
164
|
-
|
|
165
|
-
// --- use pipe chemistry for tanks if latter was not supplied
|
|
166
|
-
|
|
167
|
-
if ( numTankExpr == 0 )
|
|
168
|
-
{
|
|
169
|
-
setTankChemistry();
|
|
170
|
-
numTankExpr = numPipeExpr;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// --- check if enough equations were specified
|
|
174
|
-
|
|
175
|
-
numWallSpecies = 0;
|
|
176
|
-
numBulkSpecies = 0;
|
|
177
|
-
for (m=1; m<=NumSpecies; m++)
|
|
178
|
-
{
|
|
179
|
-
if ( MSX.Species[m].type == WALL ) numWallSpecies++;
|
|
180
|
-
if ( MSX.Species[m].type == BULK ) numBulkSpecies++;
|
|
181
|
-
}
|
|
182
|
-
if ( numPipeExpr != NumSpecies ) return ERR_NUM_PIPE_EXPR;
|
|
183
|
-
if ( numTankExpr != numBulkSpecies ) return ERR_NUM_TANK_EXPR;
|
|
184
|
-
|
|
185
|
-
// --- open the ODE solver;
|
|
186
|
-
// arguments are max. number of ODE's,
|
|
187
|
-
// max. number of steps to be taken,
|
|
188
|
-
// 1 if automatic step sizing used (or 0 if not used)
|
|
189
|
-
|
|
190
|
-
if ( MSX.Solver == RK5 )
|
|
191
|
-
{
|
|
192
|
-
if ( rk5_open(NumSpecies, 1000, 1) == FALSE )
|
|
193
|
-
return ERR_INTEGRATOR_OPEN;
|
|
194
|
-
}
|
|
195
|
-
if ( MSX.Solver == ROS2 )
|
|
196
|
-
{
|
|
197
|
-
if ( ros2_open(NumSpecies, 1) == FALSE )
|
|
198
|
-
return ERR_INTEGRATOR_OPEN;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// --- open the algebraic eqn. solver
|
|
202
|
-
|
|
203
|
-
m = MAX(NumPipeEquilSpecies, NumTankEquilSpecies);
|
|
204
|
-
if ( newton_open(m) == FALSE ) return ERR_NEWTON_OPEN;
|
|
205
|
-
|
|
206
|
-
// --- assign entries to LastIndex array
|
|
207
|
-
|
|
208
|
-
LastIndex[SPECIES] = MSX.Nobjects[SPECIES];
|
|
209
|
-
LastIndex[TERM] = LastIndex[SPECIES] + MSX.Nobjects[TERM];
|
|
210
|
-
LastIndex[PARAMETER] = LastIndex[TERM] + MSX.Nobjects[PARAMETER];
|
|
211
|
-
LastIndex[CONSTANT] = LastIndex[PARAMETER] + MSX.Nobjects[CONSTANT];
|
|
212
|
-
|
|
213
|
-
// --- compile chemistry function dynamic library if specified
|
|
214
|
-
|
|
215
|
-
if ( MSX.Compiler )
|
|
216
|
-
{
|
|
217
|
-
errcode = MSXcompiler_open();
|
|
218
|
-
if ( errcode ) return errcode;
|
|
219
|
-
}
|
|
220
|
-
return 0;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
//=============================================================================
|
|
224
|
-
|
|
225
|
-
void MSXchem_close()
|
|
226
|
-
/*
|
|
227
|
-
** Purpose:
|
|
228
|
-
** closes the multi-species chemistry system.
|
|
229
|
-
**
|
|
230
|
-
** Input:
|
|
231
|
-
** none.
|
|
232
|
-
*/
|
|
233
|
-
{
|
|
234
|
-
if (MSX.Compiler) MSXcompiler_close();
|
|
235
|
-
if (MSX.Solver == RK5) rk5_close();
|
|
236
|
-
if (MSX.Solver == ROS2) ros2_close();
|
|
237
|
-
newton_close();
|
|
238
|
-
FREE(PipeRateSpecies);
|
|
239
|
-
FREE(TankRateSpecies);
|
|
240
|
-
FREE(PipeEquilSpecies);
|
|
241
|
-
FREE(TankEquilSpecies);
|
|
242
|
-
FREE(Atol);
|
|
243
|
-
FREE(Rtol);
|
|
244
|
-
|
|
245
|
-
#pragma omp parallel
|
|
246
|
-
{
|
|
247
|
-
FREE(ChemC1);
|
|
248
|
-
FREE(Yrate);
|
|
249
|
-
FREE(Yequil);
|
|
250
|
-
FREE(F);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
//=============================================================================
|
|
256
|
-
|
|
257
|
-
int MSXchem_react(double dt)
|
|
258
|
-
/*
|
|
259
|
-
** Purpose:
|
|
260
|
-
** computes reactions in all pipes and tanks.
|
|
261
|
-
**
|
|
262
|
-
** Input:
|
|
263
|
-
** dt = current WQ time step (sec).
|
|
264
|
-
**
|
|
265
|
-
** Returns:
|
|
266
|
-
** an error code or 0 if no error.
|
|
267
|
-
*/
|
|
268
|
-
{
|
|
269
|
-
int k, m;
|
|
270
|
-
int errcode = 0;
|
|
271
|
-
|
|
272
|
-
// --- save tolerances of pipe rate species
|
|
273
|
-
|
|
274
|
-
for (k=1; k<=NumPipeRateSpecies; k++)
|
|
275
|
-
{
|
|
276
|
-
m = PipeRateSpecies[k];
|
|
277
|
-
Atol[k] = MSX.Species[m].aTol;
|
|
278
|
-
Rtol[k] = MSX.Species[m].rTol;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
// --- examine each link
|
|
282
|
-
#pragma omp parallel
|
|
283
|
-
{
|
|
284
|
-
#pragma omp for private(k)
|
|
285
|
-
for (k = 1; k <= MSX.Nobjects[LINK]; k++)
|
|
286
|
-
{
|
|
287
|
-
// --- skip non-pipe links
|
|
288
|
-
|
|
289
|
-
if (MSX.Link[k].len == 0.0) continue;
|
|
290
|
-
|
|
291
|
-
// --- evaluate hydraulic variables
|
|
292
|
-
|
|
293
|
-
//evalHydVariables(k);
|
|
294
|
-
for (int hi = 1; hi < MAX_HYD_VARS; hi++)
|
|
295
|
-
HydVar[hi] = MSX.Link[k].HydVar[hi];
|
|
296
|
-
// --- compute pipe reactions
|
|
297
|
-
|
|
298
|
-
errcode = evalPipeReactions(k, dt);
|
|
299
|
-
//if (errcode) return errcode;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
if (errcode) return errcode;
|
|
303
|
-
|
|
304
|
-
// --- save tolerances of tank rate species
|
|
305
|
-
|
|
306
|
-
for (k=1; k<=NumTankRateSpecies; k++)
|
|
307
|
-
{
|
|
308
|
-
m = TankRateSpecies[k];
|
|
309
|
-
Atol[k] = MSX.Species[m].aTol;
|
|
310
|
-
Rtol[k] = MSX.Species[m].rTol;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
// --- examine each tank
|
|
314
|
-
|
|
315
|
-
for (k=1; k<=MSX.Nobjects[TANK]; k++)
|
|
316
|
-
{
|
|
317
|
-
// --- skip reservoirs
|
|
318
|
-
|
|
319
|
-
if (MSX.Tank[k].a == 0.0) continue;
|
|
320
|
-
|
|
321
|
-
// --- compute tank reactions
|
|
322
|
-
|
|
323
|
-
errcode = evalTankReactions(k, dt);
|
|
324
|
-
if ( errcode ) return errcode;
|
|
325
|
-
}
|
|
326
|
-
return errcode;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
//=============================================================================
|
|
330
|
-
|
|
331
|
-
int MSXchem_equil(int zone, int k, double *c)
|
|
332
|
-
/*
|
|
333
|
-
** Purpose:
|
|
334
|
-
** computes equilibrium concentrations for a set of chemical species.
|
|
335
|
-
**
|
|
336
|
-
** Input:
|
|
337
|
-
** zone = reaction zone (NODE or LINK)
|
|
338
|
-
** k = pipe or tank index
|
|
339
|
-
** c[] = array of species concentrations
|
|
340
|
-
**
|
|
341
|
-
** Output:
|
|
342
|
-
** updated value of c[].
|
|
343
|
-
**
|
|
344
|
-
** Returns:
|
|
345
|
-
** an error code or 0 if no errors.
|
|
346
|
-
*/
|
|
347
|
-
{
|
|
348
|
-
int errcode = 0;
|
|
349
|
-
if ( zone == LINK )
|
|
350
|
-
{
|
|
351
|
-
TheLink = k;
|
|
352
|
-
for (int vi = 1; vi < MAX_HYD_VARS; vi++)
|
|
353
|
-
HydVar[vi] = MSX.Link[k].HydVar[vi];
|
|
354
|
-
if ( NumPipeEquilSpecies > 0 ) errcode = evalPipeEquil(c);
|
|
355
|
-
evalPipeFormulas(c);
|
|
356
|
-
}
|
|
357
|
-
if ( zone == NODE )
|
|
358
|
-
{
|
|
359
|
-
TheTank = k;
|
|
360
|
-
TheNode = MSX.Tank[k].node;
|
|
361
|
-
if ( NumTankEquilSpecies > 0 ) errcode = evalTankEquil(c);
|
|
362
|
-
evalTankFormulas(c);
|
|
363
|
-
}
|
|
364
|
-
return errcode;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
//=============================================================================
|
|
368
|
-
|
|
369
|
-
char* MSXchem_getVariableStr(int i, char *s)
|
|
370
|
-
/*
|
|
371
|
-
** Purpose:
|
|
372
|
-
** returns a string representation of a variable used in the chemistry
|
|
373
|
-
** functions appearing in the C source code file used to compile
|
|
374
|
-
** these functions
|
|
375
|
-
**
|
|
376
|
-
** Input:
|
|
377
|
-
** i = variable's index in the LastIndex array
|
|
378
|
-
** s = string to hold variable's symbol
|
|
379
|
-
**
|
|
380
|
-
** Output:
|
|
381
|
-
** returns a pointer to s
|
|
382
|
-
*/
|
|
383
|
-
{
|
|
384
|
-
// --- WQ species have index between 1 & # of species
|
|
385
|
-
|
|
386
|
-
if ( i <= LastIndex[SPECIES] ) sprintf(s, "c[%d]", i);
|
|
387
|
-
|
|
388
|
-
// --- intermediate term expressions come next
|
|
389
|
-
|
|
390
|
-
else if ( i <= LastIndex[TERM] )
|
|
391
|
-
{
|
|
392
|
-
i -= LastIndex[TERM-1];
|
|
393
|
-
sprintf(s, "term(%d, c, k, p, h)", i);
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
// --- reaction parameter indexes come after that
|
|
397
|
-
|
|
398
|
-
else if ( i <= LastIndex[PARAMETER] )
|
|
399
|
-
{
|
|
400
|
-
i -= LastIndex[PARAMETER-1];
|
|
401
|
-
sprintf(s, "p[%d]", i);
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
// --- followed by constants
|
|
405
|
-
|
|
406
|
-
else if ( i <= LastIndex[CONSTANT] )
|
|
407
|
-
{
|
|
408
|
-
i -= LastIndex[CONSTANT-1];
|
|
409
|
-
sprintf(s, "k[%d]", i);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
// --- and finally by hydraulic variables
|
|
413
|
-
|
|
414
|
-
else
|
|
415
|
-
{
|
|
416
|
-
i -= LastIndex[CONSTANT];
|
|
417
|
-
sprintf(s, "h[%d]", i);
|
|
418
|
-
}
|
|
419
|
-
return s;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
//=============================================================================
|
|
423
|
-
|
|
424
|
-
void setSpeciesChemistry()
|
|
425
|
-
/*
|
|
426
|
-
** Purpose:
|
|
427
|
-
** determines which species are described by reaction rate
|
|
428
|
-
** expressions, equilibrium expressions, or simple formulas.
|
|
429
|
-
**
|
|
430
|
-
** Input:
|
|
431
|
-
** none.
|
|
432
|
-
**
|
|
433
|
-
** Output:
|
|
434
|
-
** updates arrays of different chemistry types.
|
|
435
|
-
*/
|
|
436
|
-
{
|
|
437
|
-
int m;
|
|
438
|
-
NumPipeRateSpecies = 0;
|
|
439
|
-
NumPipeFormulaSpecies = 0;
|
|
440
|
-
NumPipeEquilSpecies = 0;
|
|
441
|
-
NumTankRateSpecies = 0;
|
|
442
|
-
NumTankFormulaSpecies = 0;
|
|
443
|
-
NumTankEquilSpecies = 0;
|
|
444
|
-
for (m=1; m<=NumSpecies; m++)
|
|
445
|
-
{
|
|
446
|
-
switch ( MSX.Species[m].pipeExprType )
|
|
447
|
-
{
|
|
448
|
-
case RATE:
|
|
449
|
-
NumPipeRateSpecies++;
|
|
450
|
-
PipeRateSpecies[NumPipeRateSpecies] = m;
|
|
451
|
-
break;
|
|
452
|
-
|
|
453
|
-
case FORMULA:
|
|
454
|
-
NumPipeFormulaSpecies++;
|
|
455
|
-
break;
|
|
456
|
-
|
|
457
|
-
case EQUIL:
|
|
458
|
-
NumPipeEquilSpecies++;
|
|
459
|
-
PipeEquilSpecies[NumPipeEquilSpecies] = m;
|
|
460
|
-
break;
|
|
461
|
-
}
|
|
462
|
-
switch ( MSX.Species[m].tankExprType )
|
|
463
|
-
{
|
|
464
|
-
case RATE:
|
|
465
|
-
NumTankRateSpecies++;
|
|
466
|
-
TankRateSpecies[NumTankRateSpecies] = m;
|
|
467
|
-
break;
|
|
468
|
-
|
|
469
|
-
case FORMULA:
|
|
470
|
-
NumTankFormulaSpecies++;
|
|
471
|
-
break;
|
|
472
|
-
|
|
473
|
-
case EQUIL:
|
|
474
|
-
NumTankEquilSpecies++;
|
|
475
|
-
TankEquilSpecies[NumTankEquilSpecies] = m;
|
|
476
|
-
break;
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
//=============================================================================
|
|
482
|
-
|
|
483
|
-
void setTankChemistry()
|
|
484
|
-
/*
|
|
485
|
-
** Purpose:
|
|
486
|
-
** assigns pipe chemistry expressions to tank chemistry for
|
|
487
|
-
** each chemical species.
|
|
488
|
-
**
|
|
489
|
-
** Input:
|
|
490
|
-
** none.
|
|
491
|
-
**
|
|
492
|
-
** Output:
|
|
493
|
-
** updates arrays of different tank chemistry types.
|
|
494
|
-
*/
|
|
495
|
-
{
|
|
496
|
-
int m;
|
|
497
|
-
for (m=1; m<=NumSpecies; m++)
|
|
498
|
-
{
|
|
499
|
-
MSX.Species[m].tankExpr = MSX.Species[m].pipeExpr;
|
|
500
|
-
MSX.Species[m].tankExprType = MSX.Species[m].pipeExprType;
|
|
501
|
-
}
|
|
502
|
-
NumTankRateSpecies = NumPipeRateSpecies;
|
|
503
|
-
for (m=1; m<=NumTankRateSpecies; m++)
|
|
504
|
-
{
|
|
505
|
-
TankRateSpecies[m] = PipeRateSpecies[m];
|
|
506
|
-
}
|
|
507
|
-
NumTankFormulaSpecies = NumPipeFormulaSpecies;
|
|
508
|
-
NumTankEquilSpecies = NumPipeEquilSpecies;
|
|
509
|
-
for (m=1; m<=NumTankEquilSpecies; m++)
|
|
510
|
-
{
|
|
511
|
-
TankEquilSpecies[m] = PipeEquilSpecies[m];
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
//=============================================================================
|
|
518
|
-
|
|
519
|
-
int evalPipeReactions(int k, double dt)
|
|
520
|
-
/*
|
|
521
|
-
** Purpose:
|
|
522
|
-
** updates species concentrations in each WQ segment of a pipe
|
|
523
|
-
** after reactions occur over time step dt.
|
|
524
|
-
**
|
|
525
|
-
** Input:
|
|
526
|
-
** k = link index
|
|
527
|
-
** dt = time step (sec).
|
|
528
|
-
**
|
|
529
|
-
** Output:
|
|
530
|
-
** updates values in the concentration vector C[] associated
|
|
531
|
-
** with a pipe's WQ segments.
|
|
532
|
-
**
|
|
533
|
-
** Returns:
|
|
534
|
-
** an error code or 0 if no error.
|
|
535
|
-
**
|
|
536
|
-
** Re-written to accommodate compiled functions (1.1)
|
|
537
|
-
*/
|
|
538
|
-
{
|
|
539
|
-
int i, m;
|
|
540
|
-
int errcode = 0, ierr = 0;
|
|
541
|
-
double tstep = (double)dt / MSX.Ucf[RATE_UNITS];
|
|
542
|
-
double c, dh;
|
|
543
|
-
|
|
544
|
-
// --- start with the most downstream pipe segment
|
|
545
|
-
|
|
546
|
-
TheLink = k;
|
|
547
|
-
TheSeg = MSX.FirstSeg[TheLink];
|
|
548
|
-
while ( TheSeg )
|
|
549
|
-
{
|
|
550
|
-
for (m = 1; m <= NumSpecies; m++)
|
|
551
|
-
{
|
|
552
|
-
ChemC1[m] = TheSeg->c[m];
|
|
553
|
-
TheSeg->lastc[m] = TheSeg->c[m];
|
|
554
|
-
}
|
|
555
|
-
ierr = 0;
|
|
556
|
-
|
|
557
|
-
// --- react each reacting species over the time step
|
|
558
|
-
|
|
559
|
-
if ( dt > 0.0 )
|
|
560
|
-
{
|
|
561
|
-
|
|
562
|
-
// --- place current concentrations of species that react in vector Yrate
|
|
563
|
-
|
|
564
|
-
for (i=1; i<=NumPipeRateSpecies; i++)
|
|
565
|
-
{
|
|
566
|
-
m = PipeRateSpecies[i];
|
|
567
|
-
Yrate[i] = TheSeg->c[m];
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
// --- Euler integrator
|
|
571
|
-
|
|
572
|
-
if ( MSX.Solver == EUL )
|
|
573
|
-
{
|
|
574
|
-
getPipeDcDt(0, Yrate, NumPipeRateSpecies, Yrate);
|
|
575
|
-
for (i=1; i<=NumPipeRateSpecies; i++)
|
|
576
|
-
{
|
|
577
|
-
m = PipeRateSpecies[i];
|
|
578
|
-
c = TheSeg->c[m] + Yrate[i]*tstep;
|
|
579
|
-
TheSeg->c[m] = MAX(c, 0.0);
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
// --- other integrators
|
|
584
|
-
else
|
|
585
|
-
{
|
|
586
|
-
dh = TheSeg->hstep;
|
|
587
|
-
|
|
588
|
-
// --- Runge-Kutta integrator
|
|
589
|
-
|
|
590
|
-
if ( MSX.Solver == RK5 )
|
|
591
|
-
ierr = rk5_integrate(Yrate, NumPipeRateSpecies, 0, tstep,
|
|
592
|
-
&dh, Atol, Rtol, getPipeDcDt);
|
|
593
|
-
|
|
594
|
-
// --- Rosenbrock integrator
|
|
595
|
-
|
|
596
|
-
if ( MSX.Solver == ROS2 )
|
|
597
|
-
ierr = ros2_integrate(Yrate, NumPipeRateSpecies, 0, tstep,
|
|
598
|
-
&dh, Atol, Rtol, getPipeDcDt);
|
|
599
|
-
|
|
600
|
-
// --- save new concentration values of the species that reacted
|
|
601
|
-
|
|
602
|
-
for (m=1; m<=NumSpecies; m++) TheSeg->c[m] = ChemC1[m];
|
|
603
|
-
for (i=1; i<=NumPipeRateSpecies; i++)
|
|
604
|
-
{
|
|
605
|
-
m = PipeRateSpecies[i];
|
|
606
|
-
TheSeg->c[m] = MAX(Yrate[i], 0.0);
|
|
607
|
-
}
|
|
608
|
-
TheSeg->hstep = dh;
|
|
609
|
-
}
|
|
610
|
-
if ( ierr < 0 ) return
|
|
611
|
-
ERR_INTEGRATOR;
|
|
612
|
-
|
|
613
|
-
for (m = 1; m <= MSX.Nobjects[SPECIES]; m++)
|
|
614
|
-
{
|
|
615
|
-
if (MSX.Species[m].type == BULK)
|
|
616
|
-
{
|
|
617
|
-
MSX.Link[k].reacted[m] += TheSeg->v * (TheSeg->c[m] - TheSeg->lastc[m]) * LperFT3;
|
|
618
|
-
}
|
|
619
|
-
else if (MSX.Link[k].diam > 0)
|
|
620
|
-
{
|
|
621
|
-
MSX.Link[k].reacted[m] += TheSeg->v * 4.0 / MSX.Link[k].diam * MSX.Ucf[AREA_UNITS] * (TheSeg->c[m] - TheSeg->lastc[m]);
|
|
622
|
-
}
|
|
623
|
-
TheSeg->lastc[m] = TheSeg->c[m];
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
// --- compute new equilibrium concentrations within segment
|
|
628
|
-
|
|
629
|
-
errcode = MSXchem_equil(LINK, k, TheSeg->c);
|
|
630
|
-
if ( errcode ) return errcode;
|
|
631
|
-
|
|
632
|
-
// --- move to the segment upstream of the current one
|
|
633
|
-
TheSeg = TheSeg->prev;
|
|
634
|
-
}
|
|
635
|
-
return errcode;
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
//=============================================================================
|
|
639
|
-
|
|
640
|
-
int evalTankReactions(int k, double dt)
|
|
641
|
-
/*
|
|
642
|
-
** Purpose:
|
|
643
|
-
** updates species concentrations in a given storage tank
|
|
644
|
-
** after reactions occur over time step dt.
|
|
645
|
-
**
|
|
646
|
-
** Input:
|
|
647
|
-
** k = tank index
|
|
648
|
-
** dt = time step (sec).
|
|
649
|
-
**
|
|
650
|
-
** Output:
|
|
651
|
-
** updates values in the concentration vector Tank[k].c[]
|
|
652
|
-
** for tank k.
|
|
653
|
-
**
|
|
654
|
-
** Returns:
|
|
655
|
-
** an error code or 0 if no error.
|
|
656
|
-
**
|
|
657
|
-
** Re-written to accommodate compiled functions (1.1)
|
|
658
|
-
*/
|
|
659
|
-
{
|
|
660
|
-
int i, m;
|
|
661
|
-
int errcode = 0, ierr = 0;
|
|
662
|
-
double tstep = (double)dt / MSX.Ucf[RATE_UNITS];
|
|
663
|
-
double c, dh;
|
|
664
|
-
|
|
665
|
-
// --- evaluate each volume segment in the tank
|
|
666
|
-
|
|
667
|
-
TheTank = k;
|
|
668
|
-
TheNode = MSX.Tank[k].node;
|
|
669
|
-
i = MSX.Nobjects[LINK] + k;
|
|
670
|
-
TheSeg = MSX.FirstSeg[i];
|
|
671
|
-
while ( TheSeg )
|
|
672
|
-
{
|
|
673
|
-
for (m = 1; m <= NumSpecies; m++)
|
|
674
|
-
{
|
|
675
|
-
ChemC1[m] = TheSeg->c[m];
|
|
676
|
-
TheSeg->lastc[m] = TheSeg->c[m];
|
|
677
|
-
}
|
|
678
|
-
ierr = 0;
|
|
679
|
-
|
|
680
|
-
// --- react each reacting species over the time step
|
|
681
|
-
|
|
682
|
-
if ( dt > 0.0 )
|
|
683
|
-
{
|
|
684
|
-
|
|
685
|
-
// --- place current concentrations of species that react in vector Yrate
|
|
686
|
-
for (i=1; i<=NumTankRateSpecies; i++)
|
|
687
|
-
{
|
|
688
|
-
m = TankRateSpecies[i];
|
|
689
|
-
// Yrate[i] = MSX.Tank[k].c[m];
|
|
690
|
-
Yrate[i] = TheSeg->c[m];
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
// --- Euler integrator
|
|
694
|
-
|
|
695
|
-
if ( MSX.Solver == EUL )
|
|
696
|
-
{
|
|
697
|
-
getTankDcDt(0, Yrate, NumTankRateSpecies, Yrate);
|
|
698
|
-
for (i=1; i<=NumTankRateSpecies; i++)
|
|
699
|
-
{
|
|
700
|
-
m = TankRateSpecies[i];
|
|
701
|
-
c = TheSeg->c[m] + Yrate[i]*tstep;
|
|
702
|
-
TheSeg->c[m] = MAX(c, 0.0);
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
// --- other integrators
|
|
707
|
-
else
|
|
708
|
-
{
|
|
709
|
-
dh = MSX.Tank[k].hstep;
|
|
710
|
-
|
|
711
|
-
// --- Runge-Kutta integrator
|
|
712
|
-
|
|
713
|
-
if ( MSX.Solver == RK5 )
|
|
714
|
-
ierr = rk5_integrate(Yrate, NumTankRateSpecies, 0, tstep,
|
|
715
|
-
&dh, Atol, Rtol, getTankDcDt);
|
|
716
|
-
|
|
717
|
-
// --- Rosenbrock integrator
|
|
718
|
-
|
|
719
|
-
if ( MSX.Solver == ROS2 )
|
|
720
|
-
ierr = ros2_integrate(Yrate, NumTankRateSpecies, 0, tstep,
|
|
721
|
-
&dh, Atol, Rtol, getTankDcDt);
|
|
722
|
-
|
|
723
|
-
// --- save new concentration values of the species that reacted
|
|
724
|
-
|
|
725
|
-
for (m=1; m<=NumSpecies; m++) TheSeg->c[m] = ChemC1[m];
|
|
726
|
-
for (i=1; i<=NumTankRateSpecies; i++)
|
|
727
|
-
{
|
|
728
|
-
m = TankRateSpecies[i];
|
|
729
|
-
TheSeg->c[m] = MAX(Yrate[i], 0.0);
|
|
730
|
-
}
|
|
731
|
-
TheSeg->hstep = dh;
|
|
732
|
-
}
|
|
733
|
-
if ( ierr < 0 ) return
|
|
734
|
-
ERR_INTEGRATOR;
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
// --- compute new equilibrium concentrations within segment
|
|
738
|
-
|
|
739
|
-
errcode = MSXchem_equil(NODE, k, TheSeg->c);
|
|
740
|
-
if ( errcode ) return errcode;
|
|
741
|
-
|
|
742
|
-
// --- move to the next tank segment
|
|
743
|
-
for (m = 1; m <= MSX.Nobjects[SPECIES]; m++)
|
|
744
|
-
{
|
|
745
|
-
if (MSX.Species[m].type == BULK)
|
|
746
|
-
{
|
|
747
|
-
MSX.Tank[k].reacted[m] += TheSeg->v * (TheSeg->c[m] - TheSeg->lastc[m]) * LperFT3;
|
|
748
|
-
}
|
|
749
|
-
TheSeg->lastc[m] = TheSeg->c[m];
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
TheSeg = TheSeg->prev;
|
|
753
|
-
}
|
|
754
|
-
return errcode;
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
//=============================================================================
|
|
758
|
-
|
|
759
|
-
int evalPipeEquil(double *c)
|
|
760
|
-
/*
|
|
761
|
-
** Purpose:
|
|
762
|
-
** computes equilibrium concentrations for water in a pipe segment.
|
|
763
|
-
**
|
|
764
|
-
** Input:
|
|
765
|
-
** c[] = array of starting species concentrations
|
|
766
|
-
**
|
|
767
|
-
** Output:
|
|
768
|
-
** c[] = array of equilibrium concentrations.
|
|
769
|
-
**
|
|
770
|
-
** Returns:
|
|
771
|
-
** an error code or 0 if no error.
|
|
772
|
-
*/
|
|
773
|
-
{
|
|
774
|
-
int i, m;
|
|
775
|
-
int errcode;
|
|
776
|
-
for (m=1; m<=NumSpecies; m++) ChemC1[m] = c[m];
|
|
777
|
-
for (i=1; i<=NumPipeEquilSpecies; i++)
|
|
778
|
-
{
|
|
779
|
-
m = PipeEquilSpecies[i];
|
|
780
|
-
Yequil[i] = c[m];
|
|
781
|
-
}
|
|
782
|
-
errcode = newton_solve(Yequil, NumPipeEquilSpecies, MAXIT, NUMSIG,
|
|
783
|
-
getPipeEquil);
|
|
784
|
-
if ( errcode < 0 ) return ERR_NEWTON;
|
|
785
|
-
for (i=1; i<=NumPipeEquilSpecies; i++)
|
|
786
|
-
{
|
|
787
|
-
m = PipeEquilSpecies[i];
|
|
788
|
-
c[m] = Yequil[i];
|
|
789
|
-
ChemC1[m] = c[m];
|
|
790
|
-
}
|
|
791
|
-
return 0;
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
//=============================================================================
|
|
796
|
-
|
|
797
|
-
int evalTankEquil(double *c)
|
|
798
|
-
/*
|
|
799
|
-
** Purpose:
|
|
800
|
-
** computes equilibrium concentrations for water in a tank.
|
|
801
|
-
**
|
|
802
|
-
** Input:
|
|
803
|
-
** c[] = array of starting species concentrations
|
|
804
|
-
**
|
|
805
|
-
** Output:
|
|
806
|
-
** c[] = array of equilibrium concentrations.
|
|
807
|
-
**
|
|
808
|
-
** Returns:
|
|
809
|
-
** an error code or 0 if no error.
|
|
810
|
-
*/
|
|
811
|
-
{
|
|
812
|
-
int i, m;
|
|
813
|
-
int errcode;
|
|
814
|
-
for (m=1; m<=NumSpecies; m++) ChemC1[m] = c[m];
|
|
815
|
-
for (i=1; i<=NumTankEquilSpecies; i++)
|
|
816
|
-
{
|
|
817
|
-
m = TankEquilSpecies[i];
|
|
818
|
-
Yequil[i] = c[m];
|
|
819
|
-
}
|
|
820
|
-
errcode = newton_solve(Yequil, NumTankEquilSpecies, MAXIT, NUMSIG,
|
|
821
|
-
getTankEquil);
|
|
822
|
-
if ( errcode < 0 ) return ERR_NEWTON;
|
|
823
|
-
for (i=1; i<=NumTankEquilSpecies; i++)
|
|
824
|
-
{
|
|
825
|
-
m = TankEquilSpecies[i];
|
|
826
|
-
c[m] = Yequil[i];
|
|
827
|
-
ChemC1[m] = c[m];
|
|
828
|
-
}
|
|
829
|
-
return 0;
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
//=============================================================================
|
|
833
|
-
|
|
834
|
-
void evalPipeFormulas(double *c)
|
|
835
|
-
/*
|
|
836
|
-
** Purpose:
|
|
837
|
-
** evaluates species concentrations in a pipe segment that are simple
|
|
838
|
-
** formulas involving other known species concentrations.
|
|
839
|
-
**
|
|
840
|
-
** Input:
|
|
841
|
-
** c[] = array of current species concentrations.
|
|
842
|
-
**
|
|
843
|
-
** Output:
|
|
844
|
-
** c[] = array of updated concentrations.
|
|
845
|
-
**
|
|
846
|
-
** Re-written to accommodate compiled functions (1.1)
|
|
847
|
-
*/
|
|
848
|
-
{
|
|
849
|
-
int m;
|
|
850
|
-
double x;
|
|
851
|
-
|
|
852
|
-
for (m=1; m<=NumSpecies; m++) ChemC1[m] = c[m];
|
|
853
|
-
// --- use compiled functions if available
|
|
854
|
-
|
|
855
|
-
if ( MSX.Compiler )
|
|
856
|
-
{
|
|
857
|
-
MSXgetPipeFormulas(ChemC1, MSX.K, MSX.Link[TheLink].param, HydVar);
|
|
858
|
-
for (m=1; m<=NumSpecies; m++)
|
|
859
|
-
{
|
|
860
|
-
if (MSX.Species[m].pipeExprType == FORMULA)
|
|
861
|
-
c[m] = MSXerr_validate(ChemC1[m], m, LINK, FORMULA);
|
|
862
|
-
}
|
|
863
|
-
return;
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
for (m=1; m<=NumSpecies; m++)
|
|
867
|
-
{
|
|
868
|
-
if ( MSX.Species[m].pipeExprType == FORMULA )
|
|
869
|
-
{
|
|
870
|
-
x = mathexpr_eval(MSX.Species[m].pipeExpr, getPipeVariableValue);
|
|
871
|
-
c[m] = MSXerr_validate(x, m, LINK, FORMULA);
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
//=============================================================================
|
|
877
|
-
|
|
878
|
-
void evalTankFormulas(double *c)
|
|
879
|
-
/*
|
|
880
|
-
** Purpose:
|
|
881
|
-
** evaluates species concentrations in a tank that are simple
|
|
882
|
-
** formulas involving other known species concentrations.
|
|
883
|
-
**
|
|
884
|
-
** Input:
|
|
885
|
-
** c[] = array of current species concentrations.
|
|
886
|
-
**
|
|
887
|
-
** Output:
|
|
888
|
-
** c[] = array of updated concentrations.
|
|
889
|
-
**
|
|
890
|
-
** Re-written to accommodate compiled functions (1.1)
|
|
891
|
-
*/
|
|
892
|
-
{
|
|
893
|
-
int m;
|
|
894
|
-
double x;
|
|
895
|
-
|
|
896
|
-
for (m=1; m<=NumSpecies; m++) ChemC1[m] = c[m];
|
|
897
|
-
|
|
898
|
-
// --- use compiled functions if available
|
|
899
|
-
|
|
900
|
-
if ( MSX.Compiler )
|
|
901
|
-
{
|
|
902
|
-
MSXgetTankFormulas(ChemC1, MSX.K, MSX.Link[TheLink].param, HydVar);
|
|
903
|
-
for (m=1; m<=NumSpecies; m++)
|
|
904
|
-
{
|
|
905
|
-
if (MSX.Species[m].tankExprType == FORMULA)
|
|
906
|
-
c[m] = MSXerr_validate(ChemC1[m], m, TANK, FORMULA);
|
|
907
|
-
}
|
|
908
|
-
return;
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
for (m=1; m<=NumSpecies; m++)
|
|
912
|
-
{
|
|
913
|
-
if ( MSX.Species[m].tankExprType == FORMULA )
|
|
914
|
-
{
|
|
915
|
-
x = mathexpr_eval(MSX.Species[m].tankExpr, getTankVariableValue);
|
|
916
|
-
c[m] = MSXerr_validate(x, m, TANK, FORMULA);
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
//=============================================================================
|
|
922
|
-
|
|
923
|
-
double getPipeVariableValue(int i)
|
|
924
|
-
/*
|
|
925
|
-
** Purpose:
|
|
926
|
-
** finds the value of a species, a parameter, or a constant for
|
|
927
|
-
** the pipe link being analyzed.
|
|
928
|
-
**
|
|
929
|
-
** Input:
|
|
930
|
-
** i = variable index.
|
|
931
|
-
**
|
|
932
|
-
** Returns:
|
|
933
|
-
** the current value of the indexed variable.
|
|
934
|
-
*/
|
|
935
|
-
{
|
|
936
|
-
double x;
|
|
937
|
-
|
|
938
|
-
// --- WQ species have index i between 1 & # of species
|
|
939
|
-
// and their current values are stored in vector ChemC1
|
|
940
|
-
|
|
941
|
-
if ( i <= LastIndex[SPECIES] )
|
|
942
|
-
{
|
|
943
|
-
// --- if species represented by a formula then evaluate it
|
|
944
|
-
|
|
945
|
-
if ( MSX.Species[i].pipeExprType == FORMULA )
|
|
946
|
-
{
|
|
947
|
-
x = mathexpr_eval(MSX.Species[i].pipeExpr, getPipeVariableValue);
|
|
948
|
-
return MSXerr_validate(x, i, LINK, FORMULA);
|
|
949
|
-
}
|
|
950
|
-
|
|
951
|
-
// --- otherwise return the current concentration
|
|
952
|
-
|
|
953
|
-
else return ChemC1[i];
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
// --- intermediate term expressions come next
|
|
957
|
-
|
|
958
|
-
else if ( i <= LastIndex[TERM] )
|
|
959
|
-
{
|
|
960
|
-
i -= LastIndex[TERM-1];
|
|
961
|
-
x = mathexpr_eval(MSX.Term[i].expr, getPipeVariableValue);
|
|
962
|
-
return MSXerr_validate(x, i, 0, TERM);
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
// --- reaction parameter indexes come after that
|
|
966
|
-
|
|
967
|
-
else if ( i <= LastIndex[PARAMETER] )
|
|
968
|
-
{
|
|
969
|
-
i -= LastIndex[PARAMETER-1];
|
|
970
|
-
return MSX.Link[TheLink].param[i];
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
// --- followed by constants
|
|
974
|
-
|
|
975
|
-
else if ( i <= LastIndex[CONSTANT] )
|
|
976
|
-
{
|
|
977
|
-
i -= LastIndex[CONSTANT-1];
|
|
978
|
-
return MSX.Const[i].value;
|
|
979
|
-
}
|
|
980
|
-
|
|
981
|
-
// --- and finally by hydraulic variables
|
|
982
|
-
else
|
|
983
|
-
{
|
|
984
|
-
i -= LastIndex[CONSTANT];
|
|
985
|
-
if (i < MAX_HYD_VARS) return HydVar[i];
|
|
986
|
-
else return 0.0;
|
|
987
|
-
}
|
|
988
|
-
}
|
|
989
|
-
|
|
990
|
-
//=============================================================================
|
|
991
|
-
|
|
992
|
-
double getTankVariableValue(int i)
|
|
993
|
-
/*
|
|
994
|
-
** Purpose:
|
|
995
|
-
** finds the value of a species, a parameter, or a constant for
|
|
996
|
-
** the current node being analyzed.
|
|
997
|
-
**
|
|
998
|
-
** Input:
|
|
999
|
-
** i = variable index.
|
|
1000
|
-
**
|
|
1001
|
-
** Returns:
|
|
1002
|
-
** the current value of the indexed variable.
|
|
1003
|
-
**
|
|
1004
|
-
** Modified to check for NaN values (L.Rossman - 11/03/10).
|
|
1005
|
-
*/
|
|
1006
|
-
{
|
|
1007
|
-
int j;
|
|
1008
|
-
double x;
|
|
1009
|
-
|
|
1010
|
-
// --- WQ species have index i between 1 & # of species
|
|
1011
|
-
// and their current values are stored in vector ChemC1
|
|
1012
|
-
|
|
1013
|
-
if ( i <= LastIndex[SPECIES] )
|
|
1014
|
-
{
|
|
1015
|
-
// --- if species represented by a formula then evaluate it
|
|
1016
|
-
|
|
1017
|
-
if ( MSX.Species[i].tankExprType == FORMULA )
|
|
1018
|
-
{
|
|
1019
|
-
x = mathexpr_eval(MSX.Species[i].tankExpr, getTankVariableValue);
|
|
1020
|
-
return MSXerr_validate(x, i, TANK, FORMULA);
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
|
-
// --- otherwise return the current concentration
|
|
1024
|
-
|
|
1025
|
-
else return ChemC1[i];
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
|
-
// --- intermediate term expressions come next
|
|
1029
|
-
|
|
1030
|
-
else if ( i <= LastIndex[TERM] )
|
|
1031
|
-
{
|
|
1032
|
-
i -= LastIndex[TERM-1];
|
|
1033
|
-
x = mathexpr_eval(MSX.Term[i].expr, getTankVariableValue);
|
|
1034
|
-
return MSXerr_validate(x, i, 0, TERM);
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
|
-
// --- next come reaction parameters associated with Tank nodes
|
|
1038
|
-
|
|
1039
|
-
else if (i <= LastIndex[PARAMETER] )
|
|
1040
|
-
{
|
|
1041
|
-
i -= LastIndex[PARAMETER-1];
|
|
1042
|
-
j = MSX.Node[TheNode].tank;
|
|
1043
|
-
if ( j > 0 )
|
|
1044
|
-
{
|
|
1045
|
-
return MSX.Tank[j].param[i];
|
|
1046
|
-
}
|
|
1047
|
-
else return 0.0;
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
|
-
// --- and then come constants
|
|
1051
|
-
|
|
1052
|
-
else if (i <= LastIndex[CONSTANT] )
|
|
1053
|
-
{
|
|
1054
|
-
i -= LastIndex[CONSTANT-1];
|
|
1055
|
-
return MSX.Const[i].value;
|
|
1056
|
-
}
|
|
1057
|
-
else return 0.0;
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
|
-
//=============================================================================
|
|
1061
|
-
|
|
1062
|
-
void getPipeDcDt(double t, double y[], int n, double deriv[])
|
|
1063
|
-
/*
|
|
1064
|
-
** Purpose:
|
|
1065
|
-
** finds reaction rate (dC/dt) for each reacting species in a pipe.
|
|
1066
|
-
**
|
|
1067
|
-
** Input:
|
|
1068
|
-
** t = current time (not used)
|
|
1069
|
-
** y[] = vector of reacting species concentrations
|
|
1070
|
-
** n = number of reacting species.
|
|
1071
|
-
**
|
|
1072
|
-
** Output:
|
|
1073
|
-
** deriv[] = vector of reaction rates of each reacting species.
|
|
1074
|
-
*/
|
|
1075
|
-
{
|
|
1076
|
-
int i, m;
|
|
1077
|
-
double x;
|
|
1078
|
-
|
|
1079
|
-
// --- assign species concentrations to their proper positions in the global
|
|
1080
|
-
// concentration vector ChemC1
|
|
1081
|
-
|
|
1082
|
-
for (i=1; i<=n; i++)
|
|
1083
|
-
{
|
|
1084
|
-
m = PipeRateSpecies[i];
|
|
1085
|
-
ChemC1[m] = y[i];
|
|
1086
|
-
}
|
|
1087
|
-
|
|
1088
|
-
// --- update equilibrium species if full coupling in use
|
|
1089
|
-
|
|
1090
|
-
if ( MSX.Coupling == FULL_COUPLING )
|
|
1091
|
-
{
|
|
1092
|
-
if ( MSXchem_equil(LINK, TheLink, ChemC1) > 0 ) // check for error condition
|
|
1093
|
-
{
|
|
1094
|
-
for (i=1; i<=n; i++) deriv[i] = 0.0;
|
|
1095
|
-
return;
|
|
1096
|
-
}
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
|
-
// --- use compiled functions if available
|
|
1100
|
-
|
|
1101
|
-
if ( MSX.Compiler )
|
|
1102
|
-
{
|
|
1103
|
-
MSXgetPipeRates(ChemC1, MSX.K, MSX.Link[TheLink].param, HydVar, F);
|
|
1104
|
-
for (i=1; i<=n; i++)
|
|
1105
|
-
{
|
|
1106
|
-
m = PipeRateSpecies[i];
|
|
1107
|
-
deriv[i] = MSXerr_validate(F[m], m, LINK, RATE);
|
|
1108
|
-
}
|
|
1109
|
-
return;
|
|
1110
|
-
}
|
|
1111
|
-
|
|
1112
|
-
// --- evaluate each pipe reaction expression
|
|
1113
|
-
|
|
1114
|
-
for (i=1; i<=n; i++)
|
|
1115
|
-
{
|
|
1116
|
-
m = PipeRateSpecies[i];
|
|
1117
|
-
x = mathexpr_eval(MSX.Species[m].pipeExpr, getPipeVariableValue);
|
|
1118
|
-
deriv[i] = MSXerr_validate(x, m, LINK, RATE);
|
|
1119
|
-
}
|
|
1120
|
-
}
|
|
1121
|
-
|
|
1122
|
-
//=============================================================================
|
|
1123
|
-
|
|
1124
|
-
void getTankDcDt(double t, double y[], int n, double deriv[])
|
|
1125
|
-
/*
|
|
1126
|
-
** Purpose:
|
|
1127
|
-
** finds reaction rate (dC/dt) for each reacting species in a tank.
|
|
1128
|
-
**
|
|
1129
|
-
** Input:
|
|
1130
|
-
** t = current time (not used)
|
|
1131
|
-
** y[] = vector of reacting species concentrations
|
|
1132
|
-
** n = number of reacting species.
|
|
1133
|
-
**
|
|
1134
|
-
** Output:
|
|
1135
|
-
** deriv[] = vector of reaction rates of each reacting species.
|
|
1136
|
-
*/
|
|
1137
|
-
{
|
|
1138
|
-
int i, m;
|
|
1139
|
-
double x;
|
|
1140
|
-
|
|
1141
|
-
// --- assign species concentrations to their proper positions in the global
|
|
1142
|
-
// concentration vector ChemC1
|
|
1143
|
-
|
|
1144
|
-
for (i=1; i<=n; i++)
|
|
1145
|
-
{
|
|
1146
|
-
m = TankRateSpecies[i];
|
|
1147
|
-
ChemC1[m] = y[i];
|
|
1148
|
-
}
|
|
1149
|
-
|
|
1150
|
-
// --- update equilibrium species if full coupling in use
|
|
1151
|
-
|
|
1152
|
-
if ( MSX.Coupling == FULL_COUPLING )
|
|
1153
|
-
{
|
|
1154
|
-
if ( MSXchem_equil(NODE, TheTank, ChemC1) > 0 ) // check for error condition
|
|
1155
|
-
{
|
|
1156
|
-
for (i=1; i<=n; i++) deriv[i] = 0.0;
|
|
1157
|
-
return;
|
|
1158
|
-
}
|
|
1159
|
-
}
|
|
1160
|
-
|
|
1161
|
-
// --- use compiled functions if available
|
|
1162
|
-
|
|
1163
|
-
if ( MSX.Compiler )
|
|
1164
|
-
{
|
|
1165
|
-
MSXgetTankRates(ChemC1, MSX.K, MSX.Tank[TheTank].param, HydVar, F);
|
|
1166
|
-
for (i=1; i<=n; i++)
|
|
1167
|
-
{
|
|
1168
|
-
m = TankRateSpecies[i];
|
|
1169
|
-
deriv[i] = MSXerr_validate(F[m], m, TANK, RATE);
|
|
1170
|
-
}
|
|
1171
|
-
return;
|
|
1172
|
-
}
|
|
1173
|
-
|
|
1174
|
-
// --- evaluate each tank reaction expression
|
|
1175
|
-
|
|
1176
|
-
for (i=1; i<=n; i++)
|
|
1177
|
-
{
|
|
1178
|
-
m = TankRateSpecies[i];
|
|
1179
|
-
x = mathexpr_eval(MSX.Species[m].tankExpr, getTankVariableValue);
|
|
1180
|
-
deriv[i] = MSXerr_validate(x, m, TANK, RATE);
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
|
-
|
|
1184
|
-
//=============================================================================
|
|
1185
|
-
|
|
1186
|
-
void getPipeEquil(double t, double y[], int n, double f[])
|
|
1187
|
-
/*
|
|
1188
|
-
** Purpose:
|
|
1189
|
-
** evaluates equilibrium expressions for pipe chemistry.
|
|
1190
|
-
**
|
|
1191
|
-
** Input:
|
|
1192
|
-
** t = current time (not used)
|
|
1193
|
-
** y[] = vector of equilibrium species concentrations
|
|
1194
|
-
** n = number of equilibrium species.
|
|
1195
|
-
**
|
|
1196
|
-
** Output:
|
|
1197
|
-
** f[] = vector of equilibrium function values.
|
|
1198
|
-
*/
|
|
1199
|
-
{
|
|
1200
|
-
int i, m;
|
|
1201
|
-
double x;
|
|
1202
|
-
|
|
1203
|
-
// --- assign species concentrations to their proper positions in the global
|
|
1204
|
-
// concentration vector ChemC1
|
|
1205
|
-
|
|
1206
|
-
for (i=1; i<=n; i++)
|
|
1207
|
-
{
|
|
1208
|
-
m = PipeEquilSpecies[i];
|
|
1209
|
-
ChemC1[m] = y[i];
|
|
1210
|
-
}
|
|
1211
|
-
|
|
1212
|
-
// --- use compiled functions if available
|
|
1213
|
-
|
|
1214
|
-
if ( MSX.Compiler )
|
|
1215
|
-
{
|
|
1216
|
-
MSXgetPipeEquil(ChemC1, MSX.K, MSX.Link[TheLink].param, HydVar, F);
|
|
1217
|
-
for (i=1; i<=n; i++)
|
|
1218
|
-
{
|
|
1219
|
-
m = PipeEquilSpecies[i];
|
|
1220
|
-
f[i] = MSXerr_validate(F[m], m, LINK, EQUIL);
|
|
1221
|
-
}
|
|
1222
|
-
return;
|
|
1223
|
-
}
|
|
1224
|
-
|
|
1225
|
-
// --- evaluate each pipe equilibrium expression
|
|
1226
|
-
|
|
1227
|
-
for (i=1; i<=n; i++)
|
|
1228
|
-
{
|
|
1229
|
-
m = PipeEquilSpecies[i];
|
|
1230
|
-
x = mathexpr_eval(MSX.Species[m].pipeExpr, getPipeVariableValue);
|
|
1231
|
-
f[i] = MSXerr_validate(x, m, LINK, EQUIL);
|
|
1232
|
-
}
|
|
1233
|
-
}
|
|
1234
|
-
|
|
1235
|
-
//=============================================================================
|
|
1236
|
-
|
|
1237
|
-
void getTankEquil(double t, double y[], int n, double f[])
|
|
1238
|
-
/*
|
|
1239
|
-
** Purpose:
|
|
1240
|
-
** evaluates equilibrium expressions for tank chemistry.
|
|
1241
|
-
**
|
|
1242
|
-
** Input:
|
|
1243
|
-
** t = current time (not used)
|
|
1244
|
-
** y[] = vector of equilibrium species concentrations
|
|
1245
|
-
** n = number of equilibrium species
|
|
1246
|
-
**
|
|
1247
|
-
** Output:
|
|
1248
|
-
** f[] = vector of equilibrium function values.
|
|
1249
|
-
*/
|
|
1250
|
-
{
|
|
1251
|
-
int i, m;
|
|
1252
|
-
double x;
|
|
1253
|
-
|
|
1254
|
-
// --- assign species concentrations to their proper positions in the global
|
|
1255
|
-
// concentration vector ChemC1
|
|
1256
|
-
|
|
1257
|
-
for (i=1; i<=n; i++)
|
|
1258
|
-
{
|
|
1259
|
-
m = TankEquilSpecies[i];
|
|
1260
|
-
ChemC1[m] = y[i];
|
|
1261
|
-
}
|
|
1262
|
-
|
|
1263
|
-
// --- use compiled functions if available
|
|
1264
|
-
|
|
1265
|
-
if ( MSX.Compiler )
|
|
1266
|
-
{
|
|
1267
|
-
MSXgetTankEquil(ChemC1, MSX.K, MSX.Tank[TheTank].param, HydVar, F);
|
|
1268
|
-
for (i=1; i<=n; i++)
|
|
1269
|
-
{
|
|
1270
|
-
m = TankEquilSpecies[i];
|
|
1271
|
-
f[i] = MSXerr_validate(F[m], m, TANK, EQUIL);
|
|
1272
|
-
}
|
|
1273
|
-
return;
|
|
1274
|
-
}
|
|
1275
|
-
|
|
1276
|
-
// --- evaluate each tank equilibrium expression
|
|
1277
|
-
|
|
1278
|
-
for (i=1; i<=n; i++)
|
|
1279
|
-
{
|
|
1280
|
-
m = TankEquilSpecies[i];
|
|
1281
|
-
x = mathexpr_eval(MSX.Species[m].tankExpr, getTankVariableValue);
|
|
1282
|
-
f[i] = MSXerr_validate(x, m, TANK, EQUIL);
|
|
1283
|
-
}
|
|
1284
|
-
}
|
|
1285
|
-
|