41#include "AbstractCvodeSystem.hpp"
42#include "CvodeAdaptor.hpp"
45#include "TimeStepper.hpp"
49#include <cvode/cvode.h>
50#include <sundials/sundials_nvector.h>
52#if CHASTE_SUNDIALS_VERSION >= 30000
53#if CHASTE_SUNDIALS_VERSION < 70000
54#include <cvode/cvode_direct.h>
56#include <sundials/sundials_types.h>
57#include <sunlinsol/sunlinsol_dense.h>
58#include <sunmatrix/sunmatrix_dense.h>
60#include <cvode/cvode_dense.h>
63#if CHASTE_SUNDIALS_VERSION >= 60000
64#include "CvodeContextManager.hpp"
87int AbstractCvodeSystemRhsAdaptor(realtype t,
N_Vector y,
N_Vector ydot,
void* pData)
89 assert(pData !=
nullptr);
97#if CHASTE_SUNDIALS_VERSION <= 20300
99 if (e.CheckShortMessageContains(
"is outside the times stored in the data clamp") ==
"")
105 std::cerr <<
"CVODE RHS Exception: " << e.GetMessage()
130#if CHASTE_SUNDIALS_VERSION >= 30000
132int AbstractCvodeSystemJacAdaptor(realtype t,
N_Vector y,
N_Vector ydot, CHASTE_CVODE_DENSE_MATRIX jacobian,
133#elif CHASTE_SUNDIALS_VERSION >= 20500
135int AbstractCvodeSystemJacAdaptor(
long int N, realtype t,
N_Vector y,
N_Vector ydot, CHASTE_CVODE_DENSE_MATRIX jacobian,
136#elif CHASTE_SUNDIALS_VERSION >= 20400
138int AbstractCvodeSystemJacAdaptor(
int N, realtype t,
N_Vector y,
N_Vector ydot, DlsMat jacobian,
141int AbstractCvodeSystemJacAdaptor(
long int N, DenseMat jacobian, realtype t,
N_Vector y,
N_Vector ydot,
145 assert(pData !=
nullptr);
153 std::cerr <<
"CVODE Jacobian Exception: " << e.GetMessage() << std::endl
162 mLastSolutionState(nullptr),
163 mLastSolutionTime(0.0),
164#if CHASTE_SUNDIALS_VERSION >= 20400
171 mForceMinimalReset(false),
172#if CHASTE_SUNDIALS_VERSION >= 30000
173 mpSundialsDenseMatrix(nullptr),
174 mpSundialsLinearSolver(nullptr),
176 mHasAnalyticJacobian(false),
177 mUseAnalyticJacobian(false),
179#if CHASTE_SUNDIALS_VERSION >= 60000
180 mpSundialsContextManager(CvodeContextManager::Instance()),
183 mLastInternalStepSize(0)
193#if CHASTE_SUNDIALS_VERSION >= 60000
224 assert(tEnd >= tStart);
243 assert(ierr == CV_SUCCESS);
250 double cvode_stopped_at = stepper.
GetTime();
252 &cvode_stopped_at, CV_NORMAL);
259 assert(fabs(cvode_stopped_at - stepper.
GetNextTime()) < DBL_EPSILON);
265 solutions.
rGetTimes().push_back(cvode_stopped_at);
273 assert(ierr == CV_SUCCESS);
285 assert(tEnd >= tStart);
290 int ierr = CVodeSetStopTime(
mpCvodeMem, tEnd);
291 assert(ierr == CV_SUCCESS);
294 double cvode_stopped_at = tStart;
299 CvodeError(ierr,
"CVODE failed to solve system", cvode_stopped_at, tStart, tEnd);
302 assert(fabs(cvode_stopped_at - tEnd) < DBL_EPSILON);
305 assert(ierr == CV_SUCCESS);
405 assert(maxDt >= 0.0);
413 for (
unsigned i = 0; i < size; i++)
426#if CHASTE_SUNDIALS_VERSION >= 60000
427 mpCvodeMem = CVodeCreate(CV_BDF, CvodeContextManager::Instance()->GetSundialsContext());
428#elif CHASTE_SUNDIALS_VERSION >= 40000
439#if CHASTE_SUNDIALS_VERSION >= 70000
440 SUNContext_PushErrHandler(CvodeContextManager::Instance()->GetSundialsContext(), CvodeErrorHandler,
nullptr);
442 CVodeSetErrHandlerFn(
mpCvodeMem, CvodeErrorHandler,
nullptr);
445#if CHASTE_SUNDIALS_VERSION >= 20400
451#if CHASTE_SUNDIALS_VERSION >= 20400
452 CVodeInit(
mpCvodeMem, AbstractCvodeSystemRhsAdaptor, tStart, initialConditions);
455 CVodeMalloc(
mpCvodeMem, AbstractCvodeSystemRhsAdaptor, tStart, initialConditions,
459#if CHASTE_SUNDIALS_VERSION >= 60000
461 mpSundialsDenseMatrix = SUNDenseMatrix(NV_LENGTH_S(initialConditions), NV_LENGTH_S(initialConditions), CvodeContextManager::Instance()->GetSundialsContext());
462#elif CHASTE_SUNDIALS_VERSION >= 30000
464 mpSundialsDenseMatrix = SUNDenseMatrix(NV_LENGTH_S(initialConditions), NV_LENGTH_S(initialConditions));
467#if CHASTE_SUNDIALS_VERSION >= 60000
469 mpSundialsLinearSolver = SUNLinSol_Dense(initialConditions, mpSundialsDenseMatrix, CvodeContextManager::Instance()->GetSundialsContext());
472 CVodeSetLinearSolver(
mpCvodeMem, mpSundialsLinearSolver, mpSundialsDenseMatrix);
473#elif CHASTE_SUNDIALS_VERSION >= 40000
475 mpSundialsLinearSolver = SUNLinSol_Dense(initialConditions, mpSundialsDenseMatrix);
478 CVodeSetLinearSolver(
mpCvodeMem, mpSundialsLinearSolver, mpSundialsDenseMatrix);
479#elif CHASTE_SUNDIALS_VERSION >= 30000
481 mpSundialsLinearSolver = SUNDenseLinearSolver(initialConditions, mpSundialsDenseMatrix);
484 CVDlsSetLinearSolver(
mpCvodeMem, mpSundialsLinearSolver, mpSundialsDenseMatrix);
488 CVDense(
mpCvodeMem, NV_LENGTH_S(initialConditions));
493#if CHASTE_SUNDIALS_VERSION >= 40000
494 CVodeSetJacFn(
mpCvodeMem, AbstractCvodeSystemJacAdaptor);
495#elif CHASTE_SUNDIALS_VERSION >= 30000
496 CVDlsSetJacFn(
mpCvodeMem, AbstractCvodeSystemJacAdaptor);
497#elif CHASTE_SUNDIALS_VERSION >= 20400
498 CVDlsSetDenseJacFn(
mpCvodeMem, AbstractCvodeSystemJacAdaptor);
500 CVDenseSetJacFn(
mpCvodeMem, AbstractCvodeSystemJacAdaptor, (
void*)(
this));
507#if CHASTE_SUNDIALS_VERSION >= 20400
508 CVodeReInit(
mpCvodeMem, tStart, initialConditions);
511 CVodeReInit(
mpCvodeMem, AbstractCvodeSystemRhsAdaptor, tStart, initialConditions,
543 for (
unsigned i = 0; i < size; i++)
558#if CHASTE_SUNDIALS_VERSION >= 30000
559 if (mpSundialsLinearSolver)
562 SUNLinSolFree(mpSundialsLinearSolver);
564 mpSundialsLinearSolver =
nullptr;
566 if (mpSundialsDenseMatrix)
569 SUNMatDestroy(mpSundialsDenseMatrix);
571 mpSundialsDenseMatrix =
nullptr;
576 const double& rTime,
const double& rStartTime,
const double& rEndTime)
578 std::stringstream err;
579 char* p_flag_name = CVodeGetReturnFlagName(flag);
580 err << msg <<
": " << p_flag_name;
582 if (flag == CV_LSETUP_FAIL)
584#if CHASTE_SUNDIALS_VERSION >= 20500
589 char* p_ls_flag_name;
591#if CHASTE_SUNDIALS_VERSION >= 40000
593 p_ls_flag_name = CVodeGetLinReturnFlagName(ls_flag);
594#elif CHASTE_SUNDIALS_VERSION >= 20400
596 p_ls_flag_name = CVDlsGetReturnFlagName(ls_flag);
599 p_ls_flag_name = CVDenseGetReturnFlagName(ls_flag);
601 err <<
" (LS flag=" << ls_flag <<
":" << p_ls_flag_name <<
")";
602 free(p_ls_flag_name);
605 err <<
"\nGot from time " << rStartTime <<
" to time " << rTime <<
", was supposed to finish at time " << rEndTime <<
"\n";
606 err <<
"\nState variables are now:\n";
609 for (
unsigned i = 0; i < state_vars.size(); i++)
611 err <<
"\t" << state_var_names[i] <<
"\t:\t" << state_vars[i] << std::endl;
615 std::cerr << err.str() << std::endl
634 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)
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
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