Chaste  Release::3.4
NhsModelWithBackwardSolver.cpp
1 /*
2 
3 Copyright (c) 2005-2016, University of Oxford.
4 All rights reserved.
5 
6 University of Oxford means the Chancellor, Masters and Scholars of the
7 University of Oxford, having an administrative office at Wellington
8 Square, Oxford OX1 2JD, UK.
9 
10 This file is part of Chaste.
11 
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions are met:
14  * Redistributions of source code must retain the above copyright notice,
15  this list of conditions and the following disclaimer.
16  * Redistributions in binary form must reproduce the above copyright notice,
17  this list of conditions and the following disclaimer in the documentation
18  and/or other materials provided with the distribution.
19  * Neither the name of the University of Oxford nor the names of its
20  contributors may be used to endorse or promote products derived from this
21  software without specific prior written permission.
22 
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 
34 */
35 
36 #include "NhsModelWithBackwardSolver.hpp"
37 #include <iostream>
38 #include <cmath>
39 #include "LogFile.hpp"
40 #include "Exception.hpp"
41 #include "TimeStepper.hpp"
42 
43 const double NhsModelWithBackwardSolver::mTolerance = 1e-10;
44 
46 {
50 
52 }
53 
54 void NhsModelWithBackwardSolver::CalculateCaTropAndZDerivatives(double calciumTroponin, double z, double Q,
55  double& dCaTrop, double& dz)
56 {
57 //As in straight Nhs, we don't cover the exception code
58 #define COVERAGE_IGNORE
59  if(calciumTroponin < 0)
60  {
61  EXCEPTION("CalciumTrop concentration went negative");
62  }
63  if(z<0)
64  {
65  EXCEPTION("z went negative");
66  }
67  if(z>1)
68  {
69  EXCEPTION("z became greater than 1");
70  }
71 #undef COVERAGE_IGNORE
72 
73  double T0 = CalculateT0(z);
74 
75  double Ta;
76  if(Q>0)
77  {
78  Ta = T0*(1+(2+mA)*Q)/(1+Q);
79  }
80  else
81  {
82  Ta = T0*(1+mA*Q)/(1-Q);
83  }
84 
85  dCaTrop = mKon * mCalciumI * ( mCalciumTroponinMax - calciumTroponin)
86  - mKrefoff * (1-Ta/(mGamma*mTref)) * calciumTroponin;
87 
88  double ca_trop_to_ca_trop50_ratio_to_n = pow(calciumTroponin/mCalciumTrop50, mN);
89 
90  dz = mAlpha0 * ca_trop_to_ca_trop50_ratio_to_n * (1-z)
91  - mAlphaR1 * z
92  - mAlphaR2 * pow(z,mNr) / (pow(z,mNr) + pow(mKZ,mNr));
93 }
94 
95 
96 
97 void NhsModelWithBackwardSolver::CalculateBackwardEulerResidual(double calciumTroponin, double z, double Q,
98  double& residualComponent1, double& residualComponent2)
99 {
100  double dcatrop;
101  double dz;
102  CalculateCaTropAndZDerivatives(calciumTroponin,z,Q,dcatrop,dz);
103 
104  residualComponent1 = calciumTroponin - mDt*dcatrop - mTemporaryStateVariables[0];
105  residualComponent2 = z - mDt*dz - mTemporaryStateVariables[1];
106 }
107 
108 
109 
111 {
112  mTemporaryStateVariables.resize(5);
113 }
114 
115 
116 
117 void NhsModelWithBackwardSolver::RunDoNotUpdate(double startTime, double endTime, double timestep)
118 {
119  assert(startTime < endTime);
120 
121  mDt = timestep;
122 
124 
125  // loop in time
126  TimeStepper stepper(startTime, endTime, timestep);
127 
128  while ( !stepper.IsTimeAtEnd() )
129  {
131  // Q1,Q2,Q3 using backward euler can solved straightaway
133  double new_Q = ImplicitSolveForQ();
134 
136  // Solve the 2D nonlinear problem for Backward Euler Ca_trop and z
138 
139  // see what the residual is
140  double catrop_guess = mTemporaryStateVariables[0];
141  double z_guess = mTemporaryStateVariables[1];
142  double f1,f2; // f=[f1,f2]=residual
143 
144  CalculateBackwardEulerResidual(catrop_guess, z_guess, new_Q, f1, f2);
145  double norm_resid = sqrt(f1*f1+f2*f2);
146 
147  // solve using Newton's method, no damping. Stop if num iterations
148  // reaches 15 (very conservative)
149  unsigned counter = 0;
150  while ((norm_resid>mTolerance) && (counter++<15))
151  {
152  // numerically approximate the jacobian J
153  double j11,j12,j21,j22; // J = [j11, j12; j21 j22]
154  double temp1,temp2;
155 
156  double h = std::max(fabs(catrop_guess/100),1e-8);
157  CalculateBackwardEulerResidual(catrop_guess+h, z_guess, new_Q, temp1, temp2);
158  j11 = (temp1-f1)/h;
159  j21 = (temp2-f2)/h;
160 
161  h = std::max(fabs(z_guess/100),1e-8);
162  CalculateBackwardEulerResidual(catrop_guess, z_guess+h, new_Q, temp1, temp2);
163  j12 = (temp1-f1)/h;
164  j22 = (temp2-f2)/h;
165 
166  // compute u = J^{-1} f (exactly, as a 2D problem)
167  double one_over_det = 1.0/(j11*j22-j12*j21);
168  double u1 = one_over_det*(j22*f1 - j12*f2);
169  double u2 = one_over_det*(-j21*f1 + j11*f2);
170 
171  catrop_guess -= u1;
172  z_guess -= u2;
173 
174  CalculateBackwardEulerResidual(catrop_guess, z_guess, new_Q, f1, f2);
175  norm_resid = sqrt(f1*f1+f2*f2);
176  }
177  assert(counter<15); // if this fails, see corresponding code in old NhsModelWithImplicitSolver
178 
179  mTemporaryStateVariables[0] = catrop_guess;
180  mTemporaryStateVariables[1] = z_guess;
181 
182  stepper.AdvanceOneTimeStep();
183  }
184 }
185 
187 {
188  double T0 = CalculateT0(mTemporaryStateVariables[1]);
190 
191  if(Q>0)
192  {
193  return T0*(1+(2+mA)*Q)/(1+Q);
194  }
195  else
196  {
197  return T0*(1+mA*Q)/(1-Q);
198  }
199 }
200 
201 void NhsModelWithBackwardSolver::RunAndUpdate(double startTime, double endTime, double timestep)
202 {
203  RunDoNotUpdate(startTime, endTime, timestep);
205 }
206 
void CalculateBackwardEulerResidual(double calciumTroponin, double z, double Q, double &residualComponent1, double &residualComponent2)
void CalculateCaTropAndZDerivatives(double calciumTroponin, double z, double Q, double &dCaTrop, double &dz)
double CalculateT0(double z)
static const double mTref
#define EXCEPTION(message)
Definition: Exception.hpp:143
static const double mKZ
static const unsigned mNr
void AdvanceOneTimeStep()
static const double mAlphaR1
bool IsTimeAtEnd() const
static const double mAlpha0
static const unsigned mN
static const double mAlpha3
static const double mCalciumTroponinMax
void RunAndUpdate(double startTime, double endTime, double timestep)
static const double mA
void RunDoNotUpdate(double startTime, double endTime, double timestep)
static const double mA2
static const double mA3
static const double mAlpha2
static const double mGamma
static const double mKon
static const double mAlpha1
static const double mAlphaR2
static const double mKrefoff
static const double mA1