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 <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         // This calls serialize on the base class.
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  * NOTE: Explicit instantiation is not used for this class, because the SIZE
00183  * template parameter could take arbitrary values.
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     // In this method, we iterate over timesteps, doing the following for each:
00206     //   - update V using a forward Euler step
00207     //   - call ComputeExceptVoltage(t) to update the remaining state variables
00208     //     using backward Euler
00209     
00210     // Check length of time interval
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     // Initialise solution store
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     // Loop over time
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             // Compute next value of V
00237             UpdateTransmembranePotential(curr_time);
00238     
00239             // Compute other state variables
00240             ComputeOneStepExceptVoltage(curr_time);
00241 
00242             // check gating variables are still in range
00243             VerifyStateVariables();
00244         }
00245 
00246         // Update solutions
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     // This method iterates over timesteps, calling ComputeExceptVoltage(t) at
00258     // each one, to update all state variables except for V, using backward Euler.
00259     // Check length of time interval
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     // Loop over time
00265     double curr_time;
00266     for (unsigned i=0; i<n_steps; i++)
00267     {
00268         curr_time = tStart + i*mDt;
00269 
00270         // Compute other state variables
00271         ComputeOneStepExceptVoltage(curr_time);
00272 
00273         // check gating variables are still in range
00274         VerifyStateVariables();
00275     }
00276 }
00277 
00278 TEMPLATED_CLASS_IS_ABSTRACT_1_UNSIGNED(AbstractBackwardEulerCardiacCell)
00279 
00280 #endif /*ABSTRACTBACKWARDEULERCARDIACCELL_HPP_*/

Generated on Mon Nov 1 12:35:16 2010 for Chaste by  doxygen 1.5.5