epanet-plus 0.0.1__cp310-cp310-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-310-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
epanet-msx-src/newton.c
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/******************************************************************************
|
|
2
|
+
** MODULE: NEWTON.C
|
|
3
|
+
** PROJECT: EPANET-MSX
|
|
4
|
+
** DESCRIPTION: Newton-Raphson algorithm used to solve a set of nonlinear
|
|
5
|
+
** algebraic equations.
|
|
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
|
+
|
|
13
|
+
#include <stdio.h>
|
|
14
|
+
#include <stdlib.h>
|
|
15
|
+
#include <string.h>
|
|
16
|
+
#include <math.h>
|
|
17
|
+
#include "msxutils.h"
|
|
18
|
+
#include "newton.h"
|
|
19
|
+
|
|
20
|
+
// Local declarations
|
|
21
|
+
//-------------------
|
|
22
|
+
MSXNewton MSXNewtonSolver;
|
|
23
|
+
|
|
24
|
+
#pragma omp threadprivate(MSXNewtonSolver)
|
|
25
|
+
|
|
26
|
+
//=============================================================================
|
|
27
|
+
|
|
28
|
+
int newton_open(int n)
|
|
29
|
+
/*
|
|
30
|
+
** Purpose:
|
|
31
|
+
** opens the algebraic solver to handle a system of n equations.
|
|
32
|
+
**
|
|
33
|
+
** Input:
|
|
34
|
+
** n = number of equations
|
|
35
|
+
**
|
|
36
|
+
** Returns:
|
|
37
|
+
** 1 if successful, 0 if not.
|
|
38
|
+
**
|
|
39
|
+
** Note:
|
|
40
|
+
** All arrays are 1-based so an extra memory location
|
|
41
|
+
** must be allocated for the unused 0-th position.
|
|
42
|
+
*/
|
|
43
|
+
{
|
|
44
|
+
int errorcode = 1;
|
|
45
|
+
|
|
46
|
+
#pragma omp parallel
|
|
47
|
+
{
|
|
48
|
+
MSXNewtonSolver.Nmax = 0;
|
|
49
|
+
MSXNewtonSolver.Indx = NULL;
|
|
50
|
+
MSXNewtonSolver.F = NULL;
|
|
51
|
+
MSXNewtonSolver.W = NULL;
|
|
52
|
+
MSXNewtonSolver.Indx = (int*)calloc(n + 1, sizeof(int));
|
|
53
|
+
MSXNewtonSolver.F = (double*)calloc(n + 1, sizeof(double));
|
|
54
|
+
MSXNewtonSolver.W = (double*)calloc(n + 1, sizeof(double));
|
|
55
|
+
MSXNewtonSolver.J = createMatrix(n + 1, n + 1);
|
|
56
|
+
#pragma omp critical
|
|
57
|
+
{
|
|
58
|
+
if (!MSXNewtonSolver.Indx || !MSXNewtonSolver.F || !MSXNewtonSolver.W || !MSXNewtonSolver.J)
|
|
59
|
+
errorcode = 0;
|
|
60
|
+
}
|
|
61
|
+
MSXNewtonSolver.Nmax = n;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return errorcode;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
//=============================================================================
|
|
68
|
+
|
|
69
|
+
void newton_close()
|
|
70
|
+
/*
|
|
71
|
+
** Purpose:
|
|
72
|
+
** closes the algebraic solver.
|
|
73
|
+
**
|
|
74
|
+
** Input:
|
|
75
|
+
** none
|
|
76
|
+
*/
|
|
77
|
+
{
|
|
78
|
+
|
|
79
|
+
#pragma omp parallel
|
|
80
|
+
{
|
|
81
|
+
if (MSXNewtonSolver.Indx) { free(MSXNewtonSolver.Indx); MSXNewtonSolver.Indx = NULL; }
|
|
82
|
+
if (MSXNewtonSolver.F) { free(MSXNewtonSolver.F); MSXNewtonSolver.F = NULL; }
|
|
83
|
+
if (MSXNewtonSolver.W) { free(MSXNewtonSolver.W); MSXNewtonSolver.W = NULL; }
|
|
84
|
+
freeMatrix(MSXNewtonSolver.J);
|
|
85
|
+
MSXNewtonSolver.J = NULL;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
//=============================================================================
|
|
91
|
+
|
|
92
|
+
int newton_solve(double x[], int n, int maxit, int numsig,
|
|
93
|
+
void (*func)(double, double*, int, double*))
|
|
94
|
+
/*
|
|
95
|
+
** Purpose:
|
|
96
|
+
** uses newton-raphson iterations to solve n nonlinear eqns.
|
|
97
|
+
**
|
|
98
|
+
** Input:
|
|
99
|
+
** x[] = solution vector
|
|
100
|
+
** n = number of equations
|
|
101
|
+
** maxit = max. number of iterations allowed
|
|
102
|
+
** numsig = number of significant digits in error
|
|
103
|
+
** func = pointer to the function that returns the function values at x.
|
|
104
|
+
**
|
|
105
|
+
** Returns:
|
|
106
|
+
** number of iterations if successful, -1 if Jacobian is singular,
|
|
107
|
+
** -2 if it didn't converge, or -3 if n exceeds allowable size.
|
|
108
|
+
**
|
|
109
|
+
** Note:
|
|
110
|
+
** the arguments to the function func are:
|
|
111
|
+
** t = a time value (not used here)
|
|
112
|
+
** x = vector of unknowns being solved for
|
|
113
|
+
** n = number of unknowns
|
|
114
|
+
** f = vector of function values evaluated at x.
|
|
115
|
+
*/
|
|
116
|
+
{
|
|
117
|
+
int i, k;
|
|
118
|
+
double errx, errmax, cscal, relconvg = pow(10.0, -numsig);
|
|
119
|
+
|
|
120
|
+
// --- check that system was sized adequetely
|
|
121
|
+
|
|
122
|
+
if ( n > MSXNewtonSolver.Nmax ) return -3;
|
|
123
|
+
|
|
124
|
+
// --- use up to maxit iterations to find a solution
|
|
125
|
+
|
|
126
|
+
for (k=1; k<=maxit; k++)
|
|
127
|
+
{
|
|
128
|
+
// --- evaluate the Jacobian matrix
|
|
129
|
+
|
|
130
|
+
jacobian(x, n, MSXNewtonSolver.F, MSXNewtonSolver.W, MSXNewtonSolver.J, func);
|
|
131
|
+
|
|
132
|
+
// --- factorize the Jacobian
|
|
133
|
+
|
|
134
|
+
if ( !factorize(MSXNewtonSolver.J, n, MSXNewtonSolver.W, MSXNewtonSolver.Indx) ) return -1;
|
|
135
|
+
|
|
136
|
+
// --- solve for the updates to x (returned in F)
|
|
137
|
+
|
|
138
|
+
for (i=1; i<=n; i++) MSXNewtonSolver.F[i] = -MSXNewtonSolver.F[i];
|
|
139
|
+
solve(MSXNewtonSolver.J, n, MSXNewtonSolver.Indx, MSXNewtonSolver.F);
|
|
140
|
+
|
|
141
|
+
// --- update solution x & check for convergence
|
|
142
|
+
|
|
143
|
+
errmax = 0.0;
|
|
144
|
+
for (i=1; i<=n; i++)
|
|
145
|
+
{
|
|
146
|
+
cscal = x[i];
|
|
147
|
+
if (cscal < relconvg) cscal = relconvg;
|
|
148
|
+
x[i] += MSXNewtonSolver.F[i];
|
|
149
|
+
errx = fabs(MSXNewtonSolver.F[i]/cscal);
|
|
150
|
+
if (errx > errmax) errmax = errx;
|
|
151
|
+
}
|
|
152
|
+
if (errmax <= relconvg) return k;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// --- return error code if no convergence
|
|
156
|
+
|
|
157
|
+
return -2;
|
|
158
|
+
}
|
epanet-msx-src/newton.h
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/******************************************************************************
|
|
2
|
+
** MODULE: NEWTON.H
|
|
3
|
+
** PROJECT: EPANET-MSX
|
|
4
|
+
** DESCRIPTION: header file for the equation solver contained in newton.c.
|
|
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
|
+
#ifndef NEWTON_H
|
|
13
|
+
#define NEWTON_H
|
|
14
|
+
|
|
15
|
+
typedef struct
|
|
16
|
+
{
|
|
17
|
+
int Nmax; // max. number of equations
|
|
18
|
+
int* Indx; // permutation vector of row indexes
|
|
19
|
+
double* F; // function & adjustment vector
|
|
20
|
+
double* W; // work vector
|
|
21
|
+
double** J; // Jacobian matrix
|
|
22
|
+
}MSXNewton;
|
|
23
|
+
|
|
24
|
+
// Opens the equation solver system
|
|
25
|
+
int newton_open(int n);
|
|
26
|
+
|
|
27
|
+
// Closes the equation solver system
|
|
28
|
+
void newton_close(void);
|
|
29
|
+
|
|
30
|
+
// Applies the solver to a specific system of equations
|
|
31
|
+
int newton_solve(double x[], int n, int maxit, int numsig,
|
|
32
|
+
void (*func)(double, double*, int, double*));
|
|
33
|
+
|
|
34
|
+
#endif
|
epanet-msx-src/rk5.c
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
/************************************************************************
|
|
2
|
+
** MODULE: RK5.C
|
|
3
|
+
** PROJECT: EPANET-MSX
|
|
4
|
+
** DESCRIPTION: Numerical solution of a system of first order
|
|
5
|
+
** ordinary differential equations dY/dt = F(t,Y).
|
|
6
|
+
** AUTHOR: L. Rossman, US EPA - NRMRL
|
|
7
|
+
** VERSION: 2.0.00
|
|
8
|
+
** LAST UPDATE: 04/14/2021
|
|
9
|
+
**
|
|
10
|
+
** This is an explicit Runge-Kutta method of order (4)5
|
|
11
|
+
** due to Dormand & Prince (with optional stepsize control).
|
|
12
|
+
** The code was adapted from the DOPRI5 code of E. Hairer
|
|
13
|
+
** and G. Wanner as described in:
|
|
14
|
+
** E. HAIRER, S.P. NORSETT AND G. WANNER, SOLVING ORDINARY
|
|
15
|
+
** DIFFERENTIAL EQUATIONS I. NONSTIFF PROBLEMS. 2ND EDITION.
|
|
16
|
+
** SPRINGER SERIES IN COMPUTATIONAL MATHEMATICS,
|
|
17
|
+
** SPRINGER-VERLAG (1993)
|
|
18
|
+
***********************************************************************/
|
|
19
|
+
|
|
20
|
+
#include <stdlib.h>
|
|
21
|
+
#include <math.h>
|
|
22
|
+
#include "rk5.h"
|
|
23
|
+
|
|
24
|
+
#define fmin(x,y) (((x)<=(y)) ? (x) : (y)) /* minimum of x and y */
|
|
25
|
+
#define fmax(x,y) (((x)>=(y)) ? (x) : (y)) /* maximum of x and y */
|
|
26
|
+
|
|
27
|
+
// Local variables
|
|
28
|
+
//-----------------
|
|
29
|
+
MSXRungeKutta MSXRungeKuttaSolver;
|
|
30
|
+
|
|
31
|
+
#pragma omp threadprivate(MSXRungeKuttaSolver)
|
|
32
|
+
//=============================================================================
|
|
33
|
+
|
|
34
|
+
int rk5_open(int n, int itmax, int adjust)
|
|
35
|
+
/*
|
|
36
|
+
** Purpose:
|
|
37
|
+
** Opens the RK5 solver to solve system of n equations
|
|
38
|
+
**
|
|
39
|
+
** Input:
|
|
40
|
+
** n = number of equtions
|
|
41
|
+
** itmax = maximum iterations allowed
|
|
42
|
+
** adjust = 1 if time step adjustment used, 0 if not
|
|
43
|
+
**
|
|
44
|
+
** Returns:
|
|
45
|
+
** 1 if successful and 0 if not.
|
|
46
|
+
*/
|
|
47
|
+
{
|
|
48
|
+
int n1 = n+1;
|
|
49
|
+
int errorcode = 1;
|
|
50
|
+
MSXRungeKuttaSolver.Report = NULL;
|
|
51
|
+
|
|
52
|
+
#pragma omp parallel
|
|
53
|
+
{
|
|
54
|
+
MSXRungeKuttaSolver.Nmax = 0;
|
|
55
|
+
MSXRungeKuttaSolver.Itmax = itmax;
|
|
56
|
+
MSXRungeKuttaSolver.Adjust = adjust;
|
|
57
|
+
MSXRungeKuttaSolver.Ynew = (double*)calloc(n1, sizeof(double));
|
|
58
|
+
MSXRungeKuttaSolver.Ak = (double*)calloc(6 * n1, sizeof(double));
|
|
59
|
+
#pragma omp critical
|
|
60
|
+
{
|
|
61
|
+
if (!MSXRungeKuttaSolver.Ynew || !MSXRungeKuttaSolver.Ak) errorcode = 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
MSXRungeKuttaSolver.Nmax = n;
|
|
65
|
+
MSXRungeKuttaSolver.K1 = (MSXRungeKuttaSolver.Ak);
|
|
66
|
+
MSXRungeKuttaSolver.K2 = ((MSXRungeKuttaSolver.Ak)+(n1));
|
|
67
|
+
MSXRungeKuttaSolver.K3 = ((MSXRungeKuttaSolver.Ak)+(2 * n1));
|
|
68
|
+
MSXRungeKuttaSolver.K4 = ((MSXRungeKuttaSolver.Ak)+(3 * n1));
|
|
69
|
+
MSXRungeKuttaSolver.K5 = ((MSXRungeKuttaSolver.Ak)+(4 * n1));
|
|
70
|
+
MSXRungeKuttaSolver.K6 = ((MSXRungeKuttaSolver.Ak)+(5 * n1));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return errorcode;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
//=============================================================================
|
|
77
|
+
|
|
78
|
+
void rk5_close()
|
|
79
|
+
/*
|
|
80
|
+
** Purpose:
|
|
81
|
+
** Closes the RK5 solver.
|
|
82
|
+
*/
|
|
83
|
+
{
|
|
84
|
+
|
|
85
|
+
#pragma omp parallel
|
|
86
|
+
{
|
|
87
|
+
if (MSXRungeKuttaSolver.Ynew) free(MSXRungeKuttaSolver.Ynew);
|
|
88
|
+
MSXRungeKuttaSolver.Ynew = NULL;
|
|
89
|
+
if (MSXRungeKuttaSolver.Ak) free(MSXRungeKuttaSolver.Ak);
|
|
90
|
+
MSXRungeKuttaSolver.Ak = NULL;
|
|
91
|
+
MSXRungeKuttaSolver.Nmax = 0;
|
|
92
|
+
MSXRungeKuttaSolver.Report = NULL;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
//=============================================================================
|
|
98
|
+
|
|
99
|
+
int rk5_integrate(double y[], int n, double t, double tnext,
|
|
100
|
+
double* htry, double atol[], double rtol[],
|
|
101
|
+
void (*func)(double, double*, int, double*))
|
|
102
|
+
/*
|
|
103
|
+
** Purpose:
|
|
104
|
+
** Integrates system of equations dY/dt = F(t,Y) over a
|
|
105
|
+
** given interval.
|
|
106
|
+
**
|
|
107
|
+
** Input:
|
|
108
|
+
** y[] = values of dependent variables at start of interval
|
|
109
|
+
** n = number of dependent variables
|
|
110
|
+
** t = value of independent variable at start of interval
|
|
111
|
+
** tnext = value of independent variable at end of interval
|
|
112
|
+
** htry = initial step size
|
|
113
|
+
** atol[] = absolute error tolerance on each dependent variable
|
|
114
|
+
** rtol[] = relative error tolerance on each dependent variable
|
|
115
|
+
** func = pointer to function that evaluates dY/dt at given
|
|
116
|
+
** values of t and Y.
|
|
117
|
+
**
|
|
118
|
+
** Output:
|
|
119
|
+
** y[] = values of dependent variables at end of interval
|
|
120
|
+
** htry = last step size used
|
|
121
|
+
**
|
|
122
|
+
** Returns:
|
|
123
|
+
** number of function evaluations if successful, -1 if not
|
|
124
|
+
** successful within Itmax iterations or -2 if step size
|
|
125
|
+
** shrinks to 0.
|
|
126
|
+
*/
|
|
127
|
+
{
|
|
128
|
+
double c2=0.20, c3=0.30, c4=0.80, c5=8.0/9.0;
|
|
129
|
+
double a21=0.20, a31=3.0/40.0, a32=9.0/40.0,
|
|
130
|
+
a41=44.0/45.0, a42=-56.0/15.0, a43=32.0/9.0,
|
|
131
|
+
a51=19372.0/6561.0, a52=-25360.0/2187.0, a53=64448.0/6561.0,
|
|
132
|
+
a54=-212.0/729.0, a61=9017.0/3168.0, a62=-355.0/33.0,
|
|
133
|
+
a63=46732.0/5247.0, a64=49.0/176.0, a65=-5103.0/18656.0,
|
|
134
|
+
a71=35.0/384.0, a73=500.0/1113.0, a74=125.0/192.0,
|
|
135
|
+
a75=-2187.0/6784.0, a76=11.0/84.0;
|
|
136
|
+
double e1=71.0/57600.0, e3=-71.0/16695.0, e4=71.0/1920.0,
|
|
137
|
+
e5=-17253.0/339200.0, e6=22.0/525.0, e7=-1.0/40.0;
|
|
138
|
+
|
|
139
|
+
double tnew, h, hmax, hnew, ytol, err, sk, fac, fac11 = 1.0;
|
|
140
|
+
int i;
|
|
141
|
+
|
|
142
|
+
// --- parameters for step size control
|
|
143
|
+
|
|
144
|
+
double UROUND = 2.3e-16;
|
|
145
|
+
double SAFE = 0.90;
|
|
146
|
+
double fac1 = 0.2;
|
|
147
|
+
double fac2 = 10.0;
|
|
148
|
+
double beta = 0.04;
|
|
149
|
+
double facold = 1.e-4;
|
|
150
|
+
double expo1 = 0.2 - beta*0.75;
|
|
151
|
+
double facc1 = 1.0/fac1;
|
|
152
|
+
double facc2 = 1.0/fac2;
|
|
153
|
+
|
|
154
|
+
// --- various counters
|
|
155
|
+
|
|
156
|
+
int nstep = 1;
|
|
157
|
+
int nfcn = 0;
|
|
158
|
+
int naccpt = 0;
|
|
159
|
+
int nrejct = 0;
|
|
160
|
+
int reject = 0;
|
|
161
|
+
int adjust = MSXRungeKuttaSolver.Adjust;
|
|
162
|
+
|
|
163
|
+
// --- initial function evaluation
|
|
164
|
+
|
|
165
|
+
func(t, y, n, MSXRungeKuttaSolver.K1);
|
|
166
|
+
nfcn++;
|
|
167
|
+
|
|
168
|
+
// --- initial step size
|
|
169
|
+
h = *htry;
|
|
170
|
+
hmax = tnext - t;
|
|
171
|
+
if (h == 0.0)
|
|
172
|
+
{
|
|
173
|
+
adjust = 1;
|
|
174
|
+
h = tnext - t;
|
|
175
|
+
for (i=1; i<=n; i++)
|
|
176
|
+
{
|
|
177
|
+
ytol = atol[i] + rtol[i]*fabs(y[i]);
|
|
178
|
+
if (MSXRungeKuttaSolver.K1[i] != 0.0)
|
|
179
|
+
h = fmin(h, (ytol/fabs(MSXRungeKuttaSolver.K1[i])));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
h = fmax(1.e-8, h);
|
|
183
|
+
|
|
184
|
+
// --- while not at end of time interval
|
|
185
|
+
|
|
186
|
+
while (t < tnext)
|
|
187
|
+
{
|
|
188
|
+
// --- check for zero step size
|
|
189
|
+
if (0.10*fabs(h) <= fabs(t)*UROUND) return -2;
|
|
190
|
+
|
|
191
|
+
// --- adjust step size if interval exceeded
|
|
192
|
+
if ((t + 1.01*h - tnext) > 0.0) h = tnext - t;
|
|
193
|
+
|
|
194
|
+
tnew = t + c2*h;
|
|
195
|
+
for (i=1; i<=n; i++)
|
|
196
|
+
MSXRungeKuttaSolver.Ynew[i] = y[i] + h*a21* MSXRungeKuttaSolver.K1[i];
|
|
197
|
+
func(tnew, MSXRungeKuttaSolver.Ynew, n, MSXRungeKuttaSolver.K2);
|
|
198
|
+
|
|
199
|
+
tnew = t + c3*h;
|
|
200
|
+
for (i=1; i<=n; i++)
|
|
201
|
+
MSXRungeKuttaSolver.Ynew[i] = y[i] + h*(a31* MSXRungeKuttaSolver.K1[i] + a32* MSXRungeKuttaSolver.K2[i]);
|
|
202
|
+
func(tnew, MSXRungeKuttaSolver.Ynew, n, MSXRungeKuttaSolver.K3);
|
|
203
|
+
|
|
204
|
+
tnew = t + c4*h;
|
|
205
|
+
for (i=1; i<=n; i++)
|
|
206
|
+
MSXRungeKuttaSolver.Ynew[i]=y[i] + h*(a41* MSXRungeKuttaSolver.K1[i] + a42* MSXRungeKuttaSolver.K2[i] + a43* MSXRungeKuttaSolver.K3[i]);
|
|
207
|
+
func(tnew, MSXRungeKuttaSolver.Ynew, n, MSXRungeKuttaSolver.K4);
|
|
208
|
+
|
|
209
|
+
tnew = t + c5*h;
|
|
210
|
+
for (i=1; i<=n; i++)
|
|
211
|
+
MSXRungeKuttaSolver.Ynew[i] = y[i] + h*(a51* MSXRungeKuttaSolver.K1[i] + a52* MSXRungeKuttaSolver.K2[i] + a53* MSXRungeKuttaSolver.K3[i]+a54* MSXRungeKuttaSolver.K4[i]);
|
|
212
|
+
func(tnew, MSXRungeKuttaSolver.Ynew, n, MSXRungeKuttaSolver.K5);
|
|
213
|
+
|
|
214
|
+
tnew = t + h;
|
|
215
|
+
for (i=1; i<=n; i++)
|
|
216
|
+
MSXRungeKuttaSolver.Ynew[i] = y[i] + h*(a61* MSXRungeKuttaSolver.K1[i] + a62* MSXRungeKuttaSolver.K2[i] +
|
|
217
|
+
a63* MSXRungeKuttaSolver.K3[i] + a64* MSXRungeKuttaSolver.K4[i] + a65* MSXRungeKuttaSolver.K5[i]);
|
|
218
|
+
func(tnew, MSXRungeKuttaSolver.Ynew, n, MSXRungeKuttaSolver.K6);
|
|
219
|
+
|
|
220
|
+
for (i=1; i<=n; i++)
|
|
221
|
+
MSXRungeKuttaSolver.Ynew[i] = y[i] + h*(a71* MSXRungeKuttaSolver.K1[i] + a73* MSXRungeKuttaSolver.K3[i] +
|
|
222
|
+
a74* MSXRungeKuttaSolver.K4[i] + a75* MSXRungeKuttaSolver.K5[i] + a76* MSXRungeKuttaSolver.K6[i]);
|
|
223
|
+
func(tnew, MSXRungeKuttaSolver.Ynew, n, MSXRungeKuttaSolver.K2);
|
|
224
|
+
nfcn += 6;
|
|
225
|
+
|
|
226
|
+
// --- step size adjustment
|
|
227
|
+
|
|
228
|
+
err = 0.0;
|
|
229
|
+
hnew = h;
|
|
230
|
+
if (adjust)
|
|
231
|
+
{
|
|
232
|
+
for (i=1; i<=n; i++)
|
|
233
|
+
MSXRungeKuttaSolver.K4[i] = (e1* MSXRungeKuttaSolver.K1[i] + e3* MSXRungeKuttaSolver.K3[i] + e4* MSXRungeKuttaSolver.K4[i] + e5* MSXRungeKuttaSolver.K5[i] +
|
|
234
|
+
e6* MSXRungeKuttaSolver.K6[i] + e7* MSXRungeKuttaSolver.K2[i])*h;
|
|
235
|
+
|
|
236
|
+
for (i=1; i<=n; i++)
|
|
237
|
+
{
|
|
238
|
+
sk = atol[i] + rtol[i]*fmax(fabs(y[i]), fabs(MSXRungeKuttaSolver.Ynew[i]));
|
|
239
|
+
sk = MSXRungeKuttaSolver.K4[i]/sk;
|
|
240
|
+
err = err + (sk*sk);
|
|
241
|
+
}
|
|
242
|
+
err = sqrt(err/n);
|
|
243
|
+
|
|
244
|
+
// --- computation of hnew
|
|
245
|
+
fac11 = pow(err, expo1);
|
|
246
|
+
fac = fac11/pow(facold, beta); // LUND-stabilization
|
|
247
|
+
fac = fmax(facc2, fmin(facc1, (fac/SAFE))); // must have FAC1 <= HNEW/H <= FAC2
|
|
248
|
+
hnew = h/fac;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// --- step is accepted
|
|
252
|
+
|
|
253
|
+
if( err <= 1.0 )
|
|
254
|
+
{
|
|
255
|
+
facold = fmax(err, 1.0e-4);
|
|
256
|
+
naccpt++;
|
|
257
|
+
for (i=1; i<=n; i++)
|
|
258
|
+
{
|
|
259
|
+
MSXRungeKuttaSolver.K1[i] = MSXRungeKuttaSolver.K2[i];
|
|
260
|
+
y[i] = MSXRungeKuttaSolver.Ynew[i];
|
|
261
|
+
}
|
|
262
|
+
t = t + h;
|
|
263
|
+
if ( adjust && t <= tnext ) *htry = h;
|
|
264
|
+
if (fabs(hnew) > hmax) hnew = hmax;
|
|
265
|
+
if (reject) hnew = fmin(fabs(hnew), fabs(h));
|
|
266
|
+
reject = 0;
|
|
267
|
+
if (MSXRungeKuttaSolver.Report) MSXRungeKuttaSolver.Report(t, y, n);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// --- step is rejected
|
|
271
|
+
|
|
272
|
+
else
|
|
273
|
+
{
|
|
274
|
+
if ( adjust ) hnew = h/fmin(facc1, (fac11/SAFE));
|
|
275
|
+
reject = 1;
|
|
276
|
+
if (naccpt >= 1) nrejct++;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// --- take another step
|
|
280
|
+
|
|
281
|
+
h = hnew;
|
|
282
|
+
if ( adjust ) *htry = h;
|
|
283
|
+
nstep++;
|
|
284
|
+
if (nstep >= MSXRungeKuttaSolver.Itmax) return -1;
|
|
285
|
+
}
|
|
286
|
+
return nfcn;
|
|
287
|
+
}
|
epanet-msx-src/rk5.h
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/************************************************************************
|
|
2
|
+
** MODULE: RK5.H
|
|
3
|
+
** PROJECT: EPANET-MSX
|
|
4
|
+
** DESCRIPTION: Header file for the ODE solver contained in RK5.C.
|
|
5
|
+
** AUTHOR: L. Rossman, US EPA - NRMRL
|
|
6
|
+
** VERSION: 2.0.00
|
|
7
|
+
** LAST UPDATE: 04/14/2021
|
|
8
|
+
***********************************************************************/
|
|
9
|
+
|
|
10
|
+
#ifndef RK5_H
|
|
11
|
+
#define RK5_H
|
|
12
|
+
|
|
13
|
+
typedef struct
|
|
14
|
+
{
|
|
15
|
+
int Nmax; // max. number of equations
|
|
16
|
+
int Itmax; // max. number of integration steps
|
|
17
|
+
int Adjust; // use adjustable step size
|
|
18
|
+
double* Ak; // work arrays
|
|
19
|
+
double* K1;
|
|
20
|
+
double* K2;
|
|
21
|
+
double* K3;
|
|
22
|
+
double* K4;
|
|
23
|
+
double* K5;
|
|
24
|
+
double* K6;
|
|
25
|
+
double* Ynew; // updated solution
|
|
26
|
+
void (*Report) (double, double*, int);
|
|
27
|
+
}MSXRungeKutta;
|
|
28
|
+
// Opens the ODE solver system
|
|
29
|
+
int rk5_open(int n, int itmax, int adjust);
|
|
30
|
+
|
|
31
|
+
// Closes the ODE solver system
|
|
32
|
+
void rk5_close(void);
|
|
33
|
+
|
|
34
|
+
// Applies the solver to integrate a specific system of ODEs
|
|
35
|
+
int rk5_integrate(double y[], int n, double t, double tnext,
|
|
36
|
+
double* htry, double atol[], double rtol[],
|
|
37
|
+
void (*func)(double, double*, int, double*));
|
|
38
|
+
|
|
39
|
+
#endif
|