AbstractBackwardEulerCardiacCell.hpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2010
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 */
00028 
00029 
00030 #ifndef ABSTRACTBACKWARDEULERCARDIACCELL_HPP_
00031 #define ABSTRACTBACKWARDEULERCARDIACCELL_HPP_
00032 
00033 #include "ChasteSerialization.hpp"
00034 #include <boost/serialization/base_object.hpp>
00035 #include "ClassIsAbstract.hpp"
00036 #include "AbstractCardiacCell.hpp"
00037 #include "Exception.hpp"
00038 
00039 #include <cassert>
00040 #include <cmath>
00041 
00056 template<unsigned SIZE>
00057 class AbstractBackwardEulerCardiacCell : public AbstractCardiacCell
00058 {
00059     private:
00061     friend class boost::serialization::access;
00068     template<class Archive>
00069     void serialize(Archive & archive, const unsigned int version)
00070     {
00071         // This calls serialize on the base class.
00072         archive & boost::serialization::base_object<AbstractCardiacCell>(*this);
00073     }
00074 public:
00075 
00091     AbstractBackwardEulerCardiacCell(
00092         unsigned numberOfStateVariables,
00093         unsigned voltageIndex,
00094         boost::shared_ptr<AbstractStimulusFunction> pIntracellularStimulus);
00095 
00097     virtual ~AbstractBackwardEulerCardiacCell();
00098 
00106     virtual void ComputeResidual(double time, const double rCurrentGuess[SIZE], double rResidual[SIZE])=0;
00107 
00115     virtual void ComputeJacobian(double time, const double rCurrentGuess[SIZE], double rJacobian[SIZE][SIZE])=0;
00116 
00128     virtual OdeSolution Compute(double tStart, double tEnd);
00129 
00139     virtual void ComputeExceptVoltage(double tStart, double tEnd);
00140 
00141 private:
00142 #define COVERAGE_IGNORE
00143 
00150     void EvaluateYDerivatives(double time, const std::vector<double> &rY, std::vector<double> &rDY)
00151     {
00152         NEVER_REACHED;
00153     }
00154 #undef COVERAGE_IGNORE
00155 
00156 protected:
00165     virtual void ComputeOneStepExceptVoltage(double tStart)=0;
00166 
00174     virtual void UpdateTransmembranePotential(double time)=0;
00175 };
00176 
00177 
00178 /*
00179  * NOTE: Explicit instantiation is not used for this class, because the SIZE
00180  * template parameter could take arbitrary values.
00181  */
00182 
00183 
00184 template <unsigned SIZE>
00185 AbstractBackwardEulerCardiacCell<SIZE>::AbstractBackwardEulerCardiacCell(
00186     unsigned numberOfStateVariables,
00187     unsigned voltageIndex,
00188     boost::shared_ptr<AbstractStimulusFunction> pIntracellularStimulus)
00189         : AbstractCardiacCell(boost::shared_ptr<AbstractIvpOdeSolver>(),
00190                               numberOfStateVariables,
00191                               voltageIndex,
00192                               pIntracellularStimulus)
00193 {}
00194 
00195 template <unsigned SIZE>
00196 AbstractBackwardEulerCardiacCell<SIZE>::~AbstractBackwardEulerCardiacCell()
00197 {}
00198 
00199 template <unsigned SIZE>
00200 OdeSolution AbstractBackwardEulerCardiacCell<SIZE>::Compute(double tStart, double tEnd)
00201 {
00202     // In this method, we iterate over timesteps, doing the following for each:
00203     //   - update V using a forward Euler step
00204     //   - call ComputeExceptVoltage(t) to update the remaining state variables
00205     //     using backward Euler
00206     // Check length of time interval
00207     double _n_steps = (tEnd - tStart) / mDt;
00208     unsigned n_steps = (unsigned) round(_n_steps);
00209     assert(fabs(tStart+n_steps*mDt - tEnd) < 1e-12);
00210 
00211     // Initialise solution store
00212     OdeSolution solutions;
00213     solutions.SetNumberOfTimeSteps(n_steps);
00214     solutions.rGetSolutions().push_back(rGetStateVariables());
00215     solutions.rGetTimes().push_back(tStart);
00216     solutions.SetOdeSystemInformation(this->mpSystemInfo);
00217 
00218     // Loop over time
00219     double curr_time;
00220     for (unsigned i=0; i<n_steps; i++)
00221     {
00222         curr_time = tStart + i*mDt;
00223 
00224         // Compute next value of V
00225         UpdateTransmembranePotential(curr_time);
00226 
00227         // Compute other state variables
00228         ComputeOneStepExceptVoltage(curr_time);
00229 
00230         // Update solutions
00231         solutions.rGetSolutions().push_back(rGetStateVariables());
00232         solutions.rGetTimes().push_back(curr_time+mDt);
00233 
00234         // check gating variables are still in range
00235         VerifyStateVariables();
00236     }
00237 
00238     return solutions;
00239 }
00240 
00241 template <unsigned SIZE>
00242 void AbstractBackwardEulerCardiacCell<SIZE>::ComputeExceptVoltage(double tStart, double tEnd)
00243 {
00244     // This method iterates over timesteps, calling ComputeExceptVoltage(t) at
00245     // each one, to update all state variables except for V, using backward Euler.
00246     // Check length of time interval
00247     double _n_steps = (tEnd - tStart) / mDt;
00248     unsigned n_steps = (unsigned) round(_n_steps);
00249     assert(fabs(tStart+n_steps*mDt - tEnd) < 1e-12);
00250 
00251     // Loop over time
00252     double curr_time;
00253     for (unsigned i=0; i<n_steps; i++)
00254     {
00255         curr_time = tStart + i*mDt;
00256 
00257         // Compute other state variables
00258         ComputeOneStepExceptVoltage(curr_time);
00259 
00260         // check gating variables are still in range
00261         VerifyStateVariables();
00262     }
00263 }
00264 
00265 TEMPLATED_CLASS_IS_ABSTRACT_1_UNSIGNED(AbstractBackwardEulerCardiacCell);
00266 
00267 #endif /*ABSTRACTBACKWARDEULERCARDIACCELL_HPP_*/

Generated by  doxygen 1.6.2