00001
00002
00004
00005 #include "QualityControlCashKarpMover.h"
00006
00008
00010
00011 const double CQualityControlCashKarpMover::m_scdA[6] = {
00012 0.0, 0.2, 0.3, 0.6, 1.0, 0.875 };
00013
00014 const double CQualityControlCashKarpMover::m_scdB[6][5] = {
00015 { 0.0, 0.0, 0.0, 0.0, 0.0 },
00016 { 1.0/5.0, 0.0, 0.0, 0.0, 0.0 },
00017 { 3.0/40.0, 9.0/40.0, 0.0, 0.0, 0.0 },
00018 { 3.0/10.0, -9.0/10.0, 6.0/5.0, 0.0, 0.0 },
00019 {-11.0/54.0, 5.0/2.0, -70.0/27.0, 35.0/27.0, 0.0 },
00020 { 1631.0/55296.0, 175.0/512.0, 575.0/13824.0, 44275.0/110592.0, 253.0/4096.0} };
00021
00022 const double CQualityControlCashKarpMover::m_scdC[6] = {
00023 37.0/378.0, 0.0, 250.0/621.0, 125.0/594.0, 0.0, 512.0/1771.0 };
00024
00025 const double CQualityControlCashKarpMover::m_scdCStar[6] = {
00026 2825.0/27648.0, 0.0, 18575.0/48384.0, 13525.0/55296.0, 277.0/14336.0, 0.25 };
00027
00028 const double CQualityControlCashKarpMover::m_scdERRCON = 1.89e-04;
00029
00030 const double CQualityControlCashKarpMover::m_scdPGROW = -0.2;
00031
00032 const double CQualityControlCashKarpMover::m_scdPSHRINK = -0.25;
00033
00034 const double CQualityControlCashKarpMover::m_scdSAFETY = 0.9;
00035
00036 const double CQualityControlCashKarpMover::m_scdTINY = 1.0e-30;
00037
00039
00041
00042 CQualityControlCashKarpMover::CQualityControlCashKarpMover(double frequency, double stepSize, double eps)
00043 :CDifferentialEquationMover(frequency,stepSize)
00044 {
00045 m_dLastStep = stepSize;
00046 m_dNextStep = stepSize;
00047 m_dInitialStepSize = stepSize;
00048 m_dEps = eps;
00049 }
00050
00051 CQualityControlCashKarpMover::~CQualityControlCashKarpMover()
00052
00053 {
00054
00055 }
00056
00057
00058 void CQualityControlCashKarpMover::Move(double xInitial, double xFinal, ReactionNetwork *pReactionNetwork)
00059 {
00060 int i;
00061
00062 double xInterval = xFinal-xInitial;
00063
00064 m_pReactionNetwork = pReactionNetwork;
00065
00066 if(this->MoveTimeIsZero(xInterval))
00067 {
00068 if(xInitial > (int) xInitial)
00069 {
00070 }
00071 else
00072 {
00073 m_iCount = (int) xInitial;
00074 m_iCount++;
00075 Notify();
00076 }
00077
00078 return;
00079 }
00080 if(m_dInitialStepSize > xInterval) {m_dInitialStepSize = xInterval;}
00081
00082 m_dTime = xInitial;
00083 double nextTime;
00084
00085 m_iCount = (int) xInitial;
00086 m_iCount++;
00087 nextTime = m_iCount;
00088
00089 m_dStepSize = m_dInitialStepSize;
00090 m_dLastStep = m_dInitialStepSize;
00091 m_dNextStep = m_dInitialStepSize;
00092
00093 int nChem = m_pReactionNetwork->GetNumberOfChemicals();
00094 double *chem = new double[nChem];
00095 double *dChemdt = new double[nChem];
00096 m_pdScale = new double[nChem];
00097 m_pdError = new double[nChem];
00098
00099
00100 for(i = 0; i < nChem; i++)
00101 {
00102 chem[i] = m_pReactionNetwork->GetChemical(i)->GetAmount();
00103 }
00104
00105 while(m_dTime < xFinal)
00106 {
00107
00108 while( m_dTime < __min(xFinal,nextTime) )
00109 {
00110
00111 ComputeDerivatives(chem,dChemdt);
00112
00113
00114
00115 for(i = 0; i < nChem; i++)
00116 {
00117 m_pdScale[i] = fabs(chem[i]) + fabs(m_dStepSize*dChemdt[i]) + m_scdTINY;
00118 }
00119
00120
00121 if( (((m_dTime + m_dNextStep) - nextTime) > 0.0) || (((m_dTime + m_dNextStep) - xFinal) > 0.0) )
00122 {
00123 m_dNextStep = __min(nextTime-m_dTime,xFinal-m_dTime);
00124 }
00125
00126
00127 Stepper(nChem,chem,dChemdt);
00128
00129
00130
00131 for(int i = 0; i < nChem; i++)
00132 {
00133 m_pReactionNetwork->GetChemical(i)->SetAmount(chem[i]);
00134 }
00135
00136
00137 if(m_dLastStep < this->GetMinStepSize()) {this->SetMinStepSize(m_dLastStep);}
00138 if(m_dLastStep > this->GetMaxStepSize()) {this->SetMaxStepSize(m_dLastStep);}
00139 this->IncrementTotalSteps();
00140 }
00141
00142 if(m_dTime == nextTime)
00143 {
00144 m_iCount++;
00145 Notify();
00146 nextTime += 1.0;
00147 }
00148 }
00149
00150 delete [] chem;
00151 delete [] dChemdt;
00152 delete [] m_pdScale;
00153 delete [] m_pdError;
00154 }
00155
00157
00158
00160
00161 void CQualityControlCashKarpMover::Stepper(int nRHS, double *y, double *dydt)
00162 {
00163 int i;
00164 double *yTemp = new double[nRHS];
00165 double maxError;
00166
00167 m_dStepSize = m_dNextStep;
00168
00169 while(1)
00170 {
00171 for(i = 0; i < nRHS; i++)
00172 {
00173 yTemp[i] = y[i];
00174 }
00175
00176
00177 CashKarpStep(nRHS,yTemp,dydt);
00178
00179 maxError = 0.0;
00180 for(i = 0; i < nRHS; i++)
00181 {
00182 maxError = __max(maxError,fabs(m_pdError[i]/m_pdScale[i]));
00183 }
00184 maxError = maxError/m_dEps;
00185
00186
00187 if(maxError <= 1.0) {break;}
00188
00189 double tempStep = m_scdSAFETY*m_dStepSize*pow(maxError,m_scdPSHRINK);
00190
00191 if(m_dStepSize >= 0.0)
00192 {
00193 m_dStepSize = __max(tempStep,0.1*m_dStepSize);
00194 }
00195 else
00196 {
00197 m_dStepSize = __min(tempStep,0.1*m_dStepSize);
00198 }
00199 if((m_dTime + m_dStepSize) == m_dTime)
00200 {
00201
00202 cout << "Stepsize too small in QualityControlCashKarpMover::Stepper()" << endl;
00203 exit(1);
00204 }
00205 }
00206
00207 m_dLastStep = m_dStepSize;
00208 if(maxError > m_scdERRCON)
00209 {
00210 m_dNextStep = m_scdSAFETY*m_dStepSize*pow(maxError,m_scdPGROW);
00211 }
00212 else
00213 {
00214 m_dNextStep = 5.0*m_dStepSize;
00215 }
00216
00217 m_dTime += m_dLastStep;
00218
00219 for(int i = 0; i < nRHS; i++)
00220 {
00221 y[i] = yTemp[i];
00222 }
00223
00224 delete [] yTemp;
00225 }
00226
00228
00229
00230
00231
00233
00234 void CQualityControlCashKarpMover::CashKarpStep(int nRHS, double *y, double *dydt)
00235 {
00236 int i;
00237 double *dy2 = new double[nRHS];
00238 double *dy3 = new double[nRHS];
00239 double *dy4 = new double[nRHS];
00240 double *dy5 = new double[nRHS];
00241 double *dy6 = new double[nRHS];
00242 double *yTemp = new double[nRHS];
00243
00244
00245 for(i = 0; i < nRHS; i++)
00246 {
00247 yTemp[i] = y[i] + m_scdB[1][0]*m_dStepSize*dydt[i];
00248 }
00249 ComputeDerivatives(yTemp,dy2);
00250
00251
00252 for(i = 0; i < nRHS; i++)
00253 {
00254 yTemp[i] = y[i] + m_dStepSize*(m_scdB[2][0]*dydt[i] + m_scdB[2][1]*dy2[i]);
00255 }
00256 ComputeDerivatives(yTemp,dy3);
00257
00258
00259 for(i = 0; i < nRHS; i++)
00260 {
00261 yTemp[i] = y[i] + m_dStepSize*(m_scdB[3][0]*dydt[i] + m_scdB[3][1]*dy2[i] + m_scdB[3][2]*dy3[i]);
00262 }
00263 ComputeDerivatives(yTemp,dy4);
00264
00265
00266 for(i = 0; i < nRHS; i++)
00267 {
00268 yTemp[i] = y[i] + m_dStepSize*(m_scdB[4][0]*dydt[i] + m_scdB[4][1]*dy2[i] + m_scdB[4][2]*dy3[i] + m_scdB[4][3]*dy4[i]);
00269 }
00270 ComputeDerivatives(yTemp,dy5);
00271
00272
00273 for(i = 0; i < nRHS; i++)
00274 {
00275 yTemp[i] = y[i] + m_dStepSize*(m_scdB[5][0]*dydt[i] + m_scdB[5][1]*dy2[i] + m_scdB[5][2]*dy3[i] + m_scdB[5][3]*dy4[i] + m_scdB[5][4]*dy5[i]);
00276 }
00277 ComputeDerivatives(yTemp,dy6);
00278
00279
00280
00281 for(i = 0; i < nRHS; i++)
00282 {
00283 y[i] = y[i] + m_dStepSize*(m_scdC[0]*dydt[i] + m_scdC[2]*dy3[i] + m_scdC[3]*dy4[i] + m_scdC[5]*dy6[i]);
00284
00285 double temp1 = m_dStepSize*(m_scdC[0] - m_scdCStar[0])*dydt[i];
00286 double temp2 = m_dStepSize*(m_scdC[2] - m_scdCStar[2])*dy3[i];
00287 double temp3 = m_dStepSize*(m_scdC[3] - m_scdCStar[3])*dy4[i];
00288 double temp4 = m_dStepSize*(m_scdC[4] - m_scdCStar[4])*dy5[i];
00289 double temp5 = m_dStepSize*(m_scdC[5] - m_scdCStar[5])*dy6[i];
00290 m_pdError[i] = temp1 + temp2 + temp3 + temp4 + temp5;
00291 }
00292
00293
00294 delete [] dy2;
00295 delete [] dy3;
00296 delete [] dy4;
00297 delete [] dy5;
00298 delete [] dy6;
00299 delete [] yTemp;
00300 }