FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

RK.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*---------------------------------------------------------------------------*/
00025 
00026 #include "RK.H"
00027 #include <OpenFOAM/addToRunTimeSelectionTable.H>
00028 
00029 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00030 
00031 defineTypeNameAndDebug(Foam::RK, 0);
00032 
00033 namespace Foam
00034 {
00035     addToRunTimeSelectionTable(ODESolver, RK, ODE);
00036 
00037 const scalar
00038     RK::safety=0.9, RK::pGrow=-0.2, RK::pShrink=-0.25, RK::errCon=1.89e-4;
00039 
00040 const scalar
00041     RK::a2 = 0.2, RK::a3 = 0.3, RK::a4 = 0.6, RK::a5 = 1.0, RK::a6 = 0.875,
00042     RK::b21 = 0.2, RK::b31 = 3.0/40.0, RK::b32 = 9.0/40.0,
00043     RK::b41 = 0.3, RK::b42 = -0.9, RK::b43 = 1.2,
00044     RK::b51 = -11.0/54.0, RK::b52 = 2.5, RK::b53 = -70.0/27.0,
00045     RK::b54 = 35.0/27.0,
00046     RK::b61 = 1631.0/55296.0, RK::b62 = 175.0/512.0, RK::b63 = 575.0/13824.0,
00047     RK::b64 = 44275.0/110592.0, RK::b65 = 253.0/4096.0,
00048     RK::c1 = 37.0/378.0, RK::c3 = 250.0/621.0,
00049     RK::c4 = 125.0/594.0, RK::c6 = 512.0/1771.0,
00050     RK::dc1 = RK::c1 - 2825.0/27648.0, RK::dc3 = RK::c3 - 18575.0/48384.0,
00051     RK::dc4 = RK::c4 - 13525.0/55296.0, RK::dc5 = -277.00/14336.0,
00052     RK::dc6 = RK::c6 - 0.25;
00053 };
00054 
00055 
00056 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00057 
00058 Foam::RK::RK(const ODE& ode)
00059 :
00060     ODESolver(ode),
00061     yTemp_(n_, 0.0),
00062     ak2_(n_, 0.0),
00063     ak3_(n_, 0.0),
00064     ak4_(n_, 0.0),
00065     ak5_(n_, 0.0),
00066     ak6_(n_, 0.0),
00067     yErr_(n_, 0.0),
00068     yTemp2_(n_, 0.0)
00069 {}
00070 
00071 
00072 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00073 
00074 void Foam::RK::solve
00075 (
00076     const ODE& ode,
00077     const scalar x,
00078     const scalarField& y,
00079     const scalarField& dydx,
00080     const scalar h,
00081     scalarField& yout,
00082     scalarField& yerr
00083 ) const
00084 {
00085     forAll(yTemp_, i)
00086     {
00087         yTemp_[i] = y[i] + b21*h*dydx[i];
00088     }
00089 
00090     ode.derivatives(x + a2*h, yTemp_, ak2_);
00091 
00092     forAll(yTemp_, i)
00093     {
00094         yTemp_[i] = y[i] + h*(b31*dydx[i] + b32*ak2_[i]);
00095     }
00096 
00097     ode.derivatives(x + a3*h, yTemp_, ak3_);
00098 
00099     forAll(yTemp_, i)
00100     {
00101         yTemp_[i] = y[i] + h*(b41*dydx[i] + b42*ak2_[i] + b43*ak3_[i]);
00102     }
00103 
00104     ode.derivatives(x + a4*h, yTemp_, ak4_);
00105 
00106     forAll(yTemp_, i)
00107     {
00108         yTemp_[i] = y[i]
00109           + h*(b51*dydx[i] + b52*ak2_[i] + b53*ak3_[i] + b54*ak4_[i]);
00110     }
00111 
00112     ode.derivatives(x + a5*h, yTemp_, ak5_);
00113 
00114     forAll(yTemp_, i)
00115     {
00116         yTemp_[i] = y[i]
00117           + h*
00118             (
00119                 b61*dydx[i] + b62*ak2_[i] + b63*ak3_[i]
00120               + b64*ak4_[i] + b65*ak5_[i]
00121             );
00122     }
00123 
00124     ode.derivatives(x + a6*h, yTemp_, ak6_);
00125 
00126     forAll(yout, i)
00127     {
00128         yout[i] = y[i]
00129           + h*(c1*dydx[i] + c3*ak3_[i] + c4*ak4_[i] + c6*ak6_[i]);
00130     }
00131 
00132     forAll(yerr, i)
00133     {
00134         yerr[i] =
00135             h*
00136             (
00137                 dc1*dydx[i] + dc3*ak3_[i] + dc4*ak4_[i]
00138               + dc5*ak5_[i] + dc6*ak6_[i]
00139             );
00140     }
00141 }
00142 
00143 
00144 void Foam::RK::solve
00145 (
00146     const ODE& ode,
00147     scalar& x,
00148     scalarField& y,
00149     scalarField& dydx,
00150     const scalar eps,
00151     const scalarField& yScale,
00152     const scalar hTry,
00153     scalar& hDid,
00154     scalar& hNext
00155 ) const
00156 {
00157     scalar h = hTry;
00158     scalar maxErr = 0.0;
00159 
00160     for (;;)
00161     {
00162         solve(ode, x, y, dydx, h, yTemp2_, yErr_);
00163 
00164         maxErr = 0.0;
00165         for (register label i=0; i<n_; i++)
00166         {
00167             maxErr = max(maxErr, mag(yErr_[i]/yScale[i]));
00168         }
00169         maxErr /= eps;
00170 
00171         if (maxErr <= 1.0)
00172         {
00173             break;
00174         }
00175 
00176         {
00177             scalar hTemp = safety*h*pow(maxErr, pShrink);
00178             h = (h >= 0.0 ? max(hTemp, 0.1*h) : min(hTemp, 0.1*h));
00179         }
00180 
00181         if (h < VSMALL)
00182         {
00183             FatalErrorIn("RK::solve")
00184                 << "stepsize underflow"
00185                 << exit(FatalError);
00186         }
00187     }
00188 
00189     hDid = h;
00190 
00191     x += h;
00192     y = yTemp2_;
00193 
00194     if (maxErr > errCon)
00195     {
00196         hNext = safety*h*pow(maxErr, pGrow);
00197     }
00198     else
00199     {
00200         hNext = 5.0*h;
00201     }
00202 }
00203 
00204 
00205 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines