Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

QualityControlRungeKuttaMover.cpp

Go to the documentation of this file.
00001 // QualityControlRungeKuttaMover.cpp: implementation of the QualityControlRungeKuttaMover class.
00002 //
00004 
00005 #include "QualityControlRungeKuttaMover.h"
00006 
00007 
00008 const double CQualityControlRungeKuttaMover::m_scdERRCON = 6.0e-4;
00009 
00010 const double CQualityControlRungeKuttaMover::m_scdFCOR = 0.06666;
00011 
00012 const double CQualityControlRungeKuttaMover::m_scdPGROW = -0.2;
00013 
00014 const double CQualityControlRungeKuttaMover::m_scdPSHRINK = -0.25;
00015 
00016 const double CQualityControlRungeKuttaMover::m_scdSAFETY = 0.9;
00017 
00018 const double CQualityControlRungeKuttaMover::m_scdTINY = 1.0e-30;
00019 
00020 
00022 // Construction/Destruction
00024 
00025 CQualityControlRungeKuttaMover::CQualityControlRungeKuttaMover(double frequency, double stepSize, double eps) 
00026 :CRK4Mover(frequency, stepSize)
00027 {
00028         this->m_dEps = eps;
00029         m_dLastStep = stepSize;
00030         m_dNextStep = stepSize;
00031         m_dInitialStepSize = stepSize;  // Each "move" starts with initialStepSize
00032 }
00033 
00034 CQualityControlRungeKuttaMover::~CQualityControlRungeKuttaMover()
00035 {
00036 
00037 }
00038 
00039 void CQualityControlRungeKuttaMover::ResetStepSize()
00040 {
00041         this->m_dInitialStepSize = m_dDefaultStepSize;
00042 }
00043 
00044 double CQualityControlRungeKuttaMover::GetStepSize() const
00045 {
00046         return m_dInitialStepSize;
00047 }
00048 
00049 void CQualityControlRungeKuttaMover::SetStepSize(double newSize)
00050 {
00051         this->m_dInitialStepSize = newSize;
00052 }
00053 
00054 void CQualityControlRungeKuttaMover::Move(double xInitial, double xFinal, ReactionNetwork *pReactionNetwork)
00055 {
00056         // do a couple of checks on the integration interval
00057         double xInterval = xFinal-xInitial;
00058         if(this->MoveTimeIsZero(xInterval)) {return;}
00059         if(m_dInitialStepSize > xInterval) {m_dInitialStepSize = xInterval;}
00060         // set the increment for nextTime appropriately (all QC integrators need this line)
00061         double increment;
00062         if(xInterval < 1.0){increment = xInterval;}
00063         else{increment = 1.0;}
00064 
00065         // set the member pointer to the network pointer passed in
00066         m_pReactionNetwork = pReactionNetwork;
00067         m_dTime = xInitial;
00068         // may be unsafe if xInitial has a fractional part!
00069         m_iCount = (int) xInitial;
00070         
00071         m_dStepSize = m_dLastStep = m_dNextStep = m_dInitialStepSize;
00072         double nextTime = m_dTime;
00073         int nChem = m_pReactionNetwork->GetNumberOfChemicals();
00074         double *chem = new double[nChem];
00075         double *dChemdt = new double[nChem];
00076         m_pdScale = new double[nChem];
00077         double minStep = 0.1*m_dStepSize;
00078 
00079         for (int cNum = 0; cNum < nChem; cNum++)
00080         {
00081                 chem[cNum] = m_pReactionNetwork->GetChemical(cNum)->GetAmount();
00082         }       
00083 
00084         while(m_dTime < xFinal)
00085         {
00086                 while(m_dTime < nextTime)
00087                 {
00088                         ComputeDerivatives(chem,dChemdt);                               
00089                 
00090                         for (int i = 0; i < nChem; i++)
00091                         {
00092                                 double scal1 = fabs(chem[i]) + fabs(dChemdt[i]*m_dNextStep) + m_scdTINY;
00093                                 double scal2 = 1.0;
00094                                 if(scal1 > scal2)
00095                                 {
00096                                         m_pdScale[i] = scal1;
00097                                 }
00098                                 else
00099                                 {
00100                                         m_pdScale[i] = scal2;
00101                                 }
00102                         }
00103                         if( ((m_dTime + m_dNextStep) - nextTime) > 0.0 )        
00104                         {
00105                                 m_dNextStep = nextTime-m_dTime;
00106                         }
00107 
00108                         // take a step
00109                         Stepper(nChem,chem,dChemdt);    
00110 
00111                 }
00112                 // ensure synchrony with chem and network
00113                 for (int cNum = 0; cNum < nChem; cNum++)
00114                 {
00115                         m_pReactionNetwork->GetChemical(cNum)->SetAmount(chem[cNum]);
00116                 }
00117 
00118                 m_iCount++;
00119                 Notify();
00120                 nextTime += increment;
00121         }
00122         
00123         delete [] chem;
00124         delete [] dChemdt;
00125         delete [] m_pdScale;
00126 }
00127 
00129 // Takes one quality-controlled 4th order Runge-Kutta step.  
00130 // The output (new concentrations after the move) are stored in 
00131 // y[] on exit. 
00133 
00134 void CQualityControlRungeKuttaMover::Stepper(int nRHS, double *y, double *dydt)
00135 {
00136         int i;
00137         double maxError;
00138         
00139         double *dydtTemp1 = new double[nRHS];
00140         double *dydtTemp2 = new double[nRHS];
00141         double *yTemp1 = new double[nRHS];
00142         double *yTemp2 = new double[nRHS];
00143 
00144         m_dStepSize = m_dNextStep;
00145 
00146         while(1)
00147         {
00148                 for(i = 0; i < nRHS; i++)
00149                 {
00150                         yTemp1[i] = y[i];
00151                         yTemp2[i] = y[i];
00152                         dydtTemp1[i] = dydt[i];
00153                         dydtTemp2[i] = dydt[i];
00154                 }
00155                 // cut stepSize in half
00156                 m_dStepSize = 0.5*m_dStepSize;
00157                 FourthOrderStep(nRHS,yTemp1,dydtTemp1);
00158                 ComputeDerivatives(yTemp1,dydtTemp1);
00159                 FourthOrderStep(nRHS,yTemp1,dydtTemp1);
00160                 
00161                 // undo halving of stepSize
00162                 m_dStepSize = 2.0*m_dStepSize;
00163 
00164                 if ((m_dTime + m_dStepSize) == m_dTime) 
00165                 {
00166                         // need to throw exception
00167                         cout << "Step size too small in routine RKQC" << endl;
00168                         exit(1);
00169                 }
00170                 
00171                 FourthOrderStep(nRHS,yTemp2,dydtTemp2);
00172                 
00173                 maxError = 0.0;
00174                 for (i = 0; i < nRHS; i++)
00175                 {       
00176                         yTemp2[i] = yTemp1[i] - yTemp2[i];
00177                         double temp = fabs(yTemp2[i]/m_pdScale[i]);
00178                         if(maxError < temp) 
00179                         {
00180                                 maxError = temp;
00181                         }
00182                 }
00183                 maxError = maxError/m_dEps;
00184                 if(maxError <= 1.0)
00185                 {
00186                         m_dLastStep = m_dStepSize;
00187                         if(maxError > m_scdERRCON)
00188                         {
00189                                 m_dNextStep = m_scdSAFETY*m_dStepSize*pow(maxError,m_scdPGROW);
00190                         }
00191                         else
00192                         {
00193                                 m_dNextStep = 4.0*m_dStepSize;
00194                         }
00195                         break;
00196                 }
00197 
00198                 m_dStepSize=m_scdSAFETY*m_dStepSize*pow(maxError,m_scdPSHRINK);
00199         }
00200 
00201         // break out of while loop; step accepted
00202         
00203         m_dTime += m_dLastStep;
00204 
00205         for(int i = 0; i < nRHS; i++)
00206         {
00207                 y[i] = yTemp1[i] + yTemp2[i]*m_scdFCOR;
00208         }
00209         
00210         // free memory
00211 
00212         delete [] yTemp1;
00213         delete [] yTemp2;
00214         delete [] dydtTemp1;
00215         delete [] dydtTemp2;
00216 }
00217 

Generated on Mon Nov 3 09:38:10 2003 by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002