Chaste Release::3.1
TysonNovak2001OdeSystem.cpp
00001 /*
00002 
00003 Copyright (c) 2005-2012, University of Oxford.
00004 All rights reserved.
00005 
00006 University of Oxford means the Chancellor, Masters and Scholars of the
00007 University of Oxford, having an administrative office at Wellington
00008 Square, Oxford OX1 2JD, UK.
00009 
00010 This file is part of Chaste.
00011 
00012 Redistribution and use in source and binary forms, with or without
00013 modification, are permitted provided that the following conditions are met:
00014  * Redistributions of source code must retain the above copyright notice,
00015    this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright notice,
00017    this list of conditions and the following disclaimer in the documentation
00018    and/or other materials provided with the distribution.
00019  * Neither the name of the University of Oxford nor the names of its
00020    contributors may be used to endorse or promote products derived from this
00021    software without specific prior written permission.
00022 
00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 
00034 */
00035 
00036 #include "TysonNovak2001OdeSystem.hpp"
00037 #include "OdeSystemInformation.hpp"
00038 #include "MathsCustomFunctions.hpp"
00039 
00040 TysonNovak2001OdeSystem::TysonNovak2001OdeSystem(std::vector<double> stateVariables)
00041     : AbstractOdeSystemWithAnalyticJacobian(6)
00042 {
00043     mpSystemInfo = OdeSystemInformation<TysonNovak2001OdeSystem>::Instance();
00044 
00045     Init();
00046 
00047     if (stateVariables != std::vector<double>())
00048     {
00049         SetStateVariables(stateVariables);
00050     }
00051 }
00052 
00053 TysonNovak2001OdeSystem::~TysonNovak2001OdeSystem()
00054 {
00055     // Do nothing
00056 }
00057 
00058 void TysonNovak2001OdeSystem::Init()
00059 {
00060     // Initialise model parameter values
00061     mK1 = 0.04;
00062     mK2d = 0.04;
00063     mK2dd = 1.0;
00064     mK2ddd = 1.0;
00065     mCycB_threshold = 0.1;
00066     mK3d = 1.0;
00067     mK3dd = 10.0;
00068     mK4d = 2.0;
00069     mK4 = 35;
00070     mJ3 = 0.04;
00071     mJ4 = 0.04;
00072     mK5d = 0.005;
00073     mK5dd = 0.2;
00074     mK6 = 0.1;
00075     mJ5 = 0.3;
00076     mN = 4u;
00077     mK7 = 1.0;
00078     mK8 = 0.5;
00079     mJ7 = 1e-3;
00080     mJ8 = 1e-3;
00081     mMad = 1.0;
00082     mK9 = 0.1;
00083     mK10 = 0.02;
00084     mK11 = 1.0;
00085     mK12d = 0.2;
00086     mK12dd = 50.0;
00087     mK12ddd = 100.0;
00088     mKeq = 1e3;
00089     mK13 = 1.0;
00090     mK14 = 1.0;
00091     mK15d = 1.5;
00092     mK15dd = 0.05;
00093     mK16d = 1.0;
00094     mK16dd = 3.0;
00095     mJ15 = 0.01;
00096     mJ16 = 0.01;
00097     mMu = 0.01;
00098     mMstar = 10.0;
00099 }
00100 
00101 void TysonNovak2001OdeSystem::EvaluateYDerivatives(double time, const std::vector<double>& rY, std::vector<double>& rDY)
00102 {
00103     double x1 = rY[0];
00104     double x2 = rY[1];
00105     double x3 = rY[2];
00106     double x4 = rY[3];
00107     double x5 = rY[4];
00108     double x6 = rY[5];
00109 
00110     double dx1 = 0.0;
00111     double dx2 = 0.0;
00112     double dx3 = 0.0;
00113     double dx4 = 0.0;
00114     double dx5 = 0.0;
00115     double dx6 = 0.0;
00116 
00117     double temp1 = 0.0;
00118     double temp2 = 0.0;
00119     double temp3 = 0.0;
00120 
00130     dx1 = mK1-(mK2d+mK2dd*x2)*x1;
00131 
00132     // The commented line below models the start transition, no cycling, without Cdc20A
00133 //    temp1 = ((mK3d)*(1.0-x2))/(mJ3+1.0-x2);
00134 
00135     temp1 = ((mK3d+mK3dd*x4)*(1.0-x2))/(mJ3+1.0-x2);
00136     temp2 = (mK4*x6*x1*x2)/(mJ4+x2);
00137     dx2 = temp1-temp2;
00138 
00139     temp1 = mK5dd*(SmallPow(x1*x6/mJ5,mN)/(1+SmallPow(x1*x6/mJ5,mN)));
00140     temp2 = mK6*x3;
00141     dx3 = mK5d + temp1 - temp2;
00142 
00143     temp1 = (mK7*x5*(x3-x4))/(mJ7+x3-x4);
00144     temp2 = (mK8*mMad*x4)/(mJ8+x4);
00145     temp3 = mK6*x4;
00146     dx4 = temp1 - temp2 - temp3;
00147 
00148     dx5 = mK9*x6*x1*(1.0-x5) - mK10*x5;
00149 
00150     dx6 = mMu*x6*(1.0-x6/mMstar);
00151 
00152     // Multiply by 60 beacuase the Tyson and Noval 2001 paper has time in minutes, not hours
00153     rDY[0] = dx1*60.0;
00154     rDY[1] = dx2*60.0;
00155     rDY[2] = dx3*60.0;
00156     rDY[3] = dx4*60.0;
00157     rDY[4] = dx5*60.0;
00158     rDY[5] = dx6*60.0;
00159 }
00160 
00161 void TysonNovak2001OdeSystem::AnalyticJacobian(const std::vector<double>& rSolutionGuess, double** jacobian, double time, double timeStep)
00162 {
00163     timeStep *= 60.0; // to scale Jacobian so in hours not minutes
00164     double x1 = rSolutionGuess[0];
00165     double x2 = rSolutionGuess[1];
00166     double x3 = rSolutionGuess[2];
00167     double x4 = rSolutionGuess[3];
00168     double x5 = rSolutionGuess[4];
00169     double x6 = rSolutionGuess[5];
00170 
00171     // f1
00172     double df1_dx1 = -mK2d - mK2dd*x2;
00173     double df1_dx2 = -mK2dd*x1;
00174 
00175     jacobian[0][0] =  1-timeStep*df1_dx1;
00176     jacobian[0][1] = -timeStep*df1_dx2;
00177 
00178     // f2
00179     double df2_dx1 = -mK4*x6*x2/(mJ4+x2);
00180     double df2_dx2 = -mJ3*(mK3d + mK3dd*x4)/(SmallPow((mJ3 + 1 - x2),2))
00181                      -mJ4*mK4*x6*x1/(SmallPow((mJ4+x2),2));
00182     double df2_dx4 =  mK3dd*(1-x2)/(mJ3+1-x2);
00183     double df2_dx6 = -mK4*x1*x2/(mJ4+x2);
00184 
00185     jacobian[1][0] = -timeStep*df2_dx1;
00186     jacobian[1][1] =  1-timeStep*df2_dx2;
00187     jacobian[1][3] = -timeStep*df2_dx4;
00188     jacobian[1][5] = -timeStep*df2_dx6;
00189 
00190     //f3
00191     double z = x1*x6/mJ5;
00192     double df3_dx1 = (mK5dd*x6/mJ5)*mN*SmallPow(z,mN-1)/(SmallPow((1-SmallPow(z,mN)),2));
00193     double df3_dx3 = -mK6;
00194     double df3_dx6 = (mK5dd*x1/mJ5)*mN*SmallPow(z,mN-1)/(SmallPow((1-SmallPow(z,mN)),2));
00195 
00196     jacobian[2][0] = -timeStep*df3_dx1;
00197     jacobian[2][2] = 1-timeStep*df3_dx3;
00198     jacobian[2][5] = -timeStep*df3_dx6;
00199 
00200     // f4
00201     double df4_dx3 =  mJ7*mK7*x5/(SmallPow(mJ7+x3-x4,2));
00202     double df4_dx4 = -mJ7*mK7*x5/(SmallPow(mJ7+x3-x4,2)) - mK6 - mJ8*mK8*mMad/(SmallPow(mJ8+x4,2));
00203     double df4_dx5 =  mK7*(x3-x4)/(mJ7+x3-x4);
00204 
00205     jacobian[3][2] = -timeStep*df4_dx3;
00206     jacobian[3][3] = 1-timeStep*df4_dx4;
00207     jacobian[3][4] = -timeStep*df4_dx5;
00208 
00209     // f5
00210     double df5_dx1 =  mK9*x6*(1-x5);
00211     double df5_dx5 = -mK10 - mK9*x6*x1;
00212     double df5_dx6 =  mK9*x1*(1-x5);
00213 
00214     jacobian[4][0] = -timeStep*df5_dx1;
00215     jacobian[4][4] = 1-timeStep*df5_dx5;
00216     jacobian[4][5] = -timeStep*df5_dx6;
00217 
00218     // f6
00219     double df6_dx6 = mMu - 2*mMu*x6/mMstar;
00220 
00221     jacobian[5][5] = 1-timeStep*df6_dx6;
00222 }
00223 
00224 bool TysonNovak2001OdeSystem::CalculateStoppingEvent(double time, const std::vector<double>& rY)
00225 {
00226     std::vector<double> dy(rY.size());
00227     EvaluateYDerivatives(time, rY, dy);
00228 
00229     // Only call this a stopping condition if the mass of the cell is over 0.6
00230     // (normally cycles from 0.5-1.0 ish!)
00231     return ( (rY[5] > 0.6 )&& (rY[0] < mCycB_threshold) && dy[0] < 0.0 );
00232 }
00233 
00234 double TysonNovak2001OdeSystem::CalculateRootFunction(double time, const std::vector<double>& rY)
00235 {
00236     std::vector<double> dy(rY.size());
00237     EvaluateYDerivatives(time, rY, dy);
00238 
00239     // Only call this a stopping condition if the mass of the cell is over 0.6
00240     // (normally cycles from 0.5-1.0 ish!)
00241     if (rY[5]<0.6)
00242     {
00243         return 1.0;
00244     }
00245 
00246     if (dy[0] >= 0.0)
00247     {
00248         return 1.0;
00249     }
00250     return rY[0]-mCycB_threshold;
00251 }
00252 
00253 template<>
00254 void OdeSystemInformation<TysonNovak2001OdeSystem>::Initialise()
00255 {
00256     /*
00257      * Initialise state variables.
00258      *
00259      * These initial conditions are the approximate steady state
00260      * solution values while the commented out conditions are taken
00261      * from the Tyson and Novak 2001 paper.
00262      */
00263     this->mVariableNames.push_back("CycB");
00264     this->mVariableUnits.push_back("nM");
00265 //    this->mInitialConditions.push_back(0.1);
00266     this->mInitialConditions.push_back(0.099999999999977);
00267 
00268     this->mVariableNames.push_back("Cdh1");
00269     this->mVariableUnits.push_back("nM");
00270 //    this->mInitialConditions.push_back(9.8770e-01);
00271     this->mInitialConditions.push_back(0.989026454281841);
00272 
00273     this->mVariableNames.push_back("Cdc20T");
00274     this->mVariableUnits.push_back("nM");
00275 //    this->mInitialConditions.push_back(1.5011e+00);
00276     this->mInitialConditions.push_back(1.547942029285891);
00277 
00278     this->mVariableNames.push_back("Cdc20A");
00279     this->mVariableUnits.push_back("nM");
00280 //    this->mInitialConditions.push_back(1.2924e+00);
00281     this->mInitialConditions.push_back(1.421110920135839);
00282 
00283     this->mVariableNames.push_back("IEP");
00284     this->mVariableUnits.push_back("nM");
00285 //    this->mInitialConditions.push_back(6.5405e-01);
00286     this->mInitialConditions.push_back(0.672838844290094);
00287 
00288     this->mVariableNames.push_back("mass");
00289     this->mVariableUnits.push_back("");
00290 //    this->mInitialConditions.push_back(4.7039e-01);
00291     this->mInitialConditions.push_back(0.970831277863956 / 2);
00292 
00293     this->mInitialised = true;
00294 }
00295 
00296 // Serialization for Boost >= 1.36
00297 #include "SerializationExportWrapperForCpp.hpp"
00298 CHASTE_CLASS_EXPORT(TysonNovak2001OdeSystem)