1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation, either version 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
25 Fourth-order Kaps-Rentrop scheme with adjustive time-step size
26 Numerical Recipes in C, Secn 16.6 page 739-742
27 Alternative reference in Numerical Recipes in C++
29 \*---------------------------------------------------------------------------*/
32 #include "simpleMatrix.H"
33 #include "addToRunTimeSelectionTable.H"
35 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37 defineTypeNameAndDebug(Foam::KRR4, 0);
41 addToRunTimeSelectionTable(ODESolver, KRR4, ODE);
44 KRR4::safety = 0.9, KRR4::grow = 1.5, KRR4::pgrow = -0.25,
45 KRR4::shrink = 0.5, KRR4::pshrink = (-1.0/3.0), KRR4::errcon = 0.1296;
48 KRR4::gamma = 1.0/2.0,
49 KRR4::a21 = 2.0, KRR4::a31 = 48.0/25.0, KRR4::a32 = 6.0/25.0,
50 KRR4::c21 = -8.0, KRR4::c31 = 372.0/25.0, KRR4::c32 = 12.0/5.0,
51 KRR4::c41 = -112.0/125.0, KRR4::c42 = -54.0/125.0, KRR4::c43 = -2.0/5.0,
52 KRR4::b1 = 19.0/9.0, KRR4::b2 = 1.0/2.0, KRR4::b3 = 25.0/108.0,
53 KRR4::b4 = 125.0/108.0,
54 KRR4::e1 = 17.0/54.0, KRR4::e2 = 7.0/36.0, KRR4::e3 = 0.0,
55 KRR4::e4 = 125.0/108.0,
56 KRR4::c1X = 1.0/2.0, KRR4::c2X = -3.0/2.0, KRR4::c3X = 121.0/50.0,
57 KRR4::c4X = 29.0/250.0,
58 KRR4::a2X = 1.0, KRR4::a3X = 3.0/5.0;
62 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
64 Foam::KRR4::KRR4(ODE& ode)
68 dydxTemp_(ode_.nEqns()),
75 dfdy_(ode_.nEqns(), ode_.nEqns()),
76 a_(ode_.nEqns(), ode_.nEqns()),
77 pivotIndices_(ode_.nEqns())
81 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
83 void Foam::KRR4::solve
89 const scalarField& yScale,
98 const label nEqns = ode_.nEqns();
100 ode_.jacobian(xTemp, yTemp_, dfdx_, dfdy_);
104 for (register label jtry=0; jtry<maxtry; jtry++)
106 for (register label i=0; i<nEqns; i++)
108 for (register label j=0; j<nEqns; j++)
110 a_[i][j] = -dfdy_[i][j];
113 a_[i][i] += 1.0/(gamma*h);
116 simpleMatrix<scalar>::LUDecompose(a_, pivotIndices_);
118 for (register label i=0; i<nEqns; i++)
120 g1_[i] = dydxTemp_[i] + h*c1X*dfdx_[i];
123 simpleMatrix<scalar>::LUBacksubstitute(a_, pivotIndices_, g1_);
125 for (register label i=0; i<nEqns; i++)
127 y[i] = yTemp_[i] + a21*g1_[i];
131 ode_.derivatives(x, y, dydx_);
133 for (register label i=0; i<nEqns; i++)
135 g2_[i] = dydx_[i] + h*c2X*dfdx_[i] + c21*g1_[i]/h;
138 simpleMatrix<scalar>::LUBacksubstitute(a_, pivotIndices_, g2_);
140 for (register label i=0; i<nEqns; i++)
142 y[i] = yTemp_[i] + a31*g1_[i] + a32*g2_[i];
146 ode_.derivatives(x, y, dydx_);
148 for (register label i=0; i<nEqns; i++)
150 g3_[i] = dydx[i] + h*c3X*dfdx_[i] + (c31*g1_[i] + c32*g2_[i])/h;
153 simpleMatrix<scalar>::LUBacksubstitute(a_, pivotIndices_, g3_);
155 for (register label i=0; i<nEqns; i++)
157 g4_[i] = dydx_[i] + h*c4X*dfdx_[i]
158 + (c41*g1_[i] + c42*g2_[i] + c43*g3_[i])/h;
161 simpleMatrix<scalar>::LUBacksubstitute(a_, pivotIndices_, g4_);
163 for (register label i=0; i<nEqns; i++)
165 y[i] = yTemp_[i] + b1*g1_[i] + b2*g2_[i] + b3*g3_[i] + b4*g4_[i];
166 yErr_[i] = e1*g1_[i] + e2*g2_[i] + e3*g3_[i] + e4*g4_[i];
173 FatalErrorIn("ODES::KRR4")
174 << "stepsize not significant"
179 for (register label i=0; i<nEqns; i++)
181 maxErr = max(maxErr, mag(yErr_[i]/yScale[i]));
188 hNext = (maxErr > errcon ? safety*h*pow(maxErr, pgrow) : grow*h);
193 hNext = safety*h*pow(maxErr, pshrink);
194 h = (h >= 0.0 ? max(hNext, shrink*h) : min(hNext, shrink*h));
198 FatalErrorIn("ODES::KRR4")
204 // ************************************************************************* //