Lr91Cvode.cpp

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

Generated by  doxygen 1.6.2