Chaste Commit::fa89f2b838c1edb21a1eaec92ee3a2eacc9255dd
AbstractCvodeSystem.hpp
1/*
2
3Copyright (c) 2005-2026, University of Oxford.
4All rights reserved.
5
6University of Oxford means the Chancellor, Masters and Scholars of the
7University of Oxford, having an administrative office at Wellington
8Square, Oxford OX1 2JD, UK.
9
10This file is part of Chaste.
11
12Redistribution and use in source and binary forms, with or without
13modification, are permitted provided that the following conditions are met:
14 * Redistributions of source code must retain the above copyright notice,
15 this list of conditions and the following disclaimer.
16 * Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19 * Neither the name of the University of Oxford nor the names of its
20 contributors may be used to endorse or promote products derived from this
21 software without specific prior written permission.
22
23THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34*/
35
36#ifdef CHASTE_CVODE
37#ifndef _ABSTRACTCVODESYSTEM_HPP_
38#define _ABSTRACTCVODESYSTEM_HPP_
39
40#include <algorithm>
41#include <memory>
42#include <string>
43#include <vector>
44
45// This is only needed to prevent compilation errors on PETSc 2.2/Boost 1.33.1 combo
47
48// Chaste includes
49#include "AbstractParameterisedSystem.hpp"
50#include "CvodeContextManager.hpp"
51#include "Exception.hpp"
52#include "OdeSolution.hpp"
54
55// Serialiazation
56#include <boost/serialization/split_member.hpp>
57#include <boost/serialization/vector.hpp>
59#include "ClassIsAbstract.hpp"
60
61// CVODE headers
62#include <nvector/nvector_serial.h>
63
64#if CHASTE_SUNDIALS_VERSION >= 30000
65#if CHASTE_SUNDIALS_VERSION < 70000
66#include <cvode/cvode_direct.h> /* access to CVDls interface */
67#endif
68#include <sundials/sundials_types.h> /* defs. of realtype, sunindextype */
69#include <sunlinsol/sunlinsol_dense.h> /* access to dense SUNLinearSolver */
70#include <sunmatrix/sunmatrix_dense.h> /* access to dense SUNMatrix */
71#else
72#include <sundials/sundials_dense.h> /* definitions DlsMat DENSE_ELEM */
73#endif
74
75// CVODE changed their dense matrix type...
76#if CHASTE_SUNDIALS_VERSION >= 30000
77#define CHASTE_CVODE_DENSE_MATRIX SUNMatrix
78#elif CHASTE_SUNDIALS_VERSION >= 20400
79#define CHASTE_CVODE_DENSE_MATRIX DlsMat
80#else
81#define CHASTE_CVODE_DENSE_MATRIX DenseMat
82#endif
83
84// CVODE changed their way of referencing elements of a matrix. So we will copy their notation in examples.
85#if CHASTE_SUNDIALS_VERSION >= 30000
86#define IJth(A, i, j) SM_ELEMENT_D(A, i, j)
87#else
88#define IJth(A, i, j) DENSE_ELEM(A, i, j)
89#endif
90
146{
147private:
148 friend class TestAbstractCvodeSystem;
149
150 friend class boost::serialization::access;
157 template <class Archive>
158 void save(Archive& archive, const unsigned int version) const
159 {
160 // Despite the fact that 3 of these variables actually live in our base class,
161 // we still archive them here to maintain backwards compatibility,
162 // this doesn't hurt
164 archive& mUseAnalyticJacobian;
165
166 if (version >= 1u)
167 {
168 archive& mHasAnalyticJacobian;
169 }
170
171 // Convert from N_Vector to std::vector for serialization
172 const std::vector<double> state_vars = MakeStdVec(mStateVariables);
173 archive& state_vars;
174 const std::vector<double> params = MakeStdVec(mParameters);
175 archive& params;
176 archive& rGetParameterNames();
177
178 archive& mLastSolutionTime;
179 archive& mForceReset;
180 archive& mForceMinimalReset;
181 archive& mRelTol;
182 archive& mAbsTol;
183 archive& mMaxSteps;
184 archive& mLastInternalStepSize;
185
186 // We don't bother archiving CVODE's internal data, because it is missing then we'll just
187 // get a new solver being initialised after a save/load.
188
189 // This is always set up by subclass constructors, and is essentially
190 // 'static' data, so shouldn't go in the archive.
191 //archive &mpSystemInfo;
192 }
199 template <class Archive>
200 void load(Archive& archive, const unsigned int version)
201 {
203 archive& mUseAnalyticJacobian;
204
205 // This is pretty much what the code was saying before.
207 if (version >= 1u)
208 { // Overwrite if it has been archived though
209 archive& mHasAnalyticJacobian;
210 }
211
212 std::vector<double> state_vars;
213 archive& state_vars;
215
216 std::vector<double> parameters;
217 archive& parameters;
218
219 std::vector<std::string> param_names;
220 archive& param_names;
221 archive& mLastSolutionTime;
222 archive& mForceReset;
223 archive& mForceMinimalReset;
224 archive& mRelTol;
225 archive& mAbsTol;
226 archive& mMaxSteps;
227 archive& mLastInternalStepSize;
228
229 // We don't bother archiving CVODE's internal data, because it is missing then we'll just
230 // get a new solver being initialised after a save/load.
231
232 // Do some checking on the parameters
233 CheckParametersOnLoad(parameters, param_names);
234 }
235 BOOST_SERIALIZATION_SPLIT_MEMBER()
236
237
244 void SetupCvode(N_Vector initialConditions,
245 realtype tStart,
246 realtype maxDt);
247
252 void RecordStoppingPoint(double stopTime);
253
255 void FreeCvodeMemory();
256
267 void CvodeError(int flag, const char* msg, const double& rTime,
268 const double& rStartTime, const double& rEndTime);
269
272
275
278
281
282#if CHASTE_SUNDIALS_VERSION >= 30000
284 SUNMatrix mpSundialsDenseMatrix;
286 SUNLinearSolver mpSundialsLinearSolver;
287#endif
288
289protected:
292
295
297 double mRelTol;
298
300 double mAbsTol;
301
304
305#if CHASTE_SUNDIALS_VERSION >= 60000
310 std::shared_ptr<CvodeContextManager> mpSundialsContextManager;
311#endif
312
317 long int mMaxSteps;
318
321
326 void Init();
327
328public:
334 AbstractCvodeSystem(unsigned numberOfStateVariables);
335
339 virtual ~AbstractCvodeSystem();
340
348 virtual void EvaluateYDerivatives(realtype time,
349 const N_Vector y,
350 N_Vector ydot)
351 = 0;
352
368 virtual void EvaluateAnalyticJacobian(realtype time, N_Vector y, N_Vector ydot,
369 CHASTE_CVODE_DENSE_MATRIX jacobian,
370 N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
371 {
372 EXCEPTION("No analytic Jacobian has been defined for this system.");
373 }
374
385 void SetForceReset(bool autoReset);
386
395 void SetMinimalReset(bool minimalReset);
396
403 bool GetMinimalReset();
404
411 bool GetForceReset();
412
423 void ResetSolver();
424
444 OdeSolution Solve(realtype tStart,
445 realtype tEnd,
446 realtype maxDt,
447 realtype tSamp);
448
464 void Solve(realtype tStart,
465 realtype tEnd,
466 realtype maxDt);
467
474 void SetMaxSteps(long int numSteps);
475
480 long int GetMaxSteps();
481
489 void SetTolerances(double relTol = 1e-5, double absTol = 1e-7);
490
494 double GetRelativeTolerance();
495
499 double GetAbsoluteTolerance();
500
504 double GetLastStepSize();
505
506 /* NB This needs making into a doxygen comment if you bring the method back in.
507 *
508 * An alternative approach to stopping events; currently only useful with CVODE.
509 * CVODE can search for roots (zeros) of this function while solving the ODE system,
510 * and home in on them to find sign transitions to high precision.
511 *
512 * The default implementation here fakes a root function using CalculateStoppingEvent.
513 *
514 * @param time the current time
515 * @param rY the current values of the state variables
516 */
517 // virtual double CalculateRootFunction(double time, const std::vector<double>& rY);
518
522 bool GetUseAnalyticJacobian() const;
523
527 bool HasAnalyticJacobian() const;
528
535 void ForceUseOfNumericalJacobian(bool useNumericalJacobian = true);
536
537 // The following method may be useful to identify problems with the Analytic Jacobians, if anything goes wrong,
538 // but #1795 seems to have got these working OK, so commented out for now.
539
540 // /*
541 // * Compare the calculated analytic jacobian to a numerical approximation, and throw if it looks silly.
542 // *
543 // * @param time the current time
544 // * @param y the current state variables
545 // * @param jacobian the analytic jacobian matrix
546 // * @param tmp1 working memory of the correct size provided by CVODE for temporary calculations
547 // * @param tmp2 working memory of the correct size provided by CVODE for temporary calculations
548 // * @param tmp3 working memory of the correct size provided by CVODE for temporary calculations
549 // */
550 // void CheckAnalyticJacobian(realtype time, N_Vector y, N_Vector ydot,
551 // CHASTE_CVODE_DENSE_MATRIX jacobian,
552 // N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
553};
554
556BOOST_CLASS_VERSION(AbstractCvodeSystem, 1u)
557
558#endif //_ABSTRACTCVODESYSTEM_HPP_
559#endif // CHASTE_CVODE
#define CLASS_IS_ABSTRACT(T)
#define EXCEPTION(message)
std::vector< double > MakeStdVec(N_Vector v)
void CopyFromStdVector(const std::vector< double > &rSrc, VECTOR &rDest)
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)
void load(Archive &archive, const unsigned int version)
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)
void RecordStoppingPoint(double stopTime)
void SetMaxSteps(long int numSteps)
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
void save(Archive &archive, const unsigned int version) const
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)
void SetMinimalReset(bool minimalReset)
bool GetForceReset()
Get whether we will force a solver reset on every call to Solve()
void CheckParametersOnLoad(const std::vector< double > &rParameters, const std::vector< std::string > &rParameterNames)
const std::vector< std::string > & rGetParameterNames() const