28 sol_ =
new double[neq];
36 Jac_ =
new double*[neq];
37 for (
unsigned long i=0; i<neq; i++)
Jac_[i] =
new double[neq];
50 for (
unsigned long i=0; i<
neq_; i++)
delete []
Jac_[i];
63 if ( !need_jac_ )
ode_print_exit(
"the Jacobian matrix wasn't allocated for whichever solver was chosen (need_jac_ == false)");
71 for (i=0; i<
neq_; i++) {
78 for (j=0; j<
neq_; j++) Jout[j][i] = (g_[j] - f_[j])/delsol;
126 if (!
quiet_) printf(
" snap %li reached\n", isnap);
135 if (!
quiet_) printf(
" snap %li written\n", isnap);
146 if ( (
t_ + dt*1.01) >= tend )
153 for (
unsigned long i=0; i<
neq_; i++ ) {
164 if (tint <= 0.0)
ode_print_exit(
"tint must be greater than zero");
166 if (dt <= 0.0)
ode_print_exit(
"dt must be greater than or equal to 0");
171 if (dt <= 0)
ode_print_exit(
"dt must be greater than or equal to 0");
173 for (
unsigned long i=0; i<nsnap; i++) {
174 if (tsnap[i] <
t_)
ode_print_exit(
"snap times must be greater than or equal to the current time");
175 if (i > 0)
if (tsnap[i] <= tsnap[i-1])
ode_print_exit(
"snap times must monotonically increase");
185 double tend =
t_ + tint;
212 if (inter < 1)
ode_print_exit(
"inter must be greater than or equal to 1");
219 double tend =
t_ + tint;
222 std::vector<double> tout;
223 std::vector< std::vector<double> > solout;
230 for (i=0; i<
neq_; i++) solout[i].push_back(
sol_[i] );
231 tout.push_back(
t_ );
238 if ( j % inter == 0 ) {
240 for (i=0; i<
neq_; i++) solout[i].push_back(
sol_[i] );
241 tout.push_back(
t_ );
248 for (i=0; i<
neq_; i++) solout[i].push_back(
sol_[i] );
249 tout.push_back(
t_ );
252 for (i=0; i<
neq_; i++) {
254 ode_write(fnout.c_str(), solout[i].data(), solout[i].size());
257 ode_write(fnout.c_str(), tout.data(), tout.size());
273 double tend =
t_ + tint;
275 double *tsnap =
new double[nsnap];
276 for (i=0; i<nsnap; i++) tsnap[i] =
t_ + i*(tend -
t_)/double(nsnap - 1);
296 for (i=0; i<nsnap; i++) {
317 for (
unsigned long i=0; i<
neq_; i++)
sol_[i] = sol[i];
void ode_jac_(double *solin, double **Jout)
wrapper, calls ode_jac() and increments nJac;
virtual void after_capture(double t)
does any extra stuff only when a step is captured
double reljacdel_
relative adjustment fraction for numerical Jacobian, if needed
OdeBase(unsigned long neq, bool need_jac)
constructs
long unsigned icheck_
interval of steps after which to check for nans and infs (zero to ignore)
unsigned long neq_
number of equations in the system of ODEs
void step(double dt, bool extra=true)
increments the step counter and the time, checks the solution integrity if needed,...
void solve_fixed(double tint, double dt, bool extras=true)
integrates for a specified duration of independent variable without output
bool solve_done(double dt, double tend)
checks if the solution is within a single time step of the end point
double t_
time, initialized to zero
long unsigned nJac_
counter for jacobian evaluations
std::string name_
the "name" of the system, which is used for output
virtual void ode_jac(double *solin, double **Jout)
evaluates the system's Jacobian matrix, also in autonomous form, and can either be defined in a deriv...
virtual void after_snap(std::string dirout, long isnap, double t)
does any extra stuff after each snap
virtual void before_solve()
does any extra stuff before starting a solve
virtual void after_solve()
does any extra stuff after completing a solve
double dt_
time step is stored and updated during solves
void snap(std::string dirout, long isnap, double tsnap)
writes the current value of the solution to a binary file
virtual ~OdeBase()
destructs
long unsigned nstep_
number of time steps
virtual void step_(double dt)=0
advances a single time step (without changing counters or the time) and must be defined in the derive...
bool quiet_
whether stuff should be printed during a solve
virtual void ode_fun(double *solin, double *fout)=0
evaluates the system of ODEs in autonomous form and must be defined by a derived class
void check_sol_integrity()
checks solution for nans and infs, exiting the program if they're found
double ** Jac_
storage for the ODE system's Jacobian matrix, only allocated for the methods that need it
void reset(double t, double *sol)
reset to a specified time and initial condition array
void solve_fixed_(double tint, double dt, bool extra=true)
integrates without output or any counters, trackers, extra functions...
bool silent_snap_
whether to skip writing the solution vector to file when snapping but still execute after_snap()
double absjacdel_
absolute adjustment fraction for numerical Jacobian, if needed
void check_pre_snaps(double dt, double *tsnap, unsigned long nsnap)
checks that snap times are monotonically increasing and > current time
double * sol_
array for the solution, changing over time
void ode_fun_(double *solin, double *fout)
wrapper, calls ode_fun() and increases the neval counter by one
virtual void after_step(double t)
does any extra stuff after each step
long unsigned neval_
function evaluation counter, must be incremented in step() when defined
void check_pre_solve(double tint, double dt)
checks that a solve can be performed with given tend and dt values
std::string dirout_
output directory if one is being used by a solver
double ode_max2(double a, double b)
Simple maximum of two doubles.
void ode_print_exit(const char *msg)
print a message and exit with failure
void ode_write(char const *fn, T *a, unsigned long n)
write an array to a binary file
std::string ode_int_to_string(long i)
converts an integer into a string