39#include "AbstractCvodeSystem.hpp"
40#include "CvodeAdaptor.hpp"
43#include "TimeStepper.hpp"
47#include <cvode/cvode.h>
48#include <sundials/sundials_nvector.h>
50#if CHASTE_SUNDIALS_VERSION < 70000
51#include <cvode/cvode_direct.h>
53#include <sundials/sundials_types.h>
54#include <sunlinsol/sunlinsol_dense.h>
55#include <sunmatrix/sunmatrix_dense.h>
57#if CHASTE_SUNDIALS_VERSION >= 60000
58#include "CvodeContextManager.hpp"
81int AbstractCvodeSystemRhsAdaptor(realtype t,
N_Vector y,
N_Vector ydot,
void* pData)
83 assert(pData !=
nullptr);
91 std::cerr <<
"CVODE RHS Exception: " << e.GetMessage()
116int AbstractCvodeSystemJacAdaptor(realtype t,
N_Vector y,
N_Vector ydot, CHASTE_CVODE_DENSE_MATRIX jacobian,
119 assert(pData !=
nullptr);
127 std::cerr <<
"CVODE Jacobian Exception: " << e.GetMessage() << std::endl
136 mLastSolutionState(nullptr),
137 mLastSolutionTime(0.0),
139 mForceMinimalReset(false),
140 mpSundialsDenseMatrix(nullptr),
141 mpSundialsLinearSolver(nullptr),
142 mHasAnalyticJacobian(false),
143 mUseAnalyticJacobian(false),
145#if CHASTE_SUNDIALS_VERSION >= 60000
146 mpSundialsContextManager(CvodeContextManager::Instance()),
149 mLastInternalStepSize(0)
159#if CHASTE_SUNDIALS_VERSION >= 60000
190 assert(tEnd >= tStart);
209 assert(ierr == CV_SUCCESS);
216 double cvode_stopped_at = stepper.
GetTime();
218 &cvode_stopped_at, CV_NORMAL);
225 assert(fabs(cvode_stopped_at - stepper.
GetNextTime()) < DBL_EPSILON);
231 solutions.
rGetTimes().push_back(cvode_stopped_at);
239 assert(ierr == CV_SUCCESS);
251 assert(tEnd >= tStart);
256 int ierr = CVodeSetStopTime(
mpCvodeMem, tEnd);
257 assert(ierr == CV_SUCCESS);
260 double cvode_stopped_at = tStart;
265 CvodeError(ierr,
"CVODE failed to solve system", cvode_stopped_at, tStart, tEnd);
268 assert(fabs(cvode_stopped_at - tEnd) < DBL_EPSILON);
271 assert(ierr == CV_SUCCESS);
371 assert(maxDt >= 0.0);
379 for (
unsigned i = 0; i < size; i++)
392#if CHASTE_SUNDIALS_VERSION >= 60000
393 mpCvodeMem = CVodeCreate(CV_BDF, CvodeContextManager::Instance()->GetSundialsContext());
403#if CHASTE_SUNDIALS_VERSION >= 70000
404 SUNContext_PushErrHandler(CvodeContextManager::Instance()->GetSundialsContext(), CvodeErrorHandler,
nullptr);
406 CVodeSetErrHandlerFn(
mpCvodeMem, CvodeErrorHandler,
nullptr);
411 CVodeInit(
mpCvodeMem, AbstractCvodeSystemRhsAdaptor, tStart, initialConditions);
414#if CHASTE_SUNDIALS_VERSION >= 60000
416 mpSundialsDenseMatrix = SUNDenseMatrix(NV_LENGTH_S(initialConditions), NV_LENGTH_S(initialConditions), CvodeContextManager::Instance()->GetSundialsContext());
419 mpSundialsDenseMatrix = SUNDenseMatrix(NV_LENGTH_S(initialConditions), NV_LENGTH_S(initialConditions));
422#if CHASTE_SUNDIALS_VERSION >= 60000
438 CVodeSetJacFn(
mpCvodeMem, AbstractCvodeSystemJacAdaptor);
444 CVodeReInit(
mpCvodeMem, tStart, initialConditions);
475 for (
unsigned i = 0; i < size; i++)
506 const double& rTime,
const double& rStartTime,
const double& rEndTime)
508 std::stringstream err;
509 char* p_flag_name = CVodeGetReturnFlagName(flag);
510 err << msg <<
": " << p_flag_name;
512 if (flag == CV_LSETUP_FAIL)
515 char* p_ls_flag_name;
518 p_ls_flag_name = CVodeGetLinReturnFlagName(ls_flag);
519 err <<
" (LS flag=" << ls_flag <<
":" << p_ls_flag_name <<
")";
520 free(p_ls_flag_name);
523 err <<
"\nGot from time " << rStartTime <<
" to time " << rTime <<
", was supposed to finish at time " << rEndTime <<
"\n";
524 err <<
"\nState variables are now:\n";
527 for (
unsigned i = 0; i < state_vars.size(); i++)
529 err <<
"\t" << state_var_names[i] <<
"\t:\t" << state_vars[i] << std::endl;
533 std::cerr << err.str() << std::endl
552 EXCEPTION(
"Analytic Jacobian requested, but this ODE system doesn't have one. You can check this with HasAnalyticJacobian().");
#define EXCEPTION(message)
void DeleteVector(VECTOR &rVec)
void CreateVectorIfEmpty(VECTOR &rVec, unsigned size)
void SetVectorComponent(VECTOR &rVec, unsigned index, double value)
double GetVectorComponent(const VECTOR &rVec, unsigned index)
std::vector< double > MakeStdVec(N_Vector v)
void SetTolerances(double relTol=1e-5, double absTol=1e-7)
SUNMatrix mpSundialsDenseMatrix
bool GetMinimalReset()
Get whether we want to run with minimal reset or not (no reinitialisation of the solver if variables ...
void SetForceReset(bool autoReset)
bool mUseAnalyticJacobian
void SetupCvode(N_Vector initialConditions, realtype tStart, realtype maxDt)
void CvodeError(int flag, const char *msg, const double &rTime, const double &rStartTime, const double &rEndTime)
double GetRelativeTolerance()
void RecordStoppingPoint(double stopTime)
void SetMaxSteps(long int numSteps)
bool HasAnalyticJacobian() const
AbstractCvodeSystem(unsigned numberOfStateVariables)
double GetAbsoluteTolerance()
OdeSolution Solve(realtype tStart, realtype tEnd, realtype maxDt, realtype tSamp)
void ForceUseOfNumericalJacobian(bool useNumericalJacobian=true)
virtual void EvaluateYDerivatives(realtype time, const N_Vector y, N_Vector ydot)=0
bool mHasAnalyticJacobian
SUNLinearSolver mpSundialsLinearSolver
virtual void EvaluateAnalyticJacobian(realtype time, N_Vector y, N_Vector ydot, CHASTE_CVODE_DENSE_MATRIX jacobian, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
bool GetUseAnalyticJacobian() const
double mLastInternalStepSize
void SetMinimalReset(bool minimalReset)
bool GetForceReset()
Get whether we will force a solver reset on every call to Solve()
N_Vector mLastSolutionState
virtual ~AbstractCvodeSystem()
N_Vector GetInitialConditions() const
virtual void VerifyStateVariables()
const std::vector< std::string > & rGetParameterNames() const
boost::shared_ptr< AbstractOdeSystemInformation > mpSystemInfo
const std::vector< std::string > & rGetStateVariableNames() const
unsigned GetNumberOfStateVariables() const
static bool WithinAnyTolerance(double number1, double number2, double relTol=DBL_EPSILON, double absTol=DBL_EPSILON, bool printError=false)
void SetNumberOfTimeSteps(unsigned numTimeSteps)
std::vector< std::vector< double > > & rGetSolutions()
std::vector< double > & rGetTimes()
void SetOdeSystemInformation(boost::shared_ptr< const AbstractOdeSystemInformation > pOdeSystemInfo)
unsigned GetTotalTimeStepsTaken() const
void AdvanceOneTimeStep()
double GetNextTime() const
unsigned EstimateTimeSteps() const