AbstractRushLarsenCardiacCell.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2011
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 #include "AbstractRushLarsenCardiacCell.hpp"
00030 
00031 #include <cassert>
00032 #include <cmath>
00033 
00034 #include "Exception.hpp"
00035 #include "OdeSolution.hpp"
00036 #include "TimeStepper.hpp"
00037 
00038 AbstractRushLarsenCardiacCell::AbstractRushLarsenCardiacCell(unsigned numberOfStateVariables,
00039                                                              unsigned voltageIndex,
00040                                                              boost::shared_ptr<AbstractStimulusFunction> pIntracellularStimulus)
00041     : AbstractCardiacCell(boost::shared_ptr<AbstractIvpOdeSolver>(),
00042                           numberOfStateVariables,
00043                           voltageIndex,
00044                           pIntracellularStimulus)
00045 {}
00046 
00047 AbstractRushLarsenCardiacCell::~AbstractRushLarsenCardiacCell()
00048 {}
00049 
00050 OdeSolution AbstractRushLarsenCardiacCell::Compute(double tStart, double tEnd, double tSamp)
00051 {
00052     // In this method, we iterate over timesteps, doing the following for each:
00053     //   - update V using a forward Euler step
00054     //   - do as in ComputeExceptVoltage(t) to update the remaining state variables
00055     //     using Rush Larsen method or forward Euler as appropriate
00056 
00057     // Check length of time interval
00058     if (tSamp < mDt)
00059     {
00060         tSamp = mDt;
00061     }
00062     const unsigned n_steps = (unsigned) floor((tEnd - tStart)/tSamp + 0.5);
00063     assert(fabs(tStart+n_steps*tSamp - tEnd) < 1e-12);
00064     const unsigned n_small_steps = (unsigned) floor(tSamp/mDt+0.5);
00065     assert(fabs(mDt*n_small_steps - tSamp) < 1e-12);
00066 
00067     // Initialise solution store
00068     OdeSolution solutions;
00069     solutions.SetNumberOfTimeSteps(n_steps);
00070     solutions.rGetSolutions().push_back(rGetStateVariables());
00071     solutions.rGetTimes().push_back(tStart);
00072     solutions.SetOdeSystemInformation(this->mpSystemInfo);
00073 
00074     std::vector<double> dy(mNumberOfStateVariables, 0);
00075     std::vector<double> alpha(mNumberOfStateVariables, 0);
00076     std::vector<double> beta(mNumberOfStateVariables, 0);
00077 
00078     // Loop over time
00079     for (unsigned i=0; i<n_steps; i++)
00080     {
00081         double curr_time = tStart;
00082         for (unsigned j=0; j<n_small_steps; j++)
00083         {
00084             curr_time = tStart + i*tSamp + j*mDt;
00085             EvaluateEquations(curr_time, dy, alpha, beta);
00086             UpdateTransmembranePotential(dy);
00087             ComputeOneStepExceptVoltage(dy, alpha, beta);
00088             VerifyStateVariables();
00089         }
00090 
00091         // Update solutions
00092         solutions.rGetSolutions().push_back(rGetStateVariables());
00093         solutions.rGetTimes().push_back(curr_time+mDt);
00094     }
00095 
00096     return solutions;
00097 }
00098 
00099 void AbstractRushLarsenCardiacCell::ComputeExceptVoltage(double tStart, double tEnd)
00100 {
00101     mSetVoltageDerivativeToZero = true;
00102     TimeStepper stepper(tStart, tEnd, mDt);
00103 
00104     std::vector<double> dy(mNumberOfStateVariables, 0);
00105     std::vector<double> alpha(mNumberOfStateVariables, 0);
00106     std::vector<double> beta(mNumberOfStateVariables, 0);
00107 
00108     while (!stepper.IsTimeAtEnd())
00109     {
00110         EvaluateEquations(stepper.GetTime(), dy, alpha, beta);
00111         ComputeOneStepExceptVoltage(dy, alpha, beta);
00112 
00113 #ifndef NDEBUG
00114         // Check gating variables are still in range
00115         VerifyStateVariables();
00116 #endif // NDEBUG
00117 
00118         stepper.AdvanceOneTimeStep();
00119     }
00120     mSetVoltageDerivativeToZero = false;
00121 }
00122 
00123 void AbstractRushLarsenCardiacCell::SolveAndUpdateState(double tStart, double tEnd)
00124 {
00125     TimeStepper stepper(tStart, tEnd, mDt);
00126 
00127     std::vector<double> dy(mNumberOfStateVariables, 0);
00128     std::vector<double> alpha(mNumberOfStateVariables, 0);
00129     std::vector<double> beta(mNumberOfStateVariables, 0);
00130 
00131     while (!stepper.IsTimeAtEnd())
00132     {
00133         EvaluateEquations(stepper.GetTime(), dy, alpha, beta);
00134         UpdateTransmembranePotential(dy);
00135         ComputeOneStepExceptVoltage(dy, alpha, beta);
00136         VerifyStateVariables();
00137 
00138         stepper.AdvanceOneTimeStep();
00139     }
00140 }
00141 
00142 void AbstractRushLarsenCardiacCell::UpdateTransmembranePotential(const std::vector<double> &rDY)
00143 {
00144     unsigned v_index = GetVoltageIndex();
00145     rGetStateVariables()[v_index] += mDt*rDY[v_index];
00146 }
Generated on Thu Dec 22 13:00:06 2011 for Chaste by  doxygen 1.6.3