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),
180 mLastInternalStepSize(0)
190#if CHASTE_SUNDIALS_VERSION >= 60000
221 assert(tEnd >= tStart);
240 assert(ierr == CV_SUCCESS);
247 double cvode_stopped_at = stepper.
GetTime();
249 &cvode_stopped_at, CV_NORMAL);
256 assert(fabs(cvode_stopped_at - stepper.
GetNextTime()) < DBL_EPSILON);
262 solutions.
rGetTimes().push_back(cvode_stopped_at);
270 assert(ierr == CV_SUCCESS);
282 assert(tEnd >= tStart);
287 int ierr = CVodeSetStopTime(
mpCvodeMem, tEnd);
288 assert(ierr == CV_SUCCESS);
291 double cvode_stopped_at = tStart;
296 CvodeError(ierr,
"CVODE failed to solve system", cvode_stopped_at, tStart, tEnd);
299 assert(fabs(cvode_stopped_at - tEnd) < DBL_EPSILON);
302 assert(ierr == CV_SUCCESS);
402 assert(maxDt >= 0.0);
410 for (
unsigned i = 0; i < size; i++)
423#if CHASTE_SUNDIALS_VERSION >= 60000
424 mpCvodeMem = CVodeCreate(CV_BDF, CvodeContextManager::Instance()->GetSundialsContext());
425#elif CHASTE_SUNDIALS_VERSION >= 40000
436#if CHASTE_SUNDIALS_VERSION >= 70000
437 SUNContext_PushErrHandler(CvodeContextManager::Instance()->GetSundialsContext(), CvodeErrorHandler,
nullptr);
439 CVodeSetErrHandlerFn(
mpCvodeMem, CvodeErrorHandler,
nullptr);
442#if CHASTE_SUNDIALS_VERSION >= 20400
448#if CHASTE_SUNDIALS_VERSION >= 20400
449 CVodeInit(
mpCvodeMem, AbstractCvodeSystemRhsAdaptor, tStart, initialConditions);
452 CVodeMalloc(
mpCvodeMem, AbstractCvodeSystemRhsAdaptor, tStart, initialConditions,
456#if CHASTE_SUNDIALS_VERSION >= 60000
458 mpSundialsDenseMatrix = SUNDenseMatrix(NV_LENGTH_S(initialConditions), NV_LENGTH_S(initialConditions), CvodeContextManager::Instance()->GetSundialsContext());
459#elif CHASTE_SUNDIALS_VERSION >= 30000
461 mpSundialsDenseMatrix = SUNDenseMatrix(NV_LENGTH_S(initialConditions), NV_LENGTH_S(initialConditions));
464#if CHASTE_SUNDIALS_VERSION >= 60000
466 mpSundialsLinearSolver = SUNLinSol_Dense(initialConditions, mpSundialsDenseMatrix, CvodeContextManager::Instance()->GetSundialsContext());
469 CVodeSetLinearSolver(
mpCvodeMem, mpSundialsLinearSolver, mpSundialsDenseMatrix);
470#elif CHASTE_SUNDIALS_VERSION >= 40000
472 mpSundialsLinearSolver = SUNLinSol_Dense(initialConditions, mpSundialsDenseMatrix);
475 CVodeSetLinearSolver(
mpCvodeMem, mpSundialsLinearSolver, mpSundialsDenseMatrix);
476#elif CHASTE_SUNDIALS_VERSION >= 30000
478 mpSundialsLinearSolver = SUNDenseLinearSolver(initialConditions, mpSundialsDenseMatrix);
481 CVDlsSetLinearSolver(
mpCvodeMem, mpSundialsLinearSolver, mpSundialsDenseMatrix);
485 CVDense(
mpCvodeMem, NV_LENGTH_S(initialConditions));
490#if CHASTE_SUNDIALS_VERSION >= 40000
491 CVodeSetJacFn(
mpCvodeMem, AbstractCvodeSystemJacAdaptor);
492#elif CHASTE_SUNDIALS_VERSION >= 30000
493 CVDlsSetJacFn(
mpCvodeMem, AbstractCvodeSystemJacAdaptor);
494#elif CHASTE_SUNDIALS_VERSION >= 20400
495 CVDlsSetDenseJacFn(
mpCvodeMem, AbstractCvodeSystemJacAdaptor);
497 CVDenseSetJacFn(
mpCvodeMem, AbstractCvodeSystemJacAdaptor, (
void*)(
this));
504#if CHASTE_SUNDIALS_VERSION >= 20400
505 CVodeReInit(
mpCvodeMem, tStart, initialConditions);
508 CVodeReInit(
mpCvodeMem, AbstractCvodeSystemRhsAdaptor, tStart, initialConditions,
540 for (
unsigned i = 0; i < size; i++)
555#if CHASTE_SUNDIALS_VERSION >= 30000
556 if (mpSundialsLinearSolver)
559 SUNLinSolFree(mpSundialsLinearSolver);
561 mpSundialsLinearSolver =
nullptr;
563 if (mpSundialsDenseMatrix)
566 SUNMatDestroy(mpSundialsDenseMatrix);
568 mpSundialsDenseMatrix =
nullptr;
573 const double& rTime,
const double& rStartTime,
const double& rEndTime)
575 std::stringstream err;
576 char* p_flag_name = CVodeGetReturnFlagName(flag);
577 err << msg <<
": " << p_flag_name;
579 if (flag == CV_LSETUP_FAIL)
581#if CHASTE_SUNDIALS_VERSION >= 20500
586 char* p_ls_flag_name;
588#if CHASTE_SUNDIALS_VERSION >= 40000
590 p_ls_flag_name = CVodeGetLinReturnFlagName(ls_flag);
591#elif CHASTE_SUNDIALS_VERSION >= 20400
593 p_ls_flag_name = CVDlsGetReturnFlagName(ls_flag);
596 p_ls_flag_name = CVDenseGetReturnFlagName(ls_flag);
598 err <<
" (LS flag=" << ls_flag <<
":" << p_ls_flag_name <<
")";
599 free(p_ls_flag_name);
602 err <<
"\nGot from time " << rStartTime <<
" to time " << rTime <<
", was supposed to finish at time " << rEndTime <<
"\n";
603 err <<
"\nState variables are now:\n";
606 for (
unsigned i = 0; i < state_vars.size(); i++)
608 err <<
"\t" << state_var_names[i] <<
"\t:\t" << state_vars[i] << std::endl;
612 std::cerr << err.str() << std::endl
631 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