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 #include "KRR4.H"
00027 #include <OpenFOAM/addToRunTimeSelectionTable.H>
00028
00029
00030
00031 defineTypeNameAndDebug(Foam::KRR4, 0);
00032
00033 namespace Foam
00034 {
00035 addToRunTimeSelectionTable(ODESolver, KRR4, ODE);
00036
00037 const scalar
00038 KRR4::safety = 0.9, KRR4::grow = 1.5, KRR4::pgrow = -0.25,
00039 KRR4::shrink = 0.5, KRR4::pshrink = (-1.0/3.0), KRR4::errcon = 0.1296;
00040
00041 const scalar
00042 KRR4::gamma = 1.0/2.0,
00043 KRR4::a21 = 2.0, KRR4::a31 = 48.0/25.0, KRR4::a32 = 6.0/25.0,
00044 KRR4::c21 = -8.0, KRR4::c31 = 372.0/25.0, KRR4::c32 = 12.0/5.0,
00045 KRR4::c41 = -112.0/125.0, KRR4::c42 = -54.0/125.0, KRR4::c43 = -2.0/5.0,
00046 KRR4::b1 = 19.0/9.0, KRR4::b2 = 1.0/2.0, KRR4::b3 = 25.0/108.0,
00047 KRR4::b4 = 125.0/108.0,
00048 KRR4::e1 = 17.0/54.0, KRR4::e2 = 7.0/36.0, KRR4::e3 = 0.0,
00049 KRR4::e4 = 125.0/108.0,
00050 KRR4::c1X = 1.0/2.0, KRR4::c2X = -3.0/2.0, KRR4::c3X = 121.0/50.0,
00051 KRR4::c4X = 29.0/250.0,
00052 KRR4::a2X = 1.0, KRR4::a3X = 3.0/5.0;
00053 };
00054
00055
00056
00057
00058 Foam::KRR4::KRR4(const ODE& ode)
00059 :
00060 ODESolver(ode),
00061 yTemp_(n_, 0.0),
00062 dydxTemp_(n_, 0.0),
00063 g1_(n_, 0.0),
00064 g2_(n_, 0.0),
00065 g3_(n_, 0.0),
00066 g4_(n_, 0.0),
00067 yErr_(n_, 0.0),
00068 dfdx_(n_, 0.0),
00069 dfdy_(n_, n_, 0.0),
00070 a_(n_, n_, 0.0),
00071 pivotIndices_(n_, 0.0)
00072 {}
00073
00074
00075
00076
00077 void Foam::KRR4::solve
00078 (
00079 const ODE& ode,
00080 scalar& x,
00081 scalarField& y,
00082 scalarField& dydx,
00083 const scalar eps,
00084 const scalarField& yScale,
00085 const scalar hTry,
00086 scalar& hDid,
00087 scalar& hNext
00088 ) const
00089 {
00090 scalar xTemp = x;
00091 yTemp_ = y;
00092 dydxTemp_ = dydx;
00093
00094 ode.jacobian(xTemp, yTemp_, dfdx_, dfdy_);
00095
00096 scalar h = hTry;
00097
00098 for (register label jtry=0; jtry<maxtry; jtry++)
00099 {
00100 for (register label i=0; i<n_; i++)
00101 {
00102 for (register label j=0; j<n_; j++)
00103 {
00104 a_[i][j] = -dfdy_[i][j];
00105 }
00106
00107 a_[i][i] += 1.0/(gamma*h);
00108 }
00109
00110 LUDecompose(a_, pivotIndices_);
00111
00112 for (register label i=0; i<n_; i++)
00113 {
00114 g1_[i] = dydxTemp_[i] + h*c1X*dfdx_[i];
00115 }
00116
00117 LUBacksubstitute(a_, pivotIndices_, g1_);
00118
00119 for (register label i=0; i<n_; i++)
00120 {
00121 y[i] = yTemp_[i] + a21*g1_[i];
00122 }
00123
00124 x = xTemp + a2X*h;
00125 ode.derivatives(x, y, dydx_);
00126
00127 for (register label i=0; i<n_; i++)
00128 {
00129 g2_[i] = dydx_[i] + h*c2X*dfdx_[i] + c21*g1_[i]/h;
00130 }
00131
00132 LUBacksubstitute(a_, pivotIndices_, g2_);
00133
00134 for (register label i=0; i<n_; i++)
00135 {
00136 y[i] = yTemp_[i] + a31*g1_[i] + a32*g2_[i];
00137 }
00138
00139 x = xTemp + a3X*h;
00140 ode.derivatives(x, y, dydx_);
00141
00142 for (register label i=0; i<n_; i++)
00143 {
00144 g3_[i] = dydx[i] + h*c3X*dfdx_[i] + (c31*g1_[i] + c32*g2_[i])/h;
00145 }
00146
00147 LUBacksubstitute(a_, pivotIndices_, g3_);
00148
00149 for (register label i=0; i<n_; i++)
00150 {
00151 g4_[i] = dydx_[i] + h*c4X*dfdx_[i]
00152 + (c41*g1_[i] + c42*g2_[i] + c43*g3_[i])/h;
00153 }
00154
00155 LUBacksubstitute(a_, pivotIndices_, g4_);
00156
00157 for (register label i=0; i<n_; i++)
00158 {
00159 y[i] = yTemp_[i] + b1*g1_[i] + b2*g2_[i] + b3*g3_[i] + b4*g4_[i];
00160 yErr_[i] = e1*g1_[i] + e2*g2_[i] + e3*g3_[i] + e4*g4_[i];
00161 }
00162
00163 x = xTemp + h;
00164
00165 if (x == xTemp)
00166 {
00167 FatalErrorIn("ODES::KRR4")
00168 << "stepsize not significant"
00169 << exit(FatalError);
00170 }
00171
00172 scalar maxErr = 0.0;
00173 for (register label i=0; i<n_; i++)
00174 {
00175 maxErr = max(maxErr, mag(yErr_[i]/yScale[i]));
00176 }
00177 maxErr /= eps;
00178
00179 if (maxErr <= 1.0)
00180 {
00181 hDid = h;
00182 hNext = (maxErr > errcon ? safety*h*pow(maxErr, pgrow) : grow*h);
00183 return;
00184 }
00185 else
00186 {
00187 hNext = safety*h*pow(maxErr, pshrink);
00188 h = (h >= 0.0 ? max(hNext, shrink*h) : min(hNext, shrink*h));
00189 }
00190 }
00191
00192 FatalErrorIn("ODES::KRR4")
00193 << "exceeded maxtry"
00194 << exit(FatalError);
00195 }
00196
00197
00198