AbstractBackwardEulerCardiacCell.hpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2009
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 <boost/serialization/access.hpp>
00034 #include <boost/serialization/is_abstract.hpp>
00035 #include <boost/serialization/base_object.hpp>
00036 
00037 #include "AbstractCardiacCell.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 
00105     virtual void ComputeResidual(const double rCurrentGuess[SIZE], double rResidual[SIZE])=0;
00106 
00113     virtual void ComputeJacobian(const double rCurrentGuess[SIZE], double rJacobian[SIZE][SIZE])=0;
00114 
00126     virtual OdeSolution Compute(double tStart, double tEnd);
00127 
00137     virtual void ComputeExceptVoltage(double tStart, double tEnd);
00138 
00139 private:
00140 #define COVERAGE_IGNORE
00141 
00148     void EvaluateYDerivatives(double time, const std::vector<double> &rY, std::vector<double> &rDY)
00149     {
00150         NEVER_REACHED;
00151     }
00152 #undef COVERAGE_IGNORE
00153 
00154 protected:
00163     virtual void ComputeOneStepExceptVoltage(double tStart)=0;
00164 
00172     virtual void UpdateTransmembranePotential(double time)=0;
00173 };
00174 
00175 
00176 /*
00177  * NOTE: Explicit instantiation is not used for this class, because the SIZE
00178  * template parameter could take arbitrary values.
00179  */
00180 
00181 
00182 template <unsigned SIZE>
00183 AbstractBackwardEulerCardiacCell<SIZE>::AbstractBackwardEulerCardiacCell(
00184     unsigned numberOfStateVariables,
00185     unsigned voltageIndex,
00186     boost::shared_ptr<AbstractStimulusFunction> pIntracellularStimulus)
00187         : AbstractCardiacCell(boost::shared_ptr<AbstractIvpOdeSolver>(),
00188                               numberOfStateVariables,
00189                               voltageIndex,
00190                               pIntracellularStimulus)
00191 {}
00192 
00193 template <unsigned SIZE>
00194 AbstractBackwardEulerCardiacCell<SIZE>::~AbstractBackwardEulerCardiacCell()
00195 {}
00196 
00197 template <unsigned SIZE>
00198 OdeSolution AbstractBackwardEulerCardiacCell<SIZE>::Compute(double tStart, double tEnd)
00199 {
00200     // In this method, we iterate over timesteps, doing the following for each:
00201     //   - update V using a forward Euler step
00202     //   - call ComputeExceptVoltage(t) to update the remaining state variables
00203     //     using backward Euler
00204     // Check length of time interval
00205     double _n_steps = (tEnd - tStart) / mDt;
00206     unsigned n_steps = (unsigned) round(_n_steps);
00207     assert(fabs(tStart+n_steps*mDt - tEnd) < 1e-12);
00208 
00209     // Initialise solution store
00210     OdeSolution solutions;
00211     solutions.SetNumberOfTimeSteps(n_steps);
00212     solutions.rGetSolutions().push_back(rGetStateVariables());
00213     solutions.rGetTimes().push_back(tStart);
00214 
00215     // Loop over time
00216     double curr_time;
00217     for (unsigned i=0; i<n_steps; i++)
00218     {
00219         curr_time = tStart + i*mDt;
00220 
00221         // Compute next value of V
00222         UpdateTransmembranePotential(curr_time);
00223 
00224         // Compute other state variables
00225         ComputeOneStepExceptVoltage(curr_time);
00226 
00227         // Update solutions
00228         solutions.rGetSolutions().push_back(rGetStateVariables());
00229         solutions.rGetTimes().push_back(curr_time+mDt);
00230 
00231         // check gating variables are still in range
00232         VerifyStateVariables();
00233     }
00234 
00235     return solutions;
00236 }
00237 
00238 template <unsigned SIZE>
00239 void AbstractBackwardEulerCardiacCell<SIZE>::ComputeExceptVoltage(double tStart, double tEnd)
00240 {
00241     // This method iterates over timesteps, calling ComputeExceptVoltage(t) at
00242     // each one, to update all state variables except for V, using backward Euler.
00243     // Check length of time interval
00244     double _n_steps = (tEnd - tStart) / mDt;
00245     unsigned n_steps = (unsigned) round(_n_steps);
00246     assert(fabs(tStart+n_steps*mDt - tEnd) < 1e-12);
00247 
00248     // Loop over time
00249     double curr_time;
00250     for (unsigned i=0; i<n_steps; i++)
00251     {
00252         curr_time = tStart + i*mDt;
00253 
00254         // Compute other state variables
00255         ComputeOneStepExceptVoltage(curr_time);
00256 
00257         // check gating variables are still in range
00258         VerifyStateVariables();
00259     }
00260 }
00261 
00262 namespace boost
00263 {
00264 namespace serialization
00265 {
00271 template<unsigned SIZE>
00272 struct is_abstract<AbstractBackwardEulerCardiacCell<SIZE> >
00273 {
00275     typedef mpl::bool_<true> type;
00277     BOOST_STATIC_CONSTANT(bool, value=true);
00278 };
00279 }
00280 }
00281 
00282 
00283 #endif /*ABSTRACTBACKWARDEULERCARDIACCELL_HPP_*/

Generated on Tue Aug 4 16:10:21 2009 for Chaste by  doxygen 1.5.5