Chaste Commit::f2ff7ee04e70ac9d06c57344df8d017dbb12b97b
AbstractParameterisedSystem.cpp
1/*
2
3Copyright (c) 2005-2024, 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#include <sstream>
37#include <cassert>
38
39#include "AbstractParameterisedSystem.hpp"
40
41#include "Exception.hpp"
43
44
45template<typename VECTOR>
52
53template<typename VECTOR>
54std::string AbstractParameterisedSystem<VECTOR>::DumpState(const std::string& rMessage)
55{
56 return GetStateMessage(rMessage, mStateVariables);
57}
58
59template<typename VECTOR>
60std::string AbstractParameterisedSystem<VECTOR>::DumpState(const std::string& rMessage,
61 VECTOR Y)
62{
63 return GetStateMessage(rMessage, Y);
64}
65
66template<typename VECTOR>
67std::string AbstractParameterisedSystem<VECTOR>::DumpState(const std::string& rMessage,
68 VECTOR Y,
69 double time)
70{
71 std::stringstream extra_message;
72 extra_message << std::endl << "At independent variable (usually time) = " << time;
73 std::string new_message = rMessage + extra_message.str();
74 return GetStateMessage(new_message, Y);
75}
76
77template<typename VECTOR>
78std::string AbstractParameterisedSystem<VECTOR>::GetStateMessage(const std::string& rMessage, VECTOR Y)
79{
80 std::stringstream res;
81 res << rMessage << std::endl << "State:" << std::endl;
82 assert(rGetStateVariableNames().size()==GetVectorSize(Y));
83 const std::vector<std::string>& r_units = rGetStateVariableUnits();
84 for (unsigned i=0; i<GetVectorSize(Y); i++)
85 {
86 res << "\t" << rGetStateVariableNames()[i] << ":" << GetVectorComponent(Y, i);
87 if (!r_units.empty())
88 {
89 res << " " << r_units[i];
90 }
91 res << std::endl;
92 }
93 return res.str();
94}
96template<typename VECTOR>
97void AbstractParameterisedSystem<VECTOR>::CheckParametersOnLoad(const std::vector<double>& rParameters, const std::vector<std::string>& rParameterNames)
98{
99 if (GetVectorSize(mParameters) != rGetParameterNames().size())
100 {
101 // Subclass constructor didn't give default values, so we need the archive to provide them all
102 if (rParameterNames.size() != rGetParameterNames().size())
103 {
104 EXCEPTION("Number of ODE parameters in archive does not match number in class.");
105 }
106 CreateVectorIfEmpty(mParameters,rGetParameterNames().size());
107 }
108
109 // Check whether the archive specifies parameters that don't appear in this class,
110 // and create a map from archive index to local index
111 std::vector<unsigned> index_map(rParameterNames.size());
112 for (unsigned i=0; i<rParameterNames.size(); ++i)
113 {
114 index_map[i] = find(rGetParameterNames().begin(), rGetParameterNames().end(), rParameterNames[i])
115 - rGetParameterNames().begin();
116 if (index_map[i] == rGetParameterNames().size())
117 {
118 EXCEPTION("Archive specifies a parameter '" + rParameterNames[i] + "' which does not appear in this class.");
119 }
120 }
121
122 for (unsigned i=0; i<rParameterNames.size(); ++i)
123 {
124 SetVectorComponent(mParameters,index_map[i],rParameters[i]);
125 }
126
127 // Paranoia check
128 assert(GetVectorSize(mParameters) == rGetParameterNames().size());
129}
130
132// State variable methods
133//
134
135template<typename VECTOR>
137{
138 return mStateVariables;
139}
141template<typename VECTOR>
143{
144 return CopyVector(mStateVariables);
145}
147template<typename VECTOR>
149{
150 if (mNumberOfStateVariables != GetVectorSize(rStateVariables))
151 {
152 EXCEPTION("The size of the passed in vector must be that of the number of state variables.");
153 }
155 CreateVectorIfEmpty(mStateVariables, mNumberOfStateVariables);
156 for (unsigned i=0; i<mNumberOfStateVariables; i++)
157 {
158 SetVectorComponent(mStateVariables, i, GetVectorComponent(rStateVariables, i));
159 }
160}
162template<typename VECTOR>
164{
165 if (index >= mNumberOfStateVariables)
166 {
167 EXCEPTION("The index passed in must be less than the number of state variables.");
169 return GetVectorComponent(mStateVariables, index);
170}
171
172template<typename VECTOR>
173double AbstractParameterisedSystem<VECTOR>::GetStateVariable(const std::string& rName) const
174{
175 return GetStateVariable(GetStateVariableIndex(rName));
177
178template<typename VECTOR>
179void AbstractParameterisedSystem<VECTOR>::SetStateVariable(unsigned index, double newValue)
180{
181 if (mNumberOfStateVariables <= index)
182 {
183 EXCEPTION("The index passed in must be less than the number of state variables.");
185 SetVectorComponent(mStateVariables, index, newValue);
186}
187
188template<typename VECTOR>
189void AbstractParameterisedSystem<VECTOR>::SetStateVariable(const std::string& rName, double newValue)
190{
191 SetStateVariable(GetStateVariableIndex(rName), newValue);
192}
193
194//
195// Initial condition methods
196//
197
198template<typename VECTOR>
200{
201 if (GetVectorSize(rInitialConditions) != mNumberOfStateVariables)
202 {
203 EXCEPTION("The number of initial conditions must be that of the number of state variables.");
204 }
205 assert(mpSystemInfo);
206 std::vector<double> inits;
207 CopyToStdVector(rInitialConditions, inits);
208 mpSystemInfo->SetDefaultInitialConditions(inits);
209}
210
211template<typename VECTOR>
212void AbstractParameterisedSystem<VECTOR>::SetDefaultInitialCondition(unsigned index, double initialCondition)
213{
214 if (index >= mNumberOfStateVariables)
215 {
216 EXCEPTION("Index is greater than the number of state variables.");
217 }
218 assert(mpSystemInfo);
219 mpSystemInfo->SetDefaultInitialCondition(index, initialCondition);
220}
221
222template<typename VECTOR>
224{
225 assert(mpSystemInfo);
226 VECTOR v;
228 CreateVectorIfEmpty(v, mNumberOfStateVariables);
229 CopyFromStdVector(mpSystemInfo->GetInitialConditions(), v);
230 return v;
231}
232
233template<typename VECTOR>
235{
236 VECTOR inits = GetInitialConditions();
237 SetStateVariables(inits);
239}
240
241//
242// Parameter methods
243//
244
245template<typename VECTOR>
247{
248 if (index >= GetVectorSize(mParameters))
250 EXCEPTION("The index passed in must be less than the number of parameters.");
251 }
252 return GetVectorComponent(mParameters, index);
253}
254
255template<typename VECTOR>
257{
258 if (index >= GetVectorSize(mParameters))
259 {
260 EXCEPTION("The index passed in must be less than the number of parameters.");
261 }
262 SetVectorComponent(mParameters, index, value);
263}
265template<typename VECTOR>
266void AbstractParameterisedSystem<VECTOR>::SetParameter(const std::string& rName, double value)
267{
268 SetVectorComponent(mParameters, GetParameterIndex(rName), value);
269}
270
271template<typename VECTOR>
272double AbstractParameterisedSystem<VECTOR>::GetParameter(const std::string& rName) const
273{
274 return GetParameter(GetParameterIndex(rName));
275}
276
277//
278// "Any variable" methods
279//
280
281template<typename VECTOR>
283 VECTOR* pDerivedQuantities)
284{
285 if (index < mNumberOfStateVariables)
286 {
287 return GetVectorComponent(mStateVariables, index);
288 }
289 else if (index - mNumberOfStateVariables < GetVectorSize(mParameters))
290 {
291 return GetVectorComponent(mParameters, index - mNumberOfStateVariables);
292 }
293 else
294 {
295 unsigned offset = mNumberOfStateVariables + GetVectorSize(mParameters);
296 if (index - offset < GetNumberOfDerivedQuantities())
297 {
298 VECTOR dqs;
299 if (pDerivedQuantities == nullptr)
300 {
301 dqs = ComputeDerivedQuantitiesFromCurrentState(time);
302 pDerivedQuantities = &dqs;
303 }
304 double value = GetVectorComponent(*pDerivedQuantities, index - offset);
305 if (pDerivedQuantities == &dqs)
306 {
308 }
309 return value;
310 }
311 else
312 {
313 EXCEPTION("Invalid index passed to GetAnyVariable.");
314 }
315 }
316}
318template<typename VECTOR>
320 double time,
321 VECTOR* pDerivedQuantities)
322{
323 return GetAnyVariable(GetAnyVariableIndex(rName), time, pDerivedQuantities);
324}
325
326template<typename VECTOR>
328{
329 if (index < mNumberOfStateVariables)
330 {
331 SetVectorComponent(mStateVariables, index, value);
332 }
333 else if (index - mNumberOfStateVariables < GetVectorSize(mParameters))
334 {
335 SetVectorComponent(mParameters, index - mNumberOfStateVariables, value);
336 }
337 else
338 {
339 EXCEPTION("Cannot set the value of a derived quantity, or invalid index.");
341}
342
343template<typename VECTOR>
344void AbstractParameterisedSystem<VECTOR>::SetAnyVariable(const std::string& rName, double value)
345{
346 SetAnyVariable(GetAnyVariableIndex(rName), value);
347}
348
350// "Derived quantities" methods
351//
352
353template<typename VECTOR>
355 const VECTOR& rState)
356{
357 EXCEPTION("This ODE system does not define derived quantities.");
358}
359
360template<typename VECTOR>
362{
363 return this->ComputeDerivedQuantities(time, mStateVariables);
364}
365
366
368
370#ifdef CHASTE_CVODE
372#endif
#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)
unsigned GetVectorSize(const VECTOR &rVec)
VECTOR CopyVector(VECTOR &rVec)
void InitialiseEmptyVector(VECTOR &rVec)
void CopyFromStdVector(const std::vector< double > &rSrc, VECTOR &rDest)
void CopyToStdVector(const VECTOR &rSrc, std::vector< double > &rDest)
virtual VECTOR ComputeDerivedQuantities(double time, const VECTOR &rState)
double GetStateVariable(unsigned index) const
void SetStateVariables(const VECTOR &rStateVariables)
double GetAnyVariable(unsigned index, double time=0.0, VECTOR *pDerivedQuantities=NULL)
double GetParameter(unsigned index) const
void SetStateVariable(unsigned index, double newValue)
void SetAnyVariable(unsigned index, double value)
VECTOR ComputeDerivedQuantitiesFromCurrentState(double time)
void CheckParametersOnLoad(const std::vector< double > &rParameters, const std::vector< std::string > &rParameterNames)
std::string GetStateMessage(const std::string &rMessage, VECTOR Y)
void SetParameter(const std::string &rName, double value)
AbstractParameterisedSystem(unsigned numberOfStateVariables)
std::string DumpState(const std::string &rMessage)
void SetDefaultInitialCondition(unsigned index, double initialCondition)
void SetDefaultInitialConditions(const VECTOR &rInitialConditions)