LuoRudyIModel1991OdeSystem.cpp

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 #include "LuoRudyIModel1991OdeSystem.hpp"
00029 #include "OdeSystemInformation.hpp"
00030 #include <cmath>
00031 
00032 //#include <iostream>
00033 #include "Exception.hpp"
00034 
00038 LuoRudyIModel1991OdeSystem::LuoRudyIModel1991OdeSystem(AbstractIvpOdeSolver *pSolver,
00039                                                        AbstractStimulusFunction *pIntracellularStimulus)
00040         : AbstractCardiacCell(pSolver, 8, 4, pIntracellularStimulus)
00041 {
00042     mpSystemInfo = OdeSystemInformation<LuoRudyIModel1991OdeSystem>::Instance();
00043     
00044     // set the final paramter
00045     fast_sodium_current_E_Na = ((membrane_R * membrane_T) / membrane_F) *
00046                                log(ionic_concentrations_Nao / ionic_concentrations_Nai);
00047     
00048     AbstractCardiacCell::Init();
00049 }
00050 
00054 LuoRudyIModel1991OdeSystem::~LuoRudyIModel1991OdeSystem(void)
00055 {    
00056 }
00057 
00058 double LuoRudyIModel1991OdeSystem::GetIntracellularCalciumConcentration()
00059 {
00060     return mStateVariables[3];
00061 }
00062 
00072 void LuoRudyIModel1991OdeSystem::EvaluateYDerivatives(double time,
00073                                                       const std::vector<double> &rY,
00074                                                       std::vector<double> &rDY)
00075 {
00076     double fast_sodium_current_h_gate_h = rY[0];
00077     double fast_sodium_current_j_gate_j = rY[1];
00078     double fast_sodium_current_m_gate_m = rY[2];
00079     double intracellular_calcium_concentration_Cai = rY[3];
00080     double membrane_V = rY[4];
00081     double slow_inward_current_d_gate_d = rY[5];
00082     double slow_inward_current_f_gate_f = rY[6];
00083     double time_dependent_potassium_current_X_gate_X = rY[7];
00084     
00085     double background_current_i_b = background_current_g_b*(membrane_V-background_current_E_b);
00086     
00087     double fast_sodium_current_h_gate_alpha_h;
00088     
00089     if (membrane_V < -40.0)
00090     {
00091         fast_sodium_current_h_gate_alpha_h = 0.135*exp((80.0+membrane_V)/-6.8);
00092     }
00093     else
00094     {
00095         fast_sodium_current_h_gate_alpha_h = 0.0;
00096     }
00097     
00098     double fast_sodium_current_h_gate_beta_h;
00099     
00100     if (membrane_V < -40.0)
00101     {
00102         fast_sodium_current_h_gate_beta_h = 3.56*exp(0.079*membrane_V)+3.1e5*exp(0.35*membrane_V);
00103     }
00104     else
00105     {
00106         fast_sodium_current_h_gate_beta_h = 1.0/(0.13*(1.0+exp((membrane_V+10.66)/-11.1)));
00107     }
00108     
00109     double fast_sodium_current_h_gate_h_prime = fast_sodium_current_h_gate_alpha_h*(1.0-fast_sodium_current_h_gate_h)-fast_sodium_current_h_gate_beta_h*fast_sodium_current_h_gate_h;
00110     
00111     double fast_sodium_current_j_gate_alpha_j;
00112     
00113     if (membrane_V < -40.0)
00114     {
00115         fast_sodium_current_j_gate_alpha_j = (-1.2714e5*exp(0.2444*membrane_V)-3.474e-5*exp(-0.04391*membrane_V))*(membrane_V+37.78)/(1.0+exp(0.311*(membrane_V+79.23)));
00116     }
00117     else
00118     {
00119         fast_sodium_current_j_gate_alpha_j = 0.0;
00120     }
00121     
00122     double fast_sodium_current_j_gate_beta_j;
00123     
00124     if (membrane_V < -40.0)
00125     {
00126         fast_sodium_current_j_gate_beta_j = 0.1212*exp(-0.01052*membrane_V)/(1.0+exp(-0.1378*(membrane_V+40.14)));
00127     }
00128     else
00129     {
00130         fast_sodium_current_j_gate_beta_j = 0.3*exp(-2.535e-7*membrane_V)/(1.0+exp(-0.1*(membrane_V+32.0)));
00131     }
00132     
00133     double fast_sodium_current_j_gate_j_prime = fast_sodium_current_j_gate_alpha_j*(1.0-fast_sodium_current_j_gate_j)-fast_sodium_current_j_gate_beta_j*fast_sodium_current_j_gate_j;
00134     double fast_sodium_current_m_gate_alpha_m = 0.32*(membrane_V+47.13)/(1.0-exp(-0.1*(membrane_V+47.13)));
00135     double fast_sodium_current_m_gate_beta_m = 0.08*exp(-membrane_V/11.0);
00136     double fast_sodium_current_m_gate_m_prime = fast_sodium_current_m_gate_alpha_m*(1.0-fast_sodium_current_m_gate_m)-fast_sodium_current_m_gate_beta_m*fast_sodium_current_m_gate_m;
00137     double fast_sodium_current_i_Na = fast_sodium_current_g_Na*pow(fast_sodium_current_m_gate_m, 3.0)*fast_sodium_current_h_gate_h*fast_sodium_current_j_gate_j*(membrane_V-fast_sodium_current_E_Na);
00138     
00139     double slow_inward_current_d_gate_alpha_d = 0.095*exp(-0.01*(membrane_V-5.0))/(1.0+exp(-0.072*(membrane_V-5.0)));
00140     double slow_inward_current_d_gate_beta_d = 0.07*exp(-0.017*(membrane_V+44.0))/(1.0+exp(0.05*(membrane_V+44.0)));
00141     double slow_inward_current_d_gate_d_prime = slow_inward_current_d_gate_alpha_d*(1.0-slow_inward_current_d_gate_d)-slow_inward_current_d_gate_beta_d*slow_inward_current_d_gate_d;
00142     
00143     double slow_inward_current_f_gate_alpha_f = 0.012*exp(-0.008*(membrane_V+28.0))/(1.0+exp(0.15*(membrane_V+28.0)));
00144     double slow_inward_current_f_gate_beta_f = 0.0065*exp(-0.02*(membrane_V+30.0))/(1.0+exp(-0.2*(membrane_V+30.0)));
00145     double slow_inward_current_f_gate_f_prime = slow_inward_current_f_gate_alpha_f*(1.0-slow_inward_current_f_gate_f)-slow_inward_current_f_gate_beta_f*slow_inward_current_f_gate_f;
00146     
00147     double slow_inward_current_E_si = 7.7-13.0287*log(intracellular_calcium_concentration_Cai);
00148     double slow_inward_current_i_si = 0.09*slow_inward_current_d_gate_d*slow_inward_current_f_gate_f*(membrane_V-slow_inward_current_E_si);
00149     double intracellular_calcium_concentration_Cai_prime = -1e-4*slow_inward_current_i_si+0.07*(1e-4-intracellular_calcium_concentration_Cai);
00150     double time_dependent_potassium_current_g_K = 0.282*sqrt(ionic_concentrations_Ko/5.4);
00151     
00152     double time_dependent_potassium_current_Xi_gate_Xi;
00153     
00154     if (membrane_V > -100.0)
00155     {
00156         time_dependent_potassium_current_Xi_gate_Xi = 2.837*(exp(0.04*(membrane_V+77.0))-1.0)/((membrane_V+77.0)*exp(0.04*(membrane_V+35.0)));
00157     }
00158     else
00159     {
00160         #define COVERAGE_IGNORE
00161         time_dependent_potassium_current_Xi_gate_Xi = 1.0;
00162         #undef COVERAGE_IGNORE
00163     }
00164     
00165     double time_dependent_potassium_current_X_gate_alpha_X = 0.0005*exp(0.083*(membrane_V+50.0))/(1.0+exp(0.057*(membrane_V+50.0)));
00166     double time_dependent_potassium_current_X_gate_beta_X = 0.0013*exp(-0.06*(membrane_V+20.0))/(1.0+exp(-0.04*(membrane_V+20.0)));
00167     double time_dependent_potassium_current_X_gate_X_prime = time_dependent_potassium_current_X_gate_alpha_X*(1.0-time_dependent_potassium_current_X_gate_X)-time_dependent_potassium_current_X_gate_beta_X*time_dependent_potassium_current_X_gate_X;
00168     
00169     double time_dependent_potassium_current_E_K = ((membrane_R*membrane_T)/membrane_F)*log((ionic_concentrations_Ko+time_dependent_potassium_current_PR_NaK*ionic_concentrations_Nao)/(ionic_concentrations_Ki+time_dependent_potassium_current_PR_NaK*ionic_concentrations_Nai));
00170     double time_dependent_potassium_current_i_K = time_dependent_potassium_current_g_K*time_dependent_potassium_current_X_gate_X*time_dependent_potassium_current_Xi_gate_Xi*(membrane_V-time_dependent_potassium_current_E_K);
00171     double time_independent_potassium_current_g_K1 = 0.6047*sqrt(ionic_concentrations_Ko/5.4);
00172     double time_independent_potassium_current_E_K1 =((membrane_R*membrane_T)/membrane_F)*log(ionic_concentrations_Ko/ionic_concentrations_Ki);
00173     double time_independent_potassium_current_K1_gate_alpha_K1 = 1.02/(1.0+exp(0.2385*(membrane_V-time_independent_potassium_current_E_K1-59.215)));
00174     double time_independent_potassium_current_K1_gate_beta_K1 = (0.49124*exp(0.08032*(membrane_V+5.476-time_independent_potassium_current_E_K1))+exp(0.06175*(membrane_V-(time_independent_potassium_current_E_K1+594.31))))/(1.0+exp(-0.5143*(membrane_V-time_independent_potassium_current_E_K1+4.753)));
00175     double time_independent_potassium_current_K1_gate_K1_infinity = time_independent_potassium_current_K1_gate_alpha_K1/(time_independent_potassium_current_K1_gate_alpha_K1+time_independent_potassium_current_K1_gate_beta_K1);
00176     double time_independent_potassium_current_i_K1 = time_independent_potassium_current_g_K1*time_independent_potassium_current_K1_gate_K1_infinity*(membrane_V-time_independent_potassium_current_E_K1);
00177     double plateau_potassium_current_Kp = 1.0/(1.0+exp((7.488-membrane_V)/5.98));
00178     double plateau_potassium_current_E_Kp = time_independent_potassium_current_E_K1;
00179     double plateau_potassium_current_i_Kp = plateau_potassium_current_g_Kp*plateau_potassium_current_Kp*(membrane_V-plateau_potassium_current_E_Kp);
00180     double i_stim = GetStimulus(time);
00181     
00182     //calculate dV
00183     double membrane_V_prime = (-1.0/membrane_C)*(fast_sodium_current_i_Na+slow_inward_current_i_si+time_dependent_potassium_current_i_K+time_independent_potassium_current_i_K1+plateau_potassium_current_i_Kp+background_current_i_b + i_stim);
00184     // do not update voltage if the mSetVoltageDerivativeToZero flag has been set
00185     if (mSetVoltageDerivativeToZero)
00186     {
00187         membrane_V_prime = 0;
00188     }
00189     
00190     rDY[0] = fast_sodium_current_h_gate_h_prime;
00191     rDY[1] = fast_sodium_current_j_gate_j_prime;
00192     rDY[2] = fast_sodium_current_m_gate_m_prime;
00193     rDY[3] = intracellular_calcium_concentration_Cai_prime;
00194     rDY[4] = membrane_V_prime;
00195     rDY[5] = slow_inward_current_d_gate_d_prime;
00196     rDY[6] = slow_inward_current_f_gate_f_prime;
00197     rDY[7] = time_dependent_potassium_current_X_gate_X_prime;
00198 }
00199 
00200 
00201 double LuoRudyIModel1991OdeSystem::GetIIonic()
00202 {
00203     double fast_sodium_current_h_gate_h = mStateVariables[0];
00204     double fast_sodium_current_j_gate_j = mStateVariables[1];
00205     double fast_sodium_current_m_gate_m = mStateVariables[2];
00206     double intracellular_calcium_concentration_Cai = mStateVariables[3];
00207     double membrane_V = mStateVariables[4];
00208     double slow_inward_current_d_gate_d = mStateVariables[5];
00209     double slow_inward_current_f_gate_f = mStateVariables[6];
00210     double time_dependent_potassium_current_X_gate_X = mStateVariables[7];
00211     
00212     /*
00213      * Compute the LuoRudyIModel1991OdeSystem model
00214      */
00215     double background_current_i_b = background_current_g_b*(membrane_V-background_current_E_b);
00216     
00217     double fast_sodium_current_i_Na = fast_sodium_current_g_Na*pow(fast_sodium_current_m_gate_m, 3.0)*fast_sodium_current_h_gate_h*fast_sodium_current_j_gate_j*(membrane_V-fast_sodium_current_E_Na);
00218     
00219     double slow_inward_current_E_si = 7.7-13.0287*log(intracellular_calcium_concentration_Cai);
00220     double slow_inward_current_i_si = 0.09*slow_inward_current_d_gate_d*slow_inward_current_f_gate_f*(membrane_V-slow_inward_current_E_si);
00221     
00222     double time_dependent_potassium_current_g_K = 0.282*sqrt(ionic_concentrations_Ko/5.4);
00223     double time_dependent_potassium_current_Xi_gate_Xi;
00224     
00225     // Although the equation below looks strange (particularly the arguments of the
00226     // exponentials, it is in fact correct.
00227     if (membrane_V > -100.0)
00228     {
00229         time_dependent_potassium_current_Xi_gate_Xi = 2.837*(exp(0.04*(membrane_V+77.0))-1.0)/((membrane_V+77.0)*exp(0.04*(membrane_V+35.0)));
00230     }
00231     else
00232     {
00233         #define COVERAGE_IGNORE
00234         time_dependent_potassium_current_Xi_gate_Xi = 1.0;
00235         #undef COVERAGE_IGNORE
00236     }
00237     double time_dependent_potassium_current_E_K = ((membrane_R*membrane_T)/membrane_F)*log((ionic_concentrations_Ko+time_dependent_potassium_current_PR_NaK*ionic_concentrations_Nao)/(ionic_concentrations_Ki+time_dependent_potassium_current_PR_NaK*ionic_concentrations_Nai));
00238     double time_dependent_potassium_current_i_K = time_dependent_potassium_current_g_K*time_dependent_potassium_current_X_gate_X*time_dependent_potassium_current_Xi_gate_Xi*(membrane_V-time_dependent_potassium_current_E_K);
00239     
00240     double time_independent_potassium_current_g_K1 = 0.6047*sqrt(ionic_concentrations_Ko/5.4);
00241     double time_independent_potassium_current_E_K1 =((membrane_R*membrane_T)/membrane_F)*log(ionic_concentrations_Ko/ionic_concentrations_Ki);
00242     double time_independent_potassium_current_K1_gate_alpha_K1 = 1.02/(1.0+exp(0.2385*(membrane_V-time_independent_potassium_current_E_K1-59.215)));
00243     double time_independent_potassium_current_K1_gate_beta_K1 = (0.49124*exp(0.08032*(membrane_V+5.476-time_independent_potassium_current_E_K1))+exp(0.06175*(membrane_V-(time_independent_potassium_current_E_K1+594.31))))/(1.0+exp(-0.5143*(membrane_V-time_independent_potassium_current_E_K1+4.753)));
00244     double time_independent_potassium_current_K1_gate_K1_infinity = time_independent_potassium_current_K1_gate_alpha_K1/(time_independent_potassium_current_K1_gate_alpha_K1+time_independent_potassium_current_K1_gate_beta_K1);
00245     double time_independent_potassium_current_i_K1 = time_independent_potassium_current_g_K1*time_independent_potassium_current_K1_gate_K1_infinity*(membrane_V-time_independent_potassium_current_E_K1);
00246     
00247     double plateau_potassium_current_Kp = 1.0/(1.0+exp((7.488-membrane_V)/5.98));
00248     double plateau_potassium_current_E_Kp = time_independent_potassium_current_E_K1;
00249     double plateau_potassium_current_i_Kp = plateau_potassium_current_g_Kp*plateau_potassium_current_Kp*(membrane_V-plateau_potassium_current_E_Kp);
00250     
00251     double i_ionic = fast_sodium_current_i_Na+slow_inward_current_i_si+time_dependent_potassium_current_i_K+time_independent_potassium_current_i_K1+plateau_potassium_current_i_Kp+background_current_i_b;
00252     
00253     assert(!isnan(i_ionic));
00254     return i_ionic;
00255 }
00256 
00257 void LuoRudyIModel1991OdeSystem::VerifyStateVariables()
00258 {
00259     const std::vector<double>& rY = rGetStateVariables();
00260  
00261     const double fast_sodium_current_h_gate_h = rY[0];            // gating
00262     const double fast_sodium_current_j_gate_j = rY[1];            // gating
00263     const double fast_sodium_current_m_gate_m = rY[2];            // gating
00264     const double intracellular_calcium_concentration_Cai = rY[3]; // concentration
00265     const double slow_inward_current_d_gate_d = rY[5];            // gating
00266     const double slow_inward_current_f_gate_f = rY[6];            // gating
00267     const double time_dependent_potassium_current_X_gate_X = rY[7]; // gating
00268 
00269     #define COVERAGE_IGNORE
00270     if (!(0.0<=fast_sodium_current_h_gate_h && fast_sodium_current_h_gate_h<=1.0))
00271     {
00272         EXCEPTION(DumpState("h gate for fast sodium current has gone out of range. Check model parameters, for example spatial stepsize"));
00273     }
00274     
00275     if (!(0.0<=fast_sodium_current_j_gate_j && fast_sodium_current_j_gate_j<=1.0))
00276     {
00277         EXCEPTION(DumpState("j gate for fast sodium current has gone out of range. Check model parameters, for example spatial stepsize"));
00278     }
00279     
00280     if (!(0.0<=fast_sodium_current_m_gate_m && fast_sodium_current_m_gate_m<=1.0))
00281     {
00282         EXCEPTION(DumpState("m gate for fast sodium current has gone out of range. Check model parameters, for example spatial stepsize"));
00283     }
00284 
00285     if (!(0.0<intracellular_calcium_concentration_Cai))
00286     {
00287         EXCEPTION(DumpState("intracellular_calcium_concentration_Cai has become non-positive, ie gone out of range. Check model parameters, for example spatial stepsize"));
00288     }
00289     
00290     if (!(0.0<=slow_inward_current_d_gate_d && slow_inward_current_d_gate_d<=1.0))
00291     {
00292         EXCEPTION(DumpState("d gate for slow inward current has gone out of range. Check model parameters, for example spatial stepsize"));
00293     }
00294     
00295     if (!(0.0<=slow_inward_current_f_gate_f && slow_inward_current_f_gate_f<=1.0))
00296     {
00297         EXCEPTION(DumpState("f gate for slow inward current has gone out of range. Check model parameters, for example spatial stepsize"));
00298     }
00299     
00300     if (!(0.0<=time_dependent_potassium_current_X_gate_X && time_dependent_potassium_current_X_gate_X<=1.0))
00301     {
00302         EXCEPTION(DumpState("X gate for time dependent potassium current has gone out of range. Check model parameters, for example spatial stepsize"));
00303     }
00304     #undef COVERAGE_IGNORE
00305 }
00306 
00307 
00308     
00309 
00310 template<>
00311 void OdeSystemInformation<LuoRudyIModel1991OdeSystem>::Initialise(void)
00312 {
00313     // State variables
00314     this->mVariableNames.push_back("h");
00315     this->mVariableUnits.push_back("");
00316     this->mInitialConditions.push_back(0.9804713);
00317     
00318     this->mVariableNames.push_back("j");
00319     this->mVariableUnits.push_back("");
00320     this->mInitialConditions.push_back(0.98767124);
00321     
00322     this->mVariableNames.push_back("m");
00323     this->mVariableUnits.push_back("");
00324     this->mInitialConditions.push_back(0.00187018);
00325     
00326     this->mVariableNames.push_back("CaI");
00327     this->mVariableUnits.push_back("mMol");
00328     this->mInitialConditions.push_back(0.0002);
00329     
00330     this->mVariableNames.push_back("V");
00331     this->mVariableUnits.push_back("mV");
00332     this->mInitialConditions.push_back(-83.853);
00333     
00334     this->mVariableNames.push_back("d");
00335     this->mVariableUnits.push_back("");
00336     this->mInitialConditions.push_back(0.00316354);
00337     
00338     this->mVariableNames.push_back("f");
00339     this->mVariableUnits.push_back("");
00340     this->mInitialConditions.push_back(0.99427859);
00341     
00342     this->mVariableNames.push_back("x");
00343     this->mVariableUnits.push_back("");
00344     this->mInitialConditions.push_back(0.16647703);
00345     
00346     this->mInitialised = true;
00347 }

Generated on Wed Mar 18 12:51:51 2009 for Chaste by  doxygen 1.5.5