-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathIntegratorCVode.cpp
More file actions
196 lines (170 loc) · 6.4 KB
/
IntegratorCVode.cpp
File metadata and controls
196 lines (170 loc) · 6.4 KB
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
/* ----------------------------------------------------
NOTICE OF COPYRIGHT AND OWNERSHIP OF SOFTWARE
Copyright 2004, The Johns Hopkins University
School of Medicine. All rights reserved.
For research use only; commercial use prohibited.
Distribution without permission of Raimond L. Winslow
not permitted. rwinslow@bme.jhu.edu
Name of Program: Guinea Pig C++: Coupled, Algbraic, BB, MCA
Version: Documented Version, version 1.0.1
Date: August 2004
-----------------------------------------------------
*/
#include "integratorcvode.h"
//Define CVode F function
//Note: direct access of y, ydot is not constant
void func_f(long N, realtype time, N_Vector y, N_Vector ydot, void *f_data) {
((Model*)f_data)->F(time, N_VGetData(ydot), N_VGetData(y));
}
IntegratorCVode::IntegratorCVode(void) {
ropt = new double[OPT_SIZE];
iopt = new long[OPT_SIZE];
usingErrorWeights = true;
}
IntegratorCVode::~IntegratorCVode(void) {
N_VFree(cvode_y);
N_VFree(cvode_ic);
//N_VDispose(cvode_y);
N_VFree(ew);
CVodeFree(cvode_mem);
delete[] ropt;
delete[] iopt;
}
//Integrates the current problem, attempting to reach time
//State variables and actual time recorded in cvode_y, &cvode_t.
void IntegratorCVode::iterateToTime(double time) {
// call CVode to solve ydot(t)=f(y,t) with y(0) given
//Normal Mode
int flag = CVode(cvode_mem, time, cvode_y, &cvode_t, NORMAL);
//*
//One step mode: ONE_STEP
// int flag;
// while(cvode_t < time) {
// flag = CVode(cvode_mem, time, cvode_y, &cvode_t, ONE_STEP);
if (flag != SUCCESS) {
cout << "CVode failed, flag=" << flag << "." << endl;
// char c;
// cin >> c;
}
// }
}
//Initializes
void IntegratorCVode::setupCVode(Model *model) {
//Parameters: step_max, step_min, usingErrorWeights, start_time
N_Vector errweight;
machEnv = NULL;
machEnv = M_EnvInit_Serial(model->getProblemSize());
if (machEnv == NULL) {
cerr << "Trouble with MachEnv in CVODE" << endl;
exit(-3);
}
// Allocate memory for solution vector y(t)
cvode_y = N_VNew( model->getProblemSize(), machEnv);
// cvode_y = N_VMake( model->getProblemSize(), model->getStates(), machEnv);
// Allocate memory for solution vector ew(t)
ew = N_VNew( model->getProblemSize(), machEnv);
errweight = N_VMake( model->getProblemSize(), model->getErrorWeights(), machEnv);
// scale tolerance based on maximum value of state
N_VInv(errweight, ew);
N_VScale(abstol, ew, ew);
//Allocate and set cvode_ic
cvode_ic = N_VNew( model->getProblemSize(), machEnv);
N_Vector ic = N_VMake( model->getProblemSize(), model->getStates(), machEnv);
N_VAddConst(ic, 0.0, cvode_ic);
N_VDispose(ic);
// use default values for options
for(int i = 0; i < OPT_SIZE; i++) {
ropt[i]=0.0;
iopt[i]=0L;
}
//Set optional parameters
iopt[MXSTEP] = 1000000; //added by JT, taken from integrator.cpp of Canine model
ropt[HMAX] = step_max; // Largest step size
ropt[HMIN] = step_min; // Smallest step size
/* CVodeMalloc sets up initial settings for CVode. See
Integration method is BDF(Backward Differential Formula)
Other choice would be ADAMS but it is not as stable */
if (usingErrorWeights) {
// We wish to pass errorweight to CVODE
cvode_mem = CVodeMalloc(model->getProblemSize(), func_f, 0, cvode_ic, BDF,
NEWTON, SV, &reltol, ew , model, NULL, TRUE, iopt, ropt, machEnv);
} else {
// This method of calling CVODE does not pass error weights
cvode_mem = CVodeMalloc(model->getProblemSize(), func_f, 0, cvode_ic, BDF,
NEWTON, SS, &reltol, &abstol, model, NULL, TRUE, iopt, ropt, machEnv);
}
if ( cvode_mem == NULL ) {
cerr << "CVodeMalloc failed." << endl;
exit(1);
}
/* CVDense is needed by Newton algorithm for solving linear system
The second NULL tells the solver to compute an approximation of the Jacobian. */
CVDense(cvode_mem, NULL, NULL);
N_VDispose(errweight);
}
//Refresh the CVode integrator for another run
void IntegratorCVode::refreshCVode(Model *model) {
//Parameters: step_max, step_min, usingErrorWeights, start_time
int error;
N_Vector ic = N_VMake( model->getProblemSize(), model->getStates(), machEnv);
N_VAddConst(ic, 0.0, cvode_ic);
N_VDispose(ic);
/* CVodeMalloc sets up initial settings for CVode. See
Integration method is BDF(Backward Differential Formula)
Other choice would be ADAMS but it is not as stable */
if (usingErrorWeights) {
// We wish to pass errorweight to CVODE
error = CVReInit(cvode_mem, func_f, 0, cvode_ic, BDF,
NEWTON, SV, &reltol, ew , model, NULL, TRUE, iopt, ropt, machEnv);
} else {
// This method of calling CVODE does not pass error weights
error = CVReInit(cvode_mem, func_f, 0, cvode_ic, BDF,
NEWTON, SS, &reltol, &abstol, model, NULL, TRUE, iopt, ropt, machEnv);
}
if (SUCCESS != error) {
cout << "Error in IntegratorCVode::refreshCVode(), code :" << error << "." << endl;
exit(-1);
}
/* CVDense is needed by Newton algorithm for solving linear system
The second NULL tells the solver to compute an approximation of the Jacobian. */
CVDense(cvode_mem, NULL, NULL);
}
//Set all the parameters for the integrator
void IntegratorCVode::setParameters(fileIO& data) {
reltol = data["reltol"];
abstol = data["abstol"];
step_max = data["step_max"];
step_min = data["step_min"];
start_time = data["start_time"];
stepsize = data["stepsize"];
cvode_t = start_time;
usingErrorWeights = data.getBoolean("usingErrorWeights");
}
//Do a single integration of the model
void IntegratorCVode::integrateModel(Model *model, fileIO *out, int runNumber) {
//Some stimulas mode parameters
// model->setInitialConditions(*out);
model->setupIFmode(runNumber);
//CVode Refresh -> Initial conditions:
refreshCVode(model);
//during each iteration of this loop, an experiment object is set up. A set of statevalues
//is also computed.
double stopTime = model->getStopTime();
//Since we don't want to max out intermediate steps getting to time t
for(double t = stepsize; t < start_time; ) {
//Periodic output to let you know how it's going
for(int i = 0; (t < start_time) && (i < 1000); i++, t = cvode_t + stepsize) {
iterateToTime(t);
}
cout<<'.';
}
for(double t = start_time + stepsize; t < stopTime; ) {
//Periodic output to let you know how it's going
for(int i = 0; (t < stopTime) && (i < 1000); i++, t = cvode_t + stepsize) {
iterateToTime(t);
out->writeLnOutputFiles( N_VGetData(cvode_y), cvode_t, model);
}
cout<<'.';
}
cout << "Complete." << endl;
}