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

SIBS.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 "SIBS.H"
00027 #include <OpenFOAM/addToRunTimeSelectionTable.H>
00028 
00029 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00030 
00031 defineTypeNameAndDebug(Foam::SIBS, 0);
00032 
00033 namespace Foam
00034 {
00035     addToRunTimeSelectionTable(ODESolver, SIBS, ODE);
00036 
00037     const label SIBS::nSeq_[iMaxX_] = {2, 6, 10, 14, 22, 34, 50, 70};
00038 
00039     const scalar
00040         SIBS::safe1 = 0.25,
00041         SIBS::safe2 = 0.7,
00042         SIBS::redMax = 1.0e-5,
00043         SIBS::redMin = 0.7,
00044         SIBS::scaleMX = 0.1;
00045 };
00046 
00047 
00048 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00049 
00050 Foam::SIBS::SIBS(const ODE& ode)
00051 :
00052     ODESolver(ode),
00053     a_(iMaxX_, 0.0),
00054     alpha_(kMaxX_, kMaxX_, 0.0),
00055     d_p_(n_, kMaxX_, 0.0),
00056     x_p_(kMaxX_, 0.0),
00057     err_(kMaxX_, 0.0),
00058 
00059     yTemp_(n_, 0.0),
00060     ySeq_(n_, 0.0),
00061     yErr_(n_, 0.0),
00062     dfdx_(n_, 0.0),
00063     dfdy_(n_, n_, 0.0),
00064     first_(1),
00065     epsOld_(-1.0)
00066 {}
00067 
00068 
00069 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00070 
00071 void Foam::SIBS::solve
00072 (
00073     const ODE& ode,
00074     scalar& x,
00075     scalarField& y,
00076     scalarField& dydx,
00077     const scalar eps,
00078     const scalarField& yScale,
00079     const scalar hTry,
00080     scalar& hDid,
00081     scalar& hNext
00082 ) const
00083 {
00084     bool exitflag = false;
00085 
00086     if (eps != epsOld_)
00087     {
00088         hNext = xNew_ = -GREAT;
00089         scalar eps1 = safe1*eps;
00090         a_[0] = nSeq_[0] + 1;
00091 
00092         for (register label k=0; k<kMaxX_; k++)
00093         {
00094             a_[k + 1] = a_[k] + nSeq_[k + 1];
00095         }
00096 
00097         for (register label iq = 1; iq<kMaxX_; iq++)
00098         {
00099             for (register label k=0; k<iq; k++)
00100             {
00101                 alpha_[k][iq] =
00102                     pow(eps1, (a_[k + 1] - a_[iq + 1])
00103                    /((a_[iq + 1] - a_[0] + 1.0)*(2*k + 3)));
00104             }
00105         }
00106 
00107         epsOld_ = eps;
00108         a_[0] += n_;
00109 
00110         for (register label k=0; k<kMaxX_; k++)
00111         {
00112             a_[k + 1] = a_[k] + nSeq_[k + 1];
00113         }
00114 
00115         for (kOpt_ = 1; kOpt_<kMaxX_ - 1; kOpt_++)
00116         {
00117             if (a_[kOpt_ + 1] > a_[kOpt_]*alpha_[kOpt_ - 1][kOpt_])
00118             {
00119                 break;
00120             }
00121         }
00122 
00123         kMax_ = kOpt_;
00124     }
00125 
00126     label k=0;
00127     scalar h = hTry;
00128     yTemp_ = y;
00129 
00130     ode.jacobian(x, y, dfdx_, dfdy_);
00131 
00132     if (x != xNew_ || h != hNext)
00133     {
00134         first_ = 1;
00135         kOpt_ = kMax_;
00136     }
00137 
00138     label km=0;
00139     label reduct=0;
00140     scalar maxErr = SMALL;
00141 
00142     for (;;)
00143     {
00144         scalar red = 1.0;
00145 
00146         for (k=0; k <= kMax_; k++)
00147         {
00148             xNew_ = x + h;
00149 
00150             if (xNew_ == x)
00151             {
00152                 FatalErrorIn("ODES::SIBS")
00153                     << "step size underflow"
00154                     << exit(FatalError);
00155             }
00156 
00157             SIMPR(ode, x, yTemp_, dydx, dfdx_, dfdy_, h, nSeq_[k], ySeq_);
00158             scalar xest = sqr(h/nSeq_[k]);
00159 
00160             polyExtrapolate(k, xest, ySeq_, y, yErr_, x_p_, d_p_);
00161 
00162             if (k != 0)
00163             {
00164                 maxErr = SMALL;
00165                 for (register label i=0; i<n_; i++)
00166                 {
00167                     maxErr = max(maxErr, mag(yErr_[i]/yScale[i]));
00168                 }
00169                 maxErr /= eps;
00170                 km = k - 1;
00171                 err_[km] = pow(maxErr/safe1, 1.0/(2*km + 3));
00172             }
00173 
00174             if (k != 0 && (k >= kOpt_ - 1 || first_))
00175             {
00176                 if (maxErr < 1.0)
00177                 {
00178                     exitflag = true;
00179                     break;
00180                 }
00181 
00182                 if (k == kMax_ || k == kOpt_ + 1)
00183                 {
00184                     red = safe2/err_[km];
00185                     break;
00186                 }
00187                 else if (k == kOpt_ && alpha_[kOpt_ - 1][kOpt_] < err_[km])
00188                 {
00189                     red = 1.0/err_[km];
00190                     break;
00191                 }
00192                 else if (kOpt_ == kMax_ && alpha_[km][kMax_ - 1] < err_[km])
00193                 {
00194                     red = alpha_[km][kMax_ - 1]*safe2/err_[km];
00195                     break;
00196                 }
00197                 else if (alpha_[km][kOpt_] < err_[km])
00198                 {
00199                     red = alpha_[km][kOpt_ - 1]/err_[km];
00200                     break;
00201                 }
00202             }
00203         }
00204 
00205         if (exitflag)
00206         {
00207             break;
00208         }
00209 
00210         red = min(red, redMin);
00211         red = max(red, redMax);
00212         h *= red;
00213         reduct = 1;
00214     }
00215 
00216     x = xNew_;
00217     hDid = h;
00218     first_=0;
00219     scalar wrkmin = GREAT;
00220     scalar scale = 1.0;
00221 
00222     for (register label kk=0; kk<=km; kk++)
00223     {
00224         scalar fact = max(err_[kk], scaleMX);
00225         scalar work = fact*a_[kk + 1];
00226         if (work < wrkmin)
00227         {
00228             scale = fact;
00229             wrkmin = work;
00230             kOpt_ = kk + 1;
00231         }
00232     }
00233 
00234     hNext = h/scale;
00235 
00236     if (kOpt_ >= k && kOpt_ != kMax_ && !reduct)
00237     {
00238         scalar fact = max(scale/alpha_[kOpt_ - 1][kOpt_], scaleMX);
00239         if (a_[kOpt_ + 1]*fact <= wrkmin)
00240         {
00241             hNext = h/fact;
00242             kOpt_++;
00243         }
00244     }
00245 }
00246 
00247 
00248 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines