求解病态系统的Rosenbrock算法实现

 

  求解病态系统的Rosenbrock算法实现

            EmilMatthew (EmilMatthew@126.com)       06/07/ 30

[  类别  ]算法实现   

[推荐指数]★★★

[  摘要  ]本文主要介绍了一种求解病态系统较为有效的半稳式Range-Kuta算法Rosenbrock的基本原理及其实现。

[ 关键词 ]半隐式Range-Kuta算法,Rosenbrock算法

 

The Implementation of Rosenbrock Algorithm------

A method for solving stiff system

[Classify] Algorithm Implementation  

[  Level ] ★★★

[Abstract] In this article, I mainly introduce the benchmark idea of a Semi Implicit Range-Kuta algorithm, which named as Rosenbrock algorithm, and also with its implementation. 

[Key Words]Semi Implicit Range-Kuta, Rosenbrock Algorithm

 

                                           

[0引言]

    常微分方程组(Ordinary Differential Equations)的数值解法理论,在工程及数值实现上有着非常重要的应用,其中有一类常微分方程组,其系统呈现病态特性(或称刚性,此类系统常称作stiff system,简介参附录1),对普通的数值求解算法的步长设定要求较高,往往需要设定非常小的步长才能得出满意结果。在一些需要时实计算的领域,如控制系统等,是不允许在求解的时间上有过多耗费的,这就要求使用能在较短时间内就可得出计算结果的数值算法。

 

[1算法介绍]

   由于求解普通常微分方程组的Range-Kuta算法具有求解精度高,适用范围广的特点,因此,针对病态系统的数值算法构造有许多也是基于Range-Kuta算法展开的。计算数学工作者发现,如将Range-Kuta算法表达成隐式的形式(参附录2),并对其进行求解,则可以在较短的步数内求得病态系统的状态变量值。

但是,如果直接对隐式Range-Kuta方程进行求解,将面临着耗时、迭代易发散的不良特性。因此,真正有效的求解病态系统的数值算法,有很大一部分基于对隐式Range-Kuta方程展开的。这里要介绍的Rosenbrock半隐式Range-Kuta算法,既保持了半隐式Range-Kutta公式的A稳定性,又避免了迭代,是对刚性系统进行实时仿真的较为有效的算法。该算法还有另外一个特性,那就是步长可以根据精度要求进行调节(参[1]p557),从而能在极少的步数下就得到指定时刻系统的状态值的数值解,且满足精度要求。但对于时实仿真来说,固定步长的Rosenbrock算法会更合适,因为时实仿真需要得到各个时刻的精确的系统状态值,若采用变步长,则会遗漏不少需要的观察时刻的系统状态值。

Rosenbrock算法并不复杂,它的描述如下:

   求解病态系统的Rosenbrock算法实现_第1张图片

  

[2算法实现]

       这里给出的算例如下:

      

       这是一个导弹偏航通道动力学方程描述,有些细节:如系统的参数,变参数特性等,这里不便于公开,敬请谅解。

 

21Matlab实现的关键部分代码:

%--DATA INITIALIZATIONS--

%--调节以下量以定不同的状态变量的初始

anglePSai=0.8;  %偏航角

anglePSai1=0.2; %偏航角角速度

angleSigma=0;  %道偏角

angleDeta=0;    %舵偏角

angleBeta=0.8;  %滑角

 

aPSaiArr(1)=anglePSai;

aPSai1Arr(1)=anglePSai1;

aSigmaArr(1)=angleSigma;

aDetaArr(1)=angleDeta;

aBetaArr(1)=angleBeta;

 

y(1)=anglePSai;

y(2)=anglePSai1;

y(3)=angleSigma;

y(4)=angleDeta;

 

%--MAIN PART OF REAL TIME SIMU --USING ROSENBOCK ALGORITHM , VARIABLE ARGU USE LINEAR INTERPLOTION

i=1;

timeCount=detaT;

arrIndexCount=1;

 

while timeCount<timeLimit+detaT/2

    

     inb1=b1Arr(arrIndexCount);

     inb2=b2Arr(arrIndexCount);

     inb3=b3Arr(arrIndexCount);

     inc1=c1Arr(arrIndexCount);

     inc2=c2Arr(arrIndexCount);

     inc3=c3Arr(arrIndexCount);

    inF=FArr(arrIndexCount);

     inM=MArr(arrIndexCount);

    

 

     J=[ 0                 1                               0              0;                 

          -inb2           -inb1           inb2           -inb3;

              inc1             0                inc2-inc1     inc3;

C_A0_div_TAO  C_A1_div_TAO         0            C_MINUS_1_div_TAO];

 

     fArgus=J;

    

     %---CAL K1---

     tmpY=y;

    

     f=(fArgus*tmpY')'+[0 inM -inF 0];

 

     k1=h*inv((eye(matrixSize,matrixSize)-h*b1*J))*f';

    

     %---CAL K2---   

     tmpY=y+(beta21*k1)';

    

     f=(fArgus*tmpY')'+[0 inM -inF 0];

    

     k2=h*inv((eye(matrixSize,matrixSize)-h*b2*J))*f';

    

     %---CAL Y Vector---

     y=y+w1*k1'+w2*k2';

    

     anglePSai=y(1);

     anglePSai1=y(2);

     angleSigma=y(3);

     angleDeta=y(4);

    

     aPSaiArr(arrIndexCount+1)=anglePSai;

     aPSai1Arr(arrIndexCount+1)=anglePSai1;

     aSigmaArr(arrIndexCount+1)=angleSigma;

     aDetaArr(arrIndexCount+1)=angleDeta;

     aBetaArr(arrIndexCount+1)=anglePSai-angleSigma;

    

     %--ITERATION CONTROL

     arrIndexCount=arrIndexCount+1;

    timeCount=timeCount+detaT;

end

 

22C语言实现的关键部分代码:

      void SimuStepFrame()

      {

           double tmpVal;

           //USING ROSENBROCK METHOD TO SIMULATION

           tmpVal=(timeCount-t1)/(t2-t1);

          

           C1=(dataArea[gI+1][1]-dataArea[gI][1])*tmpVal+dataArea[gI][1];

           C2=(dataArea[gI+1][2]-dataArea[gI][2])*tmpVal+dataArea[gI][2];

           C3=(dataArea[gI+1][3]-dataArea[gI][3])*tmpVal+dataArea[gI][3];

          

           B1=(dataArea[gI+1][4]-dataArea[gI][4])*tmpVal+dataArea[gI][4];

           B2=(dataArea[gI+1][5]-dataArea[gI][5])*tmpVal+dataArea[gI][5];

           B3=(dataArea[gI+1][6]-dataArea[gI][6])*tmpVal+dataArea[gI][6];

          

           F=(dataArea[gI+1][7]-dataArea[gI][7])*tmpVal+dataArea[gI][7];

            M=(dataArea[gI+1][8]-dataArea[gI][8])*tmpVal+dataArea[gI][8];

     

                                                         Jacobi[0][1]=1;

           Jacobi[1][0]=-B2;Jacobi[1][1]=-B1;Jacobi[1][2]=B2         ;Jacobi[1][3]=-B3;

           Jacobi[2][0]=C1;                                                  Jacobi[2][2]=C2-C1;Jacobi[2][3]=C3;

      /*The value below will not change.

           Jacobi[3][0]=C_A0_div_TAO;Jacobi[3][1]=C_A1_div_TAO;Jacobi[3][3]= C_MINUS_1_div_TAO;

      */

           copyMatrix(Jacobi,fArgus);

           //---CAL K1---

           copy1DArr(y,tmpY);

          

           calF1();            //f=(fArgus*tmpY')'+[0 inM -inF 0];

 

           calK1(b1);         //k1=h*inv((eye(matrixSize,matrixSize)-h*b1*J))*f';

          

           //---CAL K2--- 

           calTmpY();  //   tmpY=y+(beta21*k1)';

                

           calF2();            //f=(fArgus*tmpY')'+[0 inM -inF 0];

 

           calK2(b2);   //k2=h*inv((eye(matrixSize,matrixSize)-h*b2*J))*f';

     

            //---CAL Y Vector---

           CAL_Y_Vector();

          

                 anglePSai=y[0];

                 anglePSai1=y[1];

                 angleSigma=y[2];

                 angleDeta=y[3];

                 angleBeta=anglePSai-angleSigma;

                

           //OUTPUT DATAS

           outputData();          

          

           timeCount+=detaT;

           if(gI<gRow-2)//array bound protection

           {

                 if(timeCount>dataArea[gI+1][0]-detaT/2)

                 {

                      gI++;

                      t1=dataArea[gI][0];

                      t2=dataArea[gI+1][0];    

                 }

           }

      }

 

//矩阵求逆

Void invMatrix(double sourceMatrix[MATRIX_SIZE][MATRIX_SIZE],double targetMatrix[MATRIX_SIZE][MATRIX_SIZE],int size)

{

           double externMatrix[MATRIX_SIZE][MATRIX_SIZE*2];

           int i,j;

           int row,col,minIndex;

           double minVal,tmpVal;

          

           for(i=0;i<size;i++)

                 for(j=0;j<size*2;j++)

                 {

                      if(j<size)

                            externMatrix[i][j]=sourceMatrix[i][j];

                      else

                            externMatrix[i][j]=0;

                 }

 

           for(i=0;i<size;i++)

                 externMatrix[i][i+size]=1;

 

           for(row=0;row<size;row++)

           {

                 minVal=fabs(externMatrix[row][row]);

                 minIndex=row;                    

                 for(col=row+1;col<size;col++)      //find the min row index 

                      if(fabs(externMatrix[col][row])>0&&fabs(externMatrix[col][row])<minVal)

                                  {

                                             minIndex=col;

                                             minVal=externMatrix[col][row];  

                                  }

                

                 if(minIndex!=row)//SWAP ROW(minIndex),ROW(row)

                 {

                            for(i=0;i<size*2;i++)

                            {

                                       tmpVal=externMatrix[minIndex][i];

                                       externMatrix[minIndex][i]=externMatrix[row][i];

                                       externMatrix[row][i]=tmpVal;

                            }         

                 }              

                

                 for(j=0;j<size;j++)

                 {

                       if(j!=row)

                            {

                                  tmpVal=externMatrix[j][row]/externMatrix[row][row];

                                  for(i=0;i<size*2;i++)

                                       externMatrix[j][i]-=tmpVal*externMatrix[row][i];

                            }   

                      else if(externMatrix[row][row]!=1)

                            {

                                       tmpVal=externMatrix[row][row];//--repair data enrupt

                                             for(i=0;i<size*2;i++)

                                                  externMatrix[row][i]/=tmpVal;

                            }

                 }

           }

                                 

           //EUIP TO TARGET MATRIX:

           for(i=0;i<size;i++)

                      for(j=0;j<size;j++)         

                                  targetMatrix[i][j]=externMatrix[i][j+size];

          

}

//其余功能函数详参源码

 

[参考文献与网站]

[1] William H. Press , Saul A. Teukolsky 等著,傅祖芸等译,《C数值算法(第二版)》,电子工业出版社,2004.

[2] 袁兆鼎、费景高、刘德贵,《刚性常微分方程初值问题的数值解法》,北京-科学出版社,1987.

[3] http://www.math.hmc.edu/codee/

 

[附录1]

关于病态系统:

       之所以称某类微分动力系统为病态系统,主要是因为其中的系数不足以满足相应的条件,给数值解法的计算带来了困难。病态系统的基本定义如下:

       对于一个微分方程组S,设其系数矩阵为A(n*n),则可求得其特征值为 

          如有:,则可称系统为病态系统。

 

[附录2]

关于隐式迭代式:

   通常的差分方程(组)的迭代形式为fn+1=a*fn+… …(其中fn为迭代项的列向量,设其共有m)也就是说fn+1项只出现在迭代式的左端,对于隐式迭代式则不然,fn+1项可以出现在迭代式的两端。此时,显然可以把fn+1项移项到左端,但是,求解的方法却从原来的迭代变成了一个对于m维线性方程组的求值问题。如果在微分方程的每个步计算中都需要进行一个m维线性方程组的求解,显然代价是过高的,需要找到更好的方法,这也便是隐式Range-Kuta算法等一系列有效求解刚性问题算法出现的起因了。

 

[源码下载]

http://emilmatthew.51.net/EmilPapers/0628RosenbrockAlgo/code.rar

 

若直接点击无法下载(或浏览),请将下载(或浏览)的超链接粘接至浏览器地( 推荐MYIEGREENBORWSER)址栏后按回车.若不出意外,此时应能下载.

若下载中出现了问题,请参考:

http://blog.csdn.net/emilmatthew/archive/2006/04/08/655612.aspx

 

你可能感兴趣的:(求解病态系统的Rosenbrock算法实现)