AbstractBackwardEulerCardiacCell.hpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifndef ABSTRACTBACKWARDEULERCARDIACCELL_HPP_
00031 #define ABSTRACTBACKWARDEULERCARDIACCELL_HPP_
00032
00033 #include <cassert>
00034 #include <cmath>
00035
00036 #include "ChasteSerialization.hpp"
00037 #include <boost/serialization/base_object.hpp>
00038 #include "ClassIsAbstract.hpp"
00039
00040 #include "AbstractCardiacCell.hpp"
00041 #include "Exception.hpp"
00042 #include "PetscTools.hpp"
00043 #include "TimeStepper.hpp"
00044
00059 template<unsigned SIZE>
00060 class AbstractBackwardEulerCardiacCell : public AbstractCardiacCell
00061 {
00062 private:
00064 friend class boost::serialization::access;
00071 template<class Archive>
00072 void serialize(Archive & archive, const unsigned int version)
00073 {
00074
00075 archive & boost::serialization::base_object<AbstractCardiacCell>(*this);
00076 }
00077 public:
00078
00094 AbstractBackwardEulerCardiacCell(
00095 unsigned numberOfStateVariables,
00096 unsigned voltageIndex,
00097 boost::shared_ptr<AbstractStimulusFunction> pIntracellularStimulus);
00098
00100 virtual ~AbstractBackwardEulerCardiacCell();
00101
00109 virtual void ComputeResidual(double time, const double rCurrentGuess[SIZE], double rResidual[SIZE])=0;
00110
00118 virtual void ComputeJacobian(double time, const double rCurrentGuess[SIZE], double rJacobian[SIZE][SIZE])=0;
00119
00132 OdeSolution Compute(double tStart, double tEnd, double tSamp=0.0);
00133
00143 void ComputeExceptVoltage(double tStart, double tEnd);
00144
00152 void SolveAndUpdateState(double tStart, double tEnd);
00153
00154 private:
00155 #define COVERAGE_IGNORE
00156
00163 void EvaluateYDerivatives(double time, const std::vector<double> &rY, std::vector<double> &rDY)
00164 {
00165 NEVER_REACHED;
00166 }
00167 #undef COVERAGE_IGNORE
00168
00169 protected:
00178 virtual void ComputeOneStepExceptVoltage(double tStart)=0;
00179
00187 virtual void UpdateTransmembranePotential(double time)=0;
00188 };
00189
00190
00191
00192
00193
00194
00195
00196
00197 template <unsigned SIZE>
00198 AbstractBackwardEulerCardiacCell<SIZE>::AbstractBackwardEulerCardiacCell(
00199 unsigned numberOfStateVariables,
00200 unsigned voltageIndex,
00201 boost::shared_ptr<AbstractStimulusFunction> pIntracellularStimulus)
00202 : AbstractCardiacCell(boost::shared_ptr<AbstractIvpOdeSolver>(),
00203 numberOfStateVariables,
00204 voltageIndex,
00205 pIntracellularStimulus)
00206 {}
00207
00208 template <unsigned SIZE>
00209 AbstractBackwardEulerCardiacCell<SIZE>::~AbstractBackwardEulerCardiacCell()
00210 {}
00211
00212 template <unsigned SIZE>
00213 OdeSolution AbstractBackwardEulerCardiacCell<SIZE>::Compute(double tStart, double tEnd, double tSamp)
00214 {
00215
00216
00217
00218
00219
00220
00221 if (tSamp < mDt)
00222 {
00223 tSamp = mDt;
00224 }
00225 double _n_steps = (tEnd - tStart) / tSamp;
00226 const unsigned n_steps = (unsigned) floor(_n_steps+0.5);
00227 assert(fabs(tStart+n_steps*tSamp - tEnd) < 1e-12);
00228 const unsigned n_small_steps = (unsigned) floor(tSamp/mDt+0.5);
00229 assert(fabs(mDt*n_small_steps - tSamp) < 1e-12);
00230
00231
00232 OdeSolution solutions;
00233 solutions.SetNumberOfTimeSteps(n_steps);
00234 solutions.rGetSolutions().push_back(rGetStateVariables());
00235 solutions.rGetTimes().push_back(tStart);
00236 solutions.SetOdeSystemInformation(this->mpSystemInfo);
00237
00238
00239 double curr_time = tStart;
00240 for (unsigned i=0; i<n_steps; i++)
00241 {
00242 for (unsigned j=0; j<n_small_steps; j++)
00243 {
00244 curr_time = tStart + i*tSamp + j*mDt;
00245
00246
00247 UpdateTransmembranePotential(curr_time);
00248
00249
00250 ComputeOneStepExceptVoltage(curr_time);
00251
00252
00253 VerifyStateVariables();
00254 }
00255
00256
00257 solutions.rGetSolutions().push_back(rGetStateVariables());
00258 solutions.rGetTimes().push_back(curr_time+mDt);
00259 }
00260
00261 return solutions;
00262 }
00263
00264 template <unsigned SIZE>
00265 void AbstractBackwardEulerCardiacCell<SIZE>::ComputeExceptVoltage(double tStart, double tEnd)
00266 {
00267
00268
00269
00270
00271 unsigned n_steps = (unsigned)((tEnd - tStart) / mDt + 0.5);
00272 assert(fabs(tStart + n_steps*mDt - tEnd) < 1e-12);
00273
00274
00275 double curr_time;
00276 for (unsigned i=0; i<n_steps; i++)
00277 {
00278 curr_time = tStart + i*mDt;
00279
00280
00281 ComputeOneStepExceptVoltage(curr_time);
00282
00283 #ifndef NDEBUG
00284
00285 VerifyStateVariables();
00286 #endif // NDEBUG
00287 }
00288 }
00289
00290 template<unsigned SIZE>
00291 void AbstractBackwardEulerCardiacCell<SIZE>::SolveAndUpdateState(double tStart, double tEnd)
00292 {
00293 TimeStepper stepper(tStart, tEnd, mDt);
00294
00295 while(!stepper.IsTimeAtEnd())
00296 {
00297 double time = stepper.GetTime();
00298
00299
00300 UpdateTransmembranePotential(time);
00301
00302
00303 ComputeOneStepExceptVoltage(time);
00304
00305
00306 VerifyStateVariables();
00307
00308 stepper.AdvanceOneTimeStep();
00309 }
00310 }
00311
00312
00313 TEMPLATED_CLASS_IS_ABSTRACT_1_UNSIGNED(AbstractBackwardEulerCardiacCell)
00314
00315 #endif