00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "NhsModelWithBackwardSolver.hpp"
00037 #include <iostream>
00038 #include <cmath>
00039 #include "LogFile.hpp"
00040 #include "Exception.hpp"
00041 #include "TimeStepper.hpp"
00042
00043 const double NhsModelWithBackwardSolver::mTolerance = 1e-10;
00044
00045 double NhsModelWithBackwardSolver::ImplicitSolveForQ()
00046 {
00047 mTemporaryStateVariables[2] = (mTemporaryStateVariables[2] + mDt*mA1*mDLambdaDt)/(1 + mAlpha1*mDt);
00048 mTemporaryStateVariables[3] = (mTemporaryStateVariables[3] + mDt*mA2*mDLambdaDt)/(1 + mAlpha2*mDt);
00049 mTemporaryStateVariables[4] = (mTemporaryStateVariables[4] + mDt*mA3*mDLambdaDt)/(1 + mAlpha3*mDt);
00050
00051 return mTemporaryStateVariables[2] + mTemporaryStateVariables[3] + mTemporaryStateVariables[4];
00052 }
00053
00054 void NhsModelWithBackwardSolver::CalculateCaTropAndZDerivatives(double calciumTroponin, double z, double Q,
00055 double& dCaTrop, double& dz)
00056 {
00057
00058 #define COVERAGE_IGNORE
00059 if(calciumTroponin < 0)
00060 {
00061 EXCEPTION("CalciumTrop concentration went negative");
00062 }
00063 if(z<0)
00064 {
00065 EXCEPTION("z went negative");
00066 }
00067 if(z>1)
00068 {
00069 EXCEPTION("z became greater than 1");
00070 }
00071 #undef COVERAGE_IGNORE
00072
00073 double T0 = CalculateT0(z);
00074
00075 double Ta;
00076 if(Q>0)
00077 {
00078 Ta = T0*(1+(2+mA)*Q)/(1+Q);
00079 }
00080 else
00081 {
00082 Ta = T0*(1+mA*Q)/(1-Q);
00083 }
00084
00085 dCaTrop = mKon * mCalciumI * ( mCalciumTroponinMax - calciumTroponin)
00086 - mKrefoff * (1-Ta/(mGamma*mTref)) * calciumTroponin;
00087
00088 double ca_trop_to_ca_trop50_ratio_to_n = pow(calciumTroponin/mCalciumTrop50, mN);
00089
00090 dz = mAlpha0 * ca_trop_to_ca_trop50_ratio_to_n * (1-z)
00091 - mAlphaR1 * z
00092 - mAlphaR2 * pow(z,mNr) / (pow(z,mNr) + pow(mKZ,mNr));
00093 }
00094
00095
00096
00097 void NhsModelWithBackwardSolver::CalculateBackwardEulerResidual(double calciumTroponin, double z, double Q,
00098 double& residualComponent1, double& residualComponent2)
00099 {
00100 double dcatrop;
00101 double dz;
00102 CalculateCaTropAndZDerivatives(calciumTroponin,z,Q,dcatrop,dz);
00103
00104 residualComponent1 = calciumTroponin - mDt*dcatrop - mTemporaryStateVariables[0];
00105 residualComponent2 = z - mDt*dz - mTemporaryStateVariables[1];
00106 }
00107
00108
00109
00110 NhsModelWithBackwardSolver::NhsModelWithBackwardSolver()
00111 {
00112 mTemporaryStateVariables.resize(5);
00113 }
00114
00115
00116
00117 void NhsModelWithBackwardSolver::RunDoNotUpdate(double startTime, double endTime, double timestep)
00118 {
00119 assert(startTime < endTime);
00120
00121 mDt = timestep;
00122
00123 mTemporaryStateVariables = mStateVariables;
00124
00125
00126 TimeStepper stepper(startTime, endTime, timestep);
00127
00128 while ( !stepper.IsTimeAtEnd() )
00129 {
00131
00133 double new_Q = ImplicitSolveForQ();
00134
00136
00138
00139
00140 double catrop_guess = mTemporaryStateVariables[0];
00141 double z_guess = mTemporaryStateVariables[1];
00142 double f1,f2;
00143
00144 CalculateBackwardEulerResidual(catrop_guess, z_guess, new_Q, f1, f2);
00145 double norm_resid = sqrt(f1*f1+f2*f2);
00146
00147
00148
00149 unsigned counter = 0;
00150 while ((norm_resid>mTolerance) && (counter++<15))
00151 {
00152
00153 double j11,j12,j21,j22;
00154 double temp1,temp2;
00155
00156 double h = std::max(fabs(catrop_guess/100),1e-8);
00157 CalculateBackwardEulerResidual(catrop_guess+h, z_guess, new_Q, temp1, temp2);
00158 j11 = (temp1-f1)/h;
00159 j21 = (temp2-f2)/h;
00160
00161 h = std::max(fabs(z_guess/100),1e-8);
00162 CalculateBackwardEulerResidual(catrop_guess, z_guess+h, new_Q, temp1, temp2);
00163 j12 = (temp1-f1)/h;
00164 j22 = (temp2-f2)/h;
00165
00166
00167 double one_over_det = 1.0/(j11*j22-j12*j21);
00168 double u1 = one_over_det*(j22*f1 - j12*f2);
00169 double u2 = one_over_det*(-j21*f1 + j11*f2);
00170
00171 catrop_guess -= u1;
00172 z_guess -= u2;
00173
00174 CalculateBackwardEulerResidual(catrop_guess, z_guess, new_Q, f1, f2);
00175 norm_resid = sqrt(f1*f1+f2*f2);
00176 }
00177 assert(counter<15);
00178
00179 mTemporaryStateVariables[0] = catrop_guess;
00180 mTemporaryStateVariables[1] = z_guess;
00181
00182 stepper.AdvanceOneTimeStep();
00183 }
00184 }
00185
00186 double NhsModelWithBackwardSolver::GetNextActiveTension()
00187 {
00188 double T0 = CalculateT0(mTemporaryStateVariables[1]);
00189 double Q = mTemporaryStateVariables[2]+mTemporaryStateVariables[3]+mTemporaryStateVariables[4];
00190
00191 if(Q>0)
00192 {
00193 return T0*(1+(2+mA)*Q)/(1+Q);
00194 }
00195 else
00196 {
00197 return T0*(1+mA*Q)/(1-Q);
00198 }
00199 }
00200
00201 void NhsModelWithBackwardSolver::RunAndUpdate(double startTime, double endTime, double timestep)
00202 {
00203 RunDoNotUpdate(startTime, endTime, timestep);
00204 UpdateStateVariables();
00205 }
00206