epanet-plus 0.0.1__cp39-cp39-macosx_10_9_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-39-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 +10 -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,524 @@
|
|
|
1
|
+
/*******************************************************************************
|
|
2
|
+
** MODULE: MSXUTILS.C
|
|
3
|
+
** PROJECT: EPANET-MSX
|
|
4
|
+
** DESCRIPTION: Utility functions used by the EPANET Multi-Species Extension
|
|
5
|
+
** toolkit.
|
|
6
|
+
** AUTHORS: see AUTHORS
|
|
7
|
+
** Copyright: see AUTHORS
|
|
8
|
+
** License: see LICENSE
|
|
9
|
+
** VERSION: 2.0.00
|
|
10
|
+
** LAST UPDATE: 2/8/11
|
|
11
|
+
*******************************************************************************/
|
|
12
|
+
|
|
13
|
+
#include <stdlib.h>
|
|
14
|
+
#include <stdio.h>
|
|
15
|
+
#include <string.h>
|
|
16
|
+
#include <math.h>
|
|
17
|
+
#include <float.h>
|
|
18
|
+
|
|
19
|
+
#include "msxutils.h"
|
|
20
|
+
// --- define WINDOWS
|
|
21
|
+
|
|
22
|
+
#undef WINDOWS
|
|
23
|
+
#ifdef _WIN32
|
|
24
|
+
#define WINDOWS
|
|
25
|
+
#endif
|
|
26
|
+
#ifdef __WIN32__
|
|
27
|
+
#define WINDOWS
|
|
28
|
+
#endif
|
|
29
|
+
|
|
30
|
+
#define UCHAR(x) (((x) >= 'a' && (x) <= 'z') ? ((x)&~32) : (x))
|
|
31
|
+
#define TINY1 1.0e-20
|
|
32
|
+
|
|
33
|
+
//=============================================================================
|
|
34
|
+
|
|
35
|
+
char * MSXutils_getTempName(char *s)
|
|
36
|
+
/*
|
|
37
|
+
** Purpose:
|
|
38
|
+
** gets the name of a temporary file with path name and periods stripped
|
|
39
|
+
**
|
|
40
|
+
** Input:
|
|
41
|
+
** s = character string (must be of size L_tmpnam)
|
|
42
|
+
**
|
|
43
|
+
** Returns:
|
|
44
|
+
** a pointer to the file name.
|
|
45
|
+
*/
|
|
46
|
+
{
|
|
47
|
+
#ifdef WINDOWS
|
|
48
|
+
char *ptr;
|
|
49
|
+
char fname[L_tmpnam];
|
|
50
|
+
unsigned int i;
|
|
51
|
+
|
|
52
|
+
// --- use tmpnam() function to create a temporary file name
|
|
53
|
+
tmpnam(fname);
|
|
54
|
+
|
|
55
|
+
// --- replace any '.' characters (they cause problems for some compilers)
|
|
56
|
+
for (i=0; i<strlen(fname); i++)
|
|
57
|
+
{
|
|
58
|
+
if ( fname[i] == '.' ) fname[i] = '_';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// --- set ptr to non-path portion of file name
|
|
62
|
+
ptr = strrchr(fname, '\\');
|
|
63
|
+
if ( ptr ) ++ptr;
|
|
64
|
+
else ptr = fname;
|
|
65
|
+
|
|
66
|
+
// --- use '.\' as path name to keep file in current directory
|
|
67
|
+
strcpy(s, ".\\");
|
|
68
|
+
strcat(s, ptr);
|
|
69
|
+
#else
|
|
70
|
+
// --- use system function mkstemp() to create a temporary file name
|
|
71
|
+
strcpy(s, "msxXXXXXX");
|
|
72
|
+
mkstemp(s);
|
|
73
|
+
#endif
|
|
74
|
+
return s;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
//=============================================================================
|
|
78
|
+
|
|
79
|
+
int MSXutils_strcomp(char *s1, char *s2)
|
|
80
|
+
/*
|
|
81
|
+
** Purpose:
|
|
82
|
+
** performs case insensitive comparison of two strings.
|
|
83
|
+
**
|
|
84
|
+
** Input:
|
|
85
|
+
** s1 = character string
|
|
86
|
+
** s2 = character string.
|
|
87
|
+
**
|
|
88
|
+
** Returns:
|
|
89
|
+
** 1 if strings are the same, 0 otherwise.
|
|
90
|
+
*/
|
|
91
|
+
{
|
|
92
|
+
int i;
|
|
93
|
+
for (i=0; UCHAR(s1[i]) == UCHAR(s2[i]); i++)
|
|
94
|
+
if (!s1[i+1] && !s2[i+1]) return(1);
|
|
95
|
+
return(0);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
//=============================================================================
|
|
99
|
+
|
|
100
|
+
int MSXutils_findmatch(char *s, char *keyword[])
|
|
101
|
+
/*
|
|
102
|
+
** Purpose:
|
|
103
|
+
** finds a match between a string and an array of keyword strings.
|
|
104
|
+
**
|
|
105
|
+
** Input:
|
|
106
|
+
** s = character string
|
|
107
|
+
** keyword = array of keyword strings.
|
|
108
|
+
**
|
|
109
|
+
** Returns:
|
|
110
|
+
** index of matching keyword or -1 if no match found.
|
|
111
|
+
*/
|
|
112
|
+
{
|
|
113
|
+
int i = 0;
|
|
114
|
+
while (keyword[i] != NULL)
|
|
115
|
+
{
|
|
116
|
+
if (MSXutils_match(s, keyword[i])) return(i);
|
|
117
|
+
i++;
|
|
118
|
+
}
|
|
119
|
+
return(-1);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
//=============================================================================
|
|
123
|
+
|
|
124
|
+
int MSXutils_match(char *str, char *substr)
|
|
125
|
+
/*
|
|
126
|
+
** Purpose:
|
|
127
|
+
** sees if a sub-string of characters appears in a string
|
|
128
|
+
** (not case sensitive).
|
|
129
|
+
**
|
|
130
|
+
** Input:
|
|
131
|
+
** str = character string being searched
|
|
132
|
+
** substr = sub-string being searched for.
|
|
133
|
+
**
|
|
134
|
+
** Returns:
|
|
135
|
+
** 1 if sub-string found, 0 if not.
|
|
136
|
+
*/
|
|
137
|
+
{
|
|
138
|
+
int i,j;
|
|
139
|
+
|
|
140
|
+
// --- fail if substring is empty
|
|
141
|
+
if (!substr[0]) return(0);
|
|
142
|
+
|
|
143
|
+
// --- skip leading blanks of str
|
|
144
|
+
for (i=0; str[i]; i++)
|
|
145
|
+
if (str[i] != ' ') break;
|
|
146
|
+
|
|
147
|
+
// --- check if substr matches remainder of str
|
|
148
|
+
for (i=i,j=0; substr[j]; i++,j++)
|
|
149
|
+
if (!str[i] || UCHAR(str[i]) != UCHAR(substr[j]))
|
|
150
|
+
return(0);
|
|
151
|
+
return(1);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
//=============================================================================
|
|
155
|
+
|
|
156
|
+
int MSXutils_strToSeconds(char *s, long *seconds)
|
|
157
|
+
/*
|
|
158
|
+
** Purpose:
|
|
159
|
+
** converts a string in either decimal hours or hr:min:sec
|
|
160
|
+
** format to number of seconds.
|
|
161
|
+
**
|
|
162
|
+
** Input:
|
|
163
|
+
** s = string value of a time.
|
|
164
|
+
**
|
|
165
|
+
** Output:
|
|
166
|
+
** seconds = number of seconds.
|
|
167
|
+
**
|
|
168
|
+
** Returns:
|
|
169
|
+
** 1 if conversion successful, 0 if not.
|
|
170
|
+
*/
|
|
171
|
+
{
|
|
172
|
+
int n, hr = 0, min = 0, sec = 0;
|
|
173
|
+
double hours;
|
|
174
|
+
*seconds = 0;
|
|
175
|
+
if ( MSXutils_getDouble(s, &hours) )
|
|
176
|
+
{
|
|
177
|
+
*seconds = (long)(3600.0*hours);
|
|
178
|
+
return 1;
|
|
179
|
+
}
|
|
180
|
+
n = sscanf(s, "%d:%d:%d", &hr, &min, &sec);
|
|
181
|
+
if ( n == 0 ) return 0;
|
|
182
|
+
*seconds = 3600*hr + 60*min + sec;
|
|
183
|
+
return 1;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
//=============================================================================
|
|
187
|
+
|
|
188
|
+
int MSXutils_getInt(char *s, int *y)
|
|
189
|
+
/*
|
|
190
|
+
** Purpose:
|
|
191
|
+
** converts a string to an integer number.
|
|
192
|
+
**
|
|
193
|
+
** Input:
|
|
194
|
+
** s = a character string.
|
|
195
|
+
**
|
|
196
|
+
** Output:
|
|
197
|
+
** y = converted value of s.
|
|
198
|
+
**
|
|
199
|
+
** Returns:
|
|
200
|
+
** 1 if conversion successful, 0 if not.
|
|
201
|
+
*/
|
|
202
|
+
{
|
|
203
|
+
double x;
|
|
204
|
+
if ( MSXutils_getDouble(s, &x) )
|
|
205
|
+
{
|
|
206
|
+
if ( x < 0.0 ) x -= 0.01;
|
|
207
|
+
else x += 0.01;
|
|
208
|
+
*y = (int)x;
|
|
209
|
+
return 1;
|
|
210
|
+
}
|
|
211
|
+
*y = 0;
|
|
212
|
+
return 0;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
//=============================================================================
|
|
216
|
+
|
|
217
|
+
int MSXutils_getFloat(char *s, float *y)
|
|
218
|
+
/*
|
|
219
|
+
** Purpose:
|
|
220
|
+
** converts a string to a single precision floating point number.
|
|
221
|
+
**
|
|
222
|
+
** Input:
|
|
223
|
+
** s = a character string.
|
|
224
|
+
**
|
|
225
|
+
** Output:
|
|
226
|
+
** y = converted value of s
|
|
227
|
+
**
|
|
228
|
+
** Returns:
|
|
229
|
+
** 1 if conversion successful, 0 if not.
|
|
230
|
+
*/
|
|
231
|
+
{
|
|
232
|
+
char *endptr;
|
|
233
|
+
*y = (float) strtod(s, &endptr);
|
|
234
|
+
if (*endptr > 0) return(0);
|
|
235
|
+
return(1);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
//=============================================================================
|
|
239
|
+
|
|
240
|
+
int MSXutils_getDouble(char *s, double *y)
|
|
241
|
+
/*
|
|
242
|
+
** Purpose:
|
|
243
|
+
** converts a string to a double precision floating point number.
|
|
244
|
+
**
|
|
245
|
+
** Input:
|
|
246
|
+
** s = a character string.
|
|
247
|
+
**
|
|
248
|
+
** Output:
|
|
249
|
+
** y = converted value of s.
|
|
250
|
+
**
|
|
251
|
+
** Returns:
|
|
252
|
+
** 1 if conversion successful, 0 if not.
|
|
253
|
+
*/
|
|
254
|
+
{
|
|
255
|
+
char *endptr;
|
|
256
|
+
*y = strtod(s, &endptr);
|
|
257
|
+
if (*endptr > 0) return(0);
|
|
258
|
+
return(1);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
//=============================================================================
|
|
262
|
+
|
|
263
|
+
double ** createMatrix(int nrows, int ncols)
|
|
264
|
+
/*
|
|
265
|
+
** Purpose:
|
|
266
|
+
** allocates memory for a 2-dimensional array of doubles.
|
|
267
|
+
**
|
|
268
|
+
** Input:
|
|
269
|
+
** nrows = number of rows (0-based)
|
|
270
|
+
** ncols = number of columns (0-based).
|
|
271
|
+
**
|
|
272
|
+
** Returns:
|
|
273
|
+
** a pointer to the matrix (a = matrix(nr, nc)).
|
|
274
|
+
*/
|
|
275
|
+
{
|
|
276
|
+
int i,j;
|
|
277
|
+
double **a;
|
|
278
|
+
|
|
279
|
+
// --- allocate pointers to rows
|
|
280
|
+
|
|
281
|
+
a = (double **) malloc(nrows * sizeof(double *));
|
|
282
|
+
if ( !a ) return NULL;
|
|
283
|
+
|
|
284
|
+
// --- allocate rows and set pointers to them
|
|
285
|
+
|
|
286
|
+
a[0] = (double *) malloc (nrows * ncols * sizeof(double));
|
|
287
|
+
if ( !a[0] ) return NULL;
|
|
288
|
+
for ( i = 1; i < nrows; i++ ) a[i] = a[i-1] + ncols;
|
|
289
|
+
|
|
290
|
+
for ( i = 0; i < nrows; i++)
|
|
291
|
+
{
|
|
292
|
+
for ( j = 0; j < ncols; j++) a[i][j] = 0.0;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// --- return pointer to array of pointers to rows
|
|
296
|
+
|
|
297
|
+
return a;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
//=============================================================================
|
|
301
|
+
|
|
302
|
+
void freeMatrix(double **a)
|
|
303
|
+
/*
|
|
304
|
+
** Purpose:
|
|
305
|
+
** frees the memory allocated for a matrix of doubles.
|
|
306
|
+
**
|
|
307
|
+
** Input:
|
|
308
|
+
** a = pointer to a matrix of doubles.
|
|
309
|
+
*/
|
|
310
|
+
{
|
|
311
|
+
if ( a != NULL )
|
|
312
|
+
{
|
|
313
|
+
if ( a[0] != NULL ) free( a[0] );
|
|
314
|
+
free( a );
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
//=============================================================================
|
|
319
|
+
|
|
320
|
+
int factorize(double **a, int n, double *w, int *indx)
|
|
321
|
+
/*
|
|
322
|
+
** Purpose:
|
|
323
|
+
** performs an LU decomposition of a matrix.
|
|
324
|
+
**
|
|
325
|
+
** Input:
|
|
326
|
+
** a[1..n][1..n] = a square matrix of doubles
|
|
327
|
+
** n = matrix size (1-based)
|
|
328
|
+
** w[1..n] = work array of doubles.
|
|
329
|
+
**
|
|
330
|
+
** Output:
|
|
331
|
+
** a[][] = matrix that contains elements of L and U matrices
|
|
332
|
+
** indx[1..n] = vector that records the row permutation
|
|
333
|
+
** effected by the partial pivoting.
|
|
334
|
+
**
|
|
335
|
+
** Returns:
|
|
336
|
+
** 1 if successful, 0 if matrix is singular.
|
|
337
|
+
**
|
|
338
|
+
** Note:
|
|
339
|
+
** The arrays and matrices used in this function are 1-based, so
|
|
340
|
+
** they must have been sized to n+1 when first created.
|
|
341
|
+
*/
|
|
342
|
+
{
|
|
343
|
+
int i, imax, j, k;
|
|
344
|
+
double big, dum, sum, temp;
|
|
345
|
+
|
|
346
|
+
for (i = 1; i <= n; i++)
|
|
347
|
+
{
|
|
348
|
+
/*Loop over rows to get the implicit scaling information.*/
|
|
349
|
+
big = 0.0;
|
|
350
|
+
for (j = 1;j <= n;j++)
|
|
351
|
+
if ((temp = fabs(a[i][j])) > big) big = temp;
|
|
352
|
+
if (big == 0.0)
|
|
353
|
+
return 0; /* Warning for singular matrix*/
|
|
354
|
+
/*No nonzero largest element.*/
|
|
355
|
+
w[i] = 1.0/big; /*Save the scaling.*/
|
|
356
|
+
}
|
|
357
|
+
for (j = 1;j <= n;j++) /**for each column*/
|
|
358
|
+
{
|
|
359
|
+
/*This is the loop over columns of Crout�s method.*/
|
|
360
|
+
for (i = 1; i < j; i++)
|
|
361
|
+
{
|
|
362
|
+
/*Up from the diagonal*/
|
|
363
|
+
sum = a[i][j];
|
|
364
|
+
for (k = 1;k < i;k++) sum -= a[i][k]*a[k][j];
|
|
365
|
+
a[i][j] = sum;
|
|
366
|
+
}
|
|
367
|
+
big = 0.0; /*Initialize for the search for largest pivot element.*/
|
|
368
|
+
imax = j;
|
|
369
|
+
for (i = j; i <= n; i++)
|
|
370
|
+
{
|
|
371
|
+
sum = a[i][j];
|
|
372
|
+
for (k = 1; k < j; k++) sum -= a[i][k]*a[k][j];
|
|
373
|
+
a[i][j] = sum;
|
|
374
|
+
if ( (dum = w[i]*fabs(sum)) >= big)
|
|
375
|
+
{
|
|
376
|
+
big = dum;
|
|
377
|
+
imax = i;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
if (j != imax)
|
|
381
|
+
{
|
|
382
|
+
/*Do we need to interchange rows?*/
|
|
383
|
+
for (k = 1; k <= n; k++)
|
|
384
|
+
{
|
|
385
|
+
/*Yes,do so...*/
|
|
386
|
+
dum = a[imax][k];
|
|
387
|
+
a[imax][k] = a[j][k];
|
|
388
|
+
a[j][k] = dum;
|
|
389
|
+
}
|
|
390
|
+
w[imax] = w[j]; /* interchange the scale factor.*/
|
|
391
|
+
}
|
|
392
|
+
indx[j] = imax;
|
|
393
|
+
if (a[j][j] == 0.0) a[j][j] = TINY1;
|
|
394
|
+
if (j != n) /* divide by the pivot element.*/
|
|
395
|
+
{
|
|
396
|
+
dum = 1.0/(a[j][j]);
|
|
397
|
+
for (i = j+1;i <= n;i++) a[i][j] *= dum;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return 1;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
//=============================================================================
|
|
404
|
+
|
|
405
|
+
void solve(double **a, int n, int *indx, double b[])
|
|
406
|
+
/*
|
|
407
|
+
** Purpose:
|
|
408
|
+
** solves linear equations AX = B after LU decomposition of A.
|
|
409
|
+
**
|
|
410
|
+
** Input:
|
|
411
|
+
** a[1..n][1..n] = LU decomposed square matrix A returned by factorize
|
|
412
|
+
** n = matrix size
|
|
413
|
+
** indx[1..n] = permutation vector returned by factorize
|
|
414
|
+
** b[1..n] = right-hand side vector B.
|
|
415
|
+
**
|
|
416
|
+
** Output:
|
|
417
|
+
** b[1..n] = solution vector X.
|
|
418
|
+
**
|
|
419
|
+
** Note:
|
|
420
|
+
** The arrays and matrices used in this function are 1-based, so
|
|
421
|
+
** they must have been sized to n+1 when first created.
|
|
422
|
+
*/
|
|
423
|
+
{
|
|
424
|
+
int i, ii=0, ip, j;
|
|
425
|
+
double sum;
|
|
426
|
+
|
|
427
|
+
/*forward substitution */
|
|
428
|
+
for (i=1; i<=n; i++)
|
|
429
|
+
{
|
|
430
|
+
ip=indx[i];
|
|
431
|
+
sum=b[ip];
|
|
432
|
+
b[ip]=b[i];
|
|
433
|
+
if (ii)
|
|
434
|
+
for (j=ii; j<=i-1; j++)
|
|
435
|
+
sum -= a[i][j]*b[j];
|
|
436
|
+
else if (sum) ii=i;
|
|
437
|
+
b[i]=sum;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/* back substitution */
|
|
441
|
+
for (i=n; i>=1; i--)
|
|
442
|
+
{
|
|
443
|
+
sum=b[i];
|
|
444
|
+
for (j=i+1; j<=n; j++)
|
|
445
|
+
sum -= a[i][j]*b[j];
|
|
446
|
+
b[i]=sum/a[i][i];
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
//=============================================================================
|
|
451
|
+
|
|
452
|
+
void jacobian(double *x, int n, double *f, double *w, double **a,
|
|
453
|
+
void (*func)(double, double*, int, double*))
|
|
454
|
+
/*
|
|
455
|
+
** Purpose:
|
|
456
|
+
** computes Jacobian matrix of F(t,X) at given X
|
|
457
|
+
**
|
|
458
|
+
** Input:
|
|
459
|
+
** x[1..n] = vector of function variables
|
|
460
|
+
** n = number of variables
|
|
461
|
+
** f[1..n] = a work vector
|
|
462
|
+
** w[1..n] = a work vector
|
|
463
|
+
** func = user supplied routine that computes the function
|
|
464
|
+
** values at x.
|
|
465
|
+
**
|
|
466
|
+
** Output:
|
|
467
|
+
** f[1..n] = function values at x
|
|
468
|
+
** a[1..n][1..n] = coeffs. of the Jacobian matrix.
|
|
469
|
+
**
|
|
470
|
+
** Notes:
|
|
471
|
+
** 1. Arguments for func() are:
|
|
472
|
+
** t = independent variable (not used)
|
|
473
|
+
** x[1..n] = vector of dependent variables
|
|
474
|
+
** n = number of functions
|
|
475
|
+
** f[1..n] = function values at x.
|
|
476
|
+
**
|
|
477
|
+
** 2. The arrays and matrices used in this function are 1-based, so
|
|
478
|
+
** they must have been sized to n+1 when first created.
|
|
479
|
+
*/
|
|
480
|
+
{
|
|
481
|
+
|
|
482
|
+
int i, j;
|
|
483
|
+
double temp, eps = 1.0e-7, eps2;
|
|
484
|
+
|
|
485
|
+
for (j=1; j<=n; j++)
|
|
486
|
+
{
|
|
487
|
+
temp = x[j];
|
|
488
|
+
x[j] = temp + eps;
|
|
489
|
+
func(0.0, x, n, f);
|
|
490
|
+
if ( temp == 0.0 )
|
|
491
|
+
{
|
|
492
|
+
x[j] = temp;
|
|
493
|
+
eps2 = eps;
|
|
494
|
+
}
|
|
495
|
+
else
|
|
496
|
+
{
|
|
497
|
+
x[j] = temp - eps;
|
|
498
|
+
eps2 = 2.0*eps;
|
|
499
|
+
}
|
|
500
|
+
func(0.0, x, n, w);
|
|
501
|
+
for (i=1; i<=n; i++) a[i][j] = (f[i] - w[i]) / eps2;
|
|
502
|
+
x[j] = temp;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
/* --- An alternative method that uses forward differencing
|
|
507
|
+
int i,j;
|
|
508
|
+
double temp, h;
|
|
509
|
+
double eps = sqrt(DBL_EPSILON);
|
|
510
|
+
|
|
511
|
+
func(0.0, x, n, f);
|
|
512
|
+
for (j=1; j<=n; j++)
|
|
513
|
+
{
|
|
514
|
+
temp = x[j];
|
|
515
|
+
h = eps*fabs(temp);
|
|
516
|
+
if (h == 0.0) h = eps;
|
|
517
|
+
x[j] = temp + h;
|
|
518
|
+
func(0.0, x, n, w);
|
|
519
|
+
for (i=1; i<=n; i++) a[i][j] = (w[i] - f[i]) / h;
|
|
520
|
+
x[j] = temp;
|
|
521
|
+
}
|
|
522
|
+
*/
|
|
523
|
+
|
|
524
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/*******************************************************************************
|
|
2
|
+
** MODULE: MSXUTILS.H
|
|
3
|
+
** PROJECT: EPANET-MSX
|
|
4
|
+
** DESCRIPTION: Header file for the utility functions used by the EPANET
|
|
5
|
+
** Multi-Species Extension toolkit.
|
|
6
|
+
** AUTHORS: see AUTHORS
|
|
7
|
+
** Copyright: see AUTHORS
|
|
8
|
+
** License: see LICENSE
|
|
9
|
+
** VERSION: 2.0.00
|
|
10
|
+
** LAST UPDATE: 2/8/11
|
|
11
|
+
*******************************************************************************/
|
|
12
|
+
|
|
13
|
+
#ifndef MSXUTILS_H
|
|
14
|
+
#define MSXUTILS_H
|
|
15
|
+
|
|
16
|
+
// Gets the name of a temporary file
|
|
17
|
+
char * MSXutils_getTempName(char *s);
|
|
18
|
+
|
|
19
|
+
// Case insentive comparison of two strings
|
|
20
|
+
int MSXutils_strcomp(char *s1, char *s2);
|
|
21
|
+
|
|
22
|
+
// Matches a string against an array of keywords
|
|
23
|
+
int MSXutils_findmatch(char *s, char *keyword[]);
|
|
24
|
+
|
|
25
|
+
// Case insensitive search of a string for a substring
|
|
26
|
+
int MSXutils_match(char *str, char *substr);
|
|
27
|
+
|
|
28
|
+
// Converts a 24-hr clocktime to number of seconds
|
|
29
|
+
int MSXutils_strToSeconds(char *s, long *t);
|
|
30
|
+
|
|
31
|
+
// Converts a string to an integer
|
|
32
|
+
int MSXutils_getInt(char *s, int *y);
|
|
33
|
+
|
|
34
|
+
// Converts a string to a float
|
|
35
|
+
int MSXutils_getFloat(char *s, float *y);
|
|
36
|
+
|
|
37
|
+
// Converts a string to a double
|
|
38
|
+
int MSXutils_getDouble(char *s, double *y);
|
|
39
|
+
|
|
40
|
+
// Creates a two dimensional array
|
|
41
|
+
double ** createMatrix(int nrows, int ncols);
|
|
42
|
+
|
|
43
|
+
// Deletes a two dimensional array
|
|
44
|
+
void freeMatrix(double **a);
|
|
45
|
+
|
|
46
|
+
// Applies L-D factorization to a square matrix
|
|
47
|
+
int factorize(double **a, int n, double *w, int *indx);
|
|
48
|
+
|
|
49
|
+
// Solves a factorized, linear system of equations
|
|
50
|
+
void solve(double **a, int n, int *indx, double b[]);
|
|
51
|
+
|
|
52
|
+
// Computes the Jacobian matrix of a set of functions
|
|
53
|
+
void jacobian(double *x, int n, double *f, double *w, double **a,
|
|
54
|
+
void (*func)(double, double*, int, double*));
|
|
55
|
+
|
|
56
|
+
#endif
|