-
Notifications
You must be signed in to change notification settings - Fork 0
/
rksuite.h
336 lines (307 loc) · 13.6 KB
/
rksuite.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
#ifndef RKSUITE_H
#define RKSUITE_H
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <float.h>
#include <malloc.h>
/****************************************************************************
* RKSUITE/C++ - Conversion of RKSUITE to C++
*
* Conversion from FORTRAN to C by anonymous
* Conversion from C to C++ by
* D. F. Linton
* Millennium Engineering and Integration Company (MEI)
* 600 Jackson Court
* Satellite Beach, FL 32937 USA
*
* Changes are Open Source under the Lesser GPL.
*
* Not warrantied by MEI or the author. Use only after testing to confirm
* suitability for your application.
*
* Please read http://www.netlib.org/ode/rksuite/rksuite.doc before using.
*
* If you are not familiar with the routines of RKSUITE and how they are used
* to solve initial value problems, you should study the document rksuite.doc
* carefully before proceeding further. The following function documentation
* are simply "Brief Reminders" intended only to remind you of the meaning,
* type, and size requirements of the arguments.
*
****************************************************************************
*/
///////////////////////////////////////////////////////////////////////////////
/// @class RKSUITE
///
/// Used to create an integrator object.
///
/// All intermediate data is stored witin the object.
///
///////////////////////////////////////////////////////////////////////////////
class RKSUITE {
public:
/**
Create an instance of an RKSUITE integrator. The setup() method must be
called to initialize the integrator before use.
*/
RKSUITE() {
work = NULL;
lenint = 0;
wrkint = NULL;
}
/**
Destroy this instance of an HDSAPI application.
*/
~RKSUITE() {
if (work != NULL)
delete[] work;
if (wrkint != NULL)
delete[] wrkint;
}
/**
Configures and initializes this integrator object.
@param neq - The number of differential equations in the system.
Constraint: neq >= 1
@param tstart - The initial value of the independent variable.
@param ystart - The vector of initial values of the solution components.
@param tend - The integration proceeds from tstart in the direction of
tend. You cannot go past tend without calling reset() or setup() again.
@param tol - The relative error tolerance.
Constraint: 0.01D0 >= tol >= 10*MCHEPS
@param thres - threshold for the solution components.
Constraint: thres(L) >= SQRT(DWARF)
@param method - Specifies which Runge-Kutta pair is to be used.
1 - use the (2,3) pair, 2 - use the (4,5) pair, 3 - use the (7,8) pair
@param task - 'U' to use ut() or 'C' to use ct()
@param errass - bool, true to attempt to assess the true error.
@param hstart - if non-zero, use hstart as the first step size
@param mesage - bool, true if you want informative messages written to
standard output
*/
void setup(int neq, double tstart, double ystart[], double tend,
double tol, double thres[], int method, char* task,
bool errass, double hstart, bool mesage) {
this->neq = neq;
if (work != NULL)
delete[] work;
work = new double[32*neq];
if (wrkint != NULL)
delete[] wrkint;
lenint = 0;
setup( neq, tstart, ystart, tend, tol, thres, method, task, errass, hstart,
work, 32*neq, mesage );
};
/**
UT - the "usual" task. If all you want is to step to a time call this.
@param f - IN derivatives function (double tin, double yin[neq], double ypout[neq])
@param twant - IN next value of the independent variable
@param tgot - OUT acheived value of the independent variable
@param ygot - OUT approximate solution at tgot
@param ypgot - OUT approximate first derivatives at tgot
@param ymax - IN/OUT largest magnitude of ygot during integration. Do not alter.
@param uflag - OUT status, (1 - success, 2 - inefficient usage, 3 - work intensive,
4 - problem probably stiff, 5 - too much accuracy requested, 6 - global error
assessment unreliable beyond this point, 911 - catastrophic failure reported on
stdout.
*/
void ut(void (*f)(double, double*, double*), double twant, double& tgot,
double ygot[], double ypgot[], double ymax[], int& uflag) {
ut( f, twant, tgot, ygot, ypgot, ymax, work, uflag );
}
/**
Called to obtain some details about the integration.
@param totfnc - OUT total number of calls to the derivatives function
@param stpcst - OUT cost of a step in derivatives function calls
@param waste - OUT number of failed steps
@param stpsok - OUT number of accepted steps
@param hnext - step size the integrator plans to use for the next step
*/
void stat(int& totfcn, int& stpcst, double& waste, int& stpsok, double& hnext);
/**
If ERRASS was set .TRUE. in the call to SETUP, then after any call to UT
or CT to advance the integration to TNOW or TWANT, the subroutine GLBERR
may be called to obtain an assessment of the true error of the integration.
At each step and for each solution component Y(L), a more accurate "true"
solution YT(L), an average magnitude "size(L)" of its size, and its error
abs(Y(L) - YT(L))/max("size(L)",THRES(L))
are computed. The assessment returned in RMSERR(L) is the RMS (root-mean-
square) average of the error in the Lth solution component over all steps
of the integration from TSTART through TNOW.
@param rmserr - OUT approximate RMS error of solution elements
@param errmax - OUT maximum (approximate) true error taken over all
solution components and all steps from TSTART to TNOW.
@param terrmx - OUT First value of the independent variable where the
(approximate) true error attains the maximum value ERRMAX.
*/
void glberr(double rmserr[], double& errmax, double& terrmx) {
glberr( rmserr, errmax, terrmx, work );
}
/**
CT - the "complex" task. If need to check for events along the way call this.
@param f - IN derivatives function (double tin, double yin[neq], double ypout[neq])
@param tnow - OUT next value of the independent variable
@param ynow - OUT next value of the solution vector
@param ypnow - OUT first derivatives at tnow
@param cflag - OUT status, (1 - success, 2 - inefficient usage, 3 - work intensive,
4 - problem probably stiff, 5 - too much accuracy requested, 6 - global error
assessment unreliable beyond this point, 911 - catastrophic failure reported on
stdout.
*/
void ct(void (*f)(double, double*, double*), double& tnow, double ynow[],
double ypnow[], int& cflag) {
ct( f, tnow, ynow, ypnow, work, cflag );
}
/**
Obtain state and derivative values at intermediate points during the current step.
@param twant - IN next value of the independent variable
@param reqest - IN 'S' compute solution only, 'D' compute derivatives only, 'B' both
@param nwant - IN number of solution vector components to interpolate (generally neq)
@param ywant - OUT requested solution vector component elements
@param ypwant - OUT requested solution derivative vector component elements
@param f - IN derivatives function (double tin, double yin[neq], double ypout[neq])
*/
void intrp(double twant, char reqest[], int nwant, double ywant[], double ypwant[],
void (*f)(double, double*, double*)) {
int length = neq + ((neq > 5*nwant) ? neq : 5*nwant);
if (length != lenint) {
if (wrkint != NULL)
delete[] wrkint;
lenint = length;
wrkint = new double[lenint];
}
intrp( twant, reqest, nwant, ywant, ypwant, f, work, wrkint, lenint );
}
/**
Change the ending value of the independent variable
@param tendnu - new final value
*/
void reset(double tendnu);
/**
Prevent a program STOP after a "catastrophic" failure when using a routine from RKSUITE.
When a "catastrophic" failure is detected, the default action of
RKSUITE is to write an explanation to the standard output, and STOP.
This method can be used to prevent the STOP and so allow the program
to continue. To do this, you call SOFTFL with ON = true. You must then
call the method chkfl() after every call to an RKSUITE method to check whether
a catastrophic error occurred and take appropriate action if it did. Of
course, you may call setup() at any time to start a new problem, but calling
any other user-callable routine in RKSUITE after a catastrophic error will
lead to a STOP (even when "soft failure" has been set "on").
@param on - true to prevent stops
*/
void softfl(bool& on) {
softfl( false, on );
}
/**
Check if a catastrophic error has occured.
@param error - OUT bool, true if fatal error occured.
*/
void chkfl(bool& error) {
chkfl( true, error );
}
protected:
void setup(int neq, double tstart, double ystart[], double tend,
double tol, double thres[], int method, char* task,
bool errass, double hstart, double work[], int lenwrk,
bool mesage);
void ut(void (*f)(double, double*, double*), double twant, double& tgot,
double ygot[], double ypgot[], double ymax[], double work[], int& uflag);
void ct(void (*f)(double, double*, double*), double& tnow, double ynow[],
double ypnow[], double work[],int& cflag);
void intrp(double twant, char reqest[], int nwant, double ywant[], double ypwant[],
void (*f)(double, double*, double*), double work[], double wrkint[],
int lenint);
void glberr(double rmserr[], double& errmax, double& terrmx, double work[]);
void envirn(int& outch, double& mcheps, double& dwarf);
void softfl(bool ask, bool& on);
void chkfl(bool ask, bool& error);
void mconst(int method);
void rkconst(int method, int& vecstg, bool& reqstg, int& lintpl);
void rkmsg(int ier, const char* srname, int nrec, int& flag);
void rksit(bool ask, const char* srname, int& state);
void step(void (*f)(double, double*, double*), int neq, double tnow,
double* y, double* yp, double stages /* [neq][] */ [], double tol, double& htry,
double* weight, double* ynew, double* errest, double& err, bool main,
double hmin, double* thres, bool& phase2);
void stepa(double tnow, double y[], double yp[], double tstg, double ystg[],
double ypstg[], double& htry, double weight[], bool& cutbak);
void stepb(int neq, double y[], double yp[], double h, double ynew[],
double stages/*[neq][]*/[], double thres[], double& err, bool main,
double weight[]);
void stiff(void (*f)(double, double*, double*), double havg, int& jflstp,
bool toomch, int maxfcn, double work[], int& ier, int& nrec);
void stiffa(void (*f)(double, double*, double*),double x, double y[],
double hnow, double havg, double xend, int maxfcn, double wt[],
double fxy[], double v0[], bool& unsure, bool& stif, double v1[],
double v2[], double v3[], double vtemp[]);
void stiffb(double v1v1, double v0v1, double v0v0, double& rold,
double& rho, double root1[], double root2[], bool& rootre);
void stiffc(double alpha, double beta, double r1[], double r2[]);
void stiffd(double v[], double havg, double x, double y[],
void (*f)(double, double[], double[]), double fxy[], double wt[],
double scale, double vdotv, double z[], double& zdotz, double vtemp[]);
double dotprd(double u[], double v[], double wt[], int neq);
void evali(double y[], double yp[], double p /* [nwant][] */ [], double twant,
char reqest[], int nwant, double ywant[], double ypwant[]);
void formi(void (*f)(double, double*, double*), int neq, int nwant, double y[], double yp[],
double yold[], double ypold[], double stages/*[neq][]*/[], bool calstg,
double xstage[], double p[]);
void truerr(void (*f)(double, double*, double*), int neq, double y[],
double tol, double weight[], double zy[], double zyp[], double zerror[],
double zynew[], double zerres[], double zstage /* [neq][] */ [], int& ier);
double* work;
int neq;
int lenint;
double* wrkint;
struct
{
double tstrt, tnd, dir, hstrt, tolr;
int neqn;
} rkcom1;
struct
{
double t, h, told, hold;
int nfcn, svnfcn, okstp, flstp;
bool first, last;
} rkcom2;
struct
{
int prthrs, prerst, prwt, pryold, prscr,
pry, pryp, prstgs, printp, lnintp;
} rkcom3;
struct
{
double a[14][14], r[12][7];
double b[14], c[14], bhat[14], e[8];
int ptr[14];
int nstage, methd, mintp;
bool intp;
} rkcom4;
struct
{
double toosml, cost, safety, expon, stbrad, tanang,
rs, rs1, rs2, rs3, rs4;
int order, lststg, maxtry, nsec;
bool fsal;
} rkcom5;
struct
{
double maxerr, locmax;
int gnfcn, przstg, przy, przyp, przers, przerr, przynu;
bool erason, erasfl;
} rkcom6;
struct
{
double mcheps, dwarf, rndoff, sqrrmc, cubrmc, tiny;
int outch;
} rkcom7;
struct
{
bool msg, utask;
} rkcom8;
struct
{
char rec[10][80];
} rkcom9;
};
#endif