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
00058 template<unsigned SIZE>
00059 class AbstractBackwardEulerCardiacCell : public AbstractCardiacCell
00060 {
00061 private:
00063 friend class boost::serialization::access;
00070 template<class Archive>
00071 void serialize(Archive & archive, const unsigned int version)
00072 {
00073
00074 archive & boost::serialization::base_object<AbstractCardiacCell>(*this);
00075 }
00076 public:
00077
00093 AbstractBackwardEulerCardiacCell(
00094 unsigned numberOfStateVariables,
00095 unsigned voltageIndex,
00096 boost::shared_ptr<AbstractStimulusFunction> pIntracellularStimulus);
00097
00099 virtual ~AbstractBackwardEulerCardiacCell();
00100
00108 virtual void ComputeResidual(double time, const double rCurrentGuess[SIZE], double rResidual[SIZE])=0;
00109
00117 virtual void ComputeJacobian(double time, const double rCurrentGuess[SIZE], double rJacobian[SIZE][SIZE])=0;
00118
00131 virtual OdeSolution Compute(double tStart, double tEnd, double tSamp=0.0);
00132
00142 virtual void ComputeExceptVoltage(double tStart, double tEnd);
00143
00144 private:
00145 #define COVERAGE_IGNORE
00146
00153 void EvaluateYDerivatives(double time, const std::vector<double> &rY, std::vector<double> &rDY)
00154 {
00155 NEVER_REACHED;
00156 }
00157 #undef COVERAGE_IGNORE
00158
00159 protected:
00168 virtual void ComputeOneStepExceptVoltage(double tStart)=0;
00169
00177 virtual void UpdateTransmembranePotential(double time)=0;
00178 };
00179
00180
00181
00182
00183
00184
00185
00186
00187 template <unsigned SIZE>
00188 AbstractBackwardEulerCardiacCell<SIZE>::AbstractBackwardEulerCardiacCell(
00189 unsigned numberOfStateVariables,
00190 unsigned voltageIndex,
00191 boost::shared_ptr<AbstractStimulusFunction> pIntracellularStimulus)
00192 : AbstractCardiacCell(boost::shared_ptr<AbstractIvpOdeSolver>(),
00193 numberOfStateVariables,
00194 voltageIndex,
00195 pIntracellularStimulus)
00196 {}
00197
00198 template <unsigned SIZE>
00199 AbstractBackwardEulerCardiacCell<SIZE>::~AbstractBackwardEulerCardiacCell()
00200 {}
00201
00202 template <unsigned SIZE>
00203 OdeSolution AbstractBackwardEulerCardiacCell<SIZE>::Compute(double tStart, double tEnd, double tSamp)
00204 {
00205
00206
00207
00208
00209
00210
00211 if (tSamp < mDt)
00212 {
00213 tSamp = mDt;
00214 }
00215 double _n_steps = (tEnd - tStart) / tSamp;
00216 const unsigned n_steps = (unsigned) floor(_n_steps+0.5);
00217 assert(fabs(tStart+n_steps*tSamp - tEnd) < 1e-12);
00218 const unsigned n_small_steps = (unsigned) floor(tSamp/mDt+0.5);
00219 assert(fabs(mDt*n_small_steps - tSamp) < 1e-12);
00220
00221
00222 OdeSolution solutions;
00223 solutions.SetNumberOfTimeSteps(n_steps);
00224 solutions.rGetSolutions().push_back(rGetStateVariables());
00225 solutions.rGetTimes().push_back(tStart);
00226 solutions.SetOdeSystemInformation(this->mpSystemInfo);
00227
00228
00229 double curr_time = tStart;
00230 for (unsigned i=0; i<n_steps; i++)
00231 {
00232 for (unsigned j=0; j<n_small_steps; j++)
00233 {
00234 curr_time = tStart + i*tSamp + j*mDt;
00235
00236
00237 UpdateTransmembranePotential(curr_time);
00238
00239
00240 ComputeOneStepExceptVoltage(curr_time);
00241
00242
00243 VerifyStateVariables();
00244 }
00245
00246
00247 solutions.rGetSolutions().push_back(rGetStateVariables());
00248 solutions.rGetTimes().push_back(curr_time+mDt);
00249 }
00250
00251 return solutions;
00252 }
00253
00254 template <unsigned SIZE>
00255 void AbstractBackwardEulerCardiacCell<SIZE>::ComputeExceptVoltage(double tStart, double tEnd)
00256 {
00257
00258
00259
00260 double _n_steps = (tEnd - tStart) / mDt;
00261 unsigned n_steps = (unsigned) floor(_n_steps+0.5);
00262 assert(fabs(tStart+n_steps*mDt - tEnd) < 1e-12);
00263
00264
00265 double curr_time;
00266 for (unsigned i=0; i<n_steps; i++)
00267 {
00268 curr_time = tStart + i*mDt;
00269
00270
00271 ComputeOneStepExceptVoltage(curr_time);
00272
00273
00274 VerifyStateVariables();
00275 }
00276 }
00277
00278 TEMPLATED_CLASS_IS_ABSTRACT_1_UNSIGNED(AbstractBackwardEulerCardiacCell)
00279
00280 #endif