Merge branch 'master' of /home/dm4/OpenFOAM/OpenFOAM-dev

This commit is contained in:
andy
2013-11-11 13:05:51 +00:00
39 changed files with 625 additions and 685 deletions

View File

@ -142,7 +142,7 @@ int main(int argc, char *argv[])
scalar dxNext = dxEst;
odeSolver->relTol() = relTol;
odeSolver->solve(ode, x, y, dxNext);
odeSolver->solve(x, y, dxNext);
Info<< scientific << setw(13) << relTol;
Info<< fixed << setw(11) << dxEst;
@ -165,7 +165,7 @@ int main(int argc, char *argv[])
scalar dxEst = 0.5;
odeSolver->relTol() = 1e-4;
odeSolver->solve(ode, x, xEnd, y, dxEst);
odeSolver->solve(x, xEnd, y, dxEst);
Info<< nl << "Analytical: y(2.0) = " << yEnd << endl;
Info << "Numerical: y(2.0) = " << y << ", dxEst = " << dxEst << endl;

View File

@ -8,11 +8,11 @@ ODESolvers/Trapezoid/Trapezoid.C
ODESolvers/RKF45/RKF45.C
ODESolvers/RKCK45/RKCK45.C
ODESolvers/RKDP45/RKDP45.C
ODESolvers/Rosenbrock21/Rosenbrock21.C
ODESolvers/Rosenbrock32/Rosenbrock32.C
ODESolvers/Rosenbrock43/Rosenbrock43.C
ODESolvers/rodas32/rodas32.C
ODESolvers/rodas43/rodas43.C
ODESolvers/Rosenbrock12/Rosenbrock12.C
ODESolvers/Rosenbrock23/Rosenbrock23.C
ODESolvers/Rosenbrock34/Rosenbrock34.C
ODESolvers/rodas23/rodas23.C
ODESolvers/rodas34/rodas34.C
ODESolvers/SIBS/SIBS.C
ODESolvers/SIBS/SIMPR.C
ODESolvers/SIBS/polyExtrapolate.C

View File

@ -49,7 +49,6 @@ Foam::Euler::Euler(const ODESystem& ode, const dictionary& dict)
Foam::scalar Foam::Euler::solve
(
const ODESystem& ode,
const scalar x0,
const scalarField& y0,
const scalarField& dydx0,
@ -75,13 +74,12 @@ Foam::scalar Foam::Euler::solve
void Foam::Euler::solve
(
const ODESystem& odes,
scalar& x,
scalarField& y,
scalar& dxTry
) const
{
adaptiveSolver::solve(odes, x, y, dxTry);
adaptiveSolver::solve(odes_, x, y, dxTry);
}

View File

@ -84,7 +84,6 @@ public:
//- Solve a single step dx and return the error
scalar solve
(
const ODESystem& ode,
const scalar x0,
const scalarField& y0,
const scalarField& dydx0,
@ -95,7 +94,6 @@ public:
//- Solve the ODE system and the update the state
void solve
(
const ODESystem& ode,
scalar& x,
scalarField& y,
scalar& dxTry

View File

@ -54,7 +54,6 @@ Foam::EulerSI::EulerSI(const ODESystem& ode, const dictionary& dict)
Foam::scalar Foam::EulerSI::solve
(
const ODESystem& ode,
const scalar x0,
const scalarField& y0,
const scalarField& dydx0,
@ -62,7 +61,7 @@ Foam::scalar Foam::EulerSI::solve
scalarField& y
) const
{
ode.jacobian(x0, y0, dfdx_, dfdy_);
odes_.jacobian(x0, y0, dfdx_, dfdy_);
for (register label i=0; i<n_; i++)
{
@ -95,13 +94,12 @@ Foam::scalar Foam::EulerSI::solve
void Foam::EulerSI::solve
(
const ODESystem& odes,
scalar& x,
scalarField& y,
scalar& dxTry
) const
{
adaptiveSolver::solve(odes, x, y, dxTry);
adaptiveSolver::solve(odes_, x, y, dxTry);
}

View File

@ -91,7 +91,6 @@ public:
//- Solve a single step dx and return the error
scalar solve
(
const ODESystem& ode,
const scalar x0,
const scalarField& y0,
const scalarField& dydx0,
@ -102,7 +101,6 @@ public:
//- Solve the ODE system and the update the state
void solve
(
const ODESystem& ode,
scalar& x,
scalarField& y,
scalar& dxTry

View File

@ -38,6 +38,7 @@ namespace Foam
Foam::ODESolver::ODESolver(const ODESystem& ode, const dictionary& dict)
:
odes_(ode),
n_(ode.nEqns()),
absTol_(n_, dict.lookupOrDefault<scalar>("absTol", SMALL)),
relTol_(n_, dict.lookupOrDefault<scalar>("relTol", 1e-4)),
@ -52,6 +53,7 @@ Foam::ODESolver::ODESolver
const scalarField& relTol
)
:
odes_(ode),
n_(ode.nEqns()),
absTol_(absTol),
relTol_(relTol),
@ -82,48 +84,70 @@ Foam::scalar Foam::ODESolver::normalizeError
void Foam::ODESolver::solve
(
const ODESystem& ode,
scalar& x,
scalarField& y,
stepState& step
) const
{
solve(x, y, step.dxTry);
}
void Foam::ODESolver::solve
(
const scalar xStart,
const scalar xEnd,
scalarField& y,
scalar& dxEst
scalar& dxTry
) const
{
stepState step(dxTry);
scalar x = xStart;
bool truncated = false;
for (label nStep=0; nStep<maxSteps_; nStep++)
{
// Store previous iteration dxEst
scalar dxEst0 = dxEst;
// Store previous iteration dxTry
scalar dxTry0 = step.dxTry;
// Check if this is a truncated step and set dxEst to integrate to xEnd
if ((x + dxEst - xEnd)*(x + dxEst - xStart) > 0)
step.reject = false;
// Check if this is a truncated step and set dxTry to integrate to xEnd
if ((x + step.dxTry - xEnd)*(x + step.dxTry - xStart) > 0)
{
truncated = true;
dxEst = xEnd - x;
step.last = true;
step.dxTry = xEnd - x;
}
// Integrate as far as possible up to dxEst
solve(ode, x, y, dxEst);
// Integrate as far as possible up to step.dxTry
solve(x, y, step);
// Check if reached xEnd
if ((x - xEnd)*(xEnd - xStart) >= 0)
{
if (nStep > 0 && truncated)
if (nStep > 0 && step.last)
{
dxEst = dxEst0;
step.dxTry = dxTry0;
}
dxTry = step.dxTry;
return;
}
step.first = false;
// If the step.dxTry was reject set step.prevReject
if (step.reject)
{
step.prevReject = true;
}
}
FatalErrorIn
(
"ODESolver::solve"
"(const ODESystem& ode, const scalar xStart, const scalar xEnd,"
"scalarField& y, scalar& dxEst) const"
"(const scalar xStart, const scalar xEnd,"
"scalarField& y, scalar& dxTry) const"
) << "Integration steps greater than maximum " << maxSteps_
<< exit(FatalError);
}

View File

@ -55,6 +55,9 @@ protected:
// Protected data
//- Reference to ODESystem
const ODESystem& odes_;
//- Size of the ODESystem
label n_;
@ -90,6 +93,30 @@ public:
//- Runtime type information
TypeName("ODESolver");
class stepState
{
public:
const bool forward;
scalar dxTry;
scalar dxDid;
bool first;
bool last;
bool reject;
bool prevReject;
stepState(const scalar dx)
:
forward(dx > 0 ? true : false),
dxTry(dx),
dxDid(0),
first(true),
last(false),
reject(false),
prevReject(false)
{}
};
// Declare run-time constructor selection table
@ -150,17 +177,31 @@ public:
// Update the state and return an estimate for the next step in dxTry
virtual void solve
(
const ODESystem& ode,
scalar& x,
scalarField& y,
scalar& dxTry
) const = 0;
) const //= 0;
{
stepState step(dxTry);
solve(x, y, step);
dxTry = step.dxTry;
}
//- Solve the ODE system as far as possible upto dxTry
// adjusting the step as necessary to provide a solution within
// the specified tolerance.
// Update the state and return an estimate for the next step in dxTry
virtual void solve
(
scalar& x,
scalarField& y,
stepState& step
) const;
//- Solve the ODE system from xStart to xEnd, update the state
// and return an estimate for the next step in dxTry
virtual void solve
(
const ODESystem& ode,
const scalar xStart,
const scalar xEnd,
scalarField& y,

View File

@ -89,7 +89,6 @@ Foam::RKCK45::RKCK45(const ODESystem& ode, const dictionary& dict)
Foam::scalar Foam::RKCK45::solve
(
const ODESystem& odes,
const scalar x0,
const scalarField& y0,
const scalarField& dydx0,
@ -102,21 +101,21 @@ Foam::scalar Foam::RKCK45::solve
yTemp_[i] = y0[i] + a21*dx*dydx0[i];
}
odes.derivatives(x0 + c2*dx, yTemp_, k2_);
odes_.derivatives(x0 + c2*dx, yTemp_, k2_);
forAll(yTemp_, i)
{
yTemp_[i] = y0[i] + dx*(a31*dydx0[i] + a32*k2_[i]);
}
odes.derivatives(x0 + c3*dx, yTemp_, k3_);
odes_.derivatives(x0 + c3*dx, yTemp_, k3_);
forAll(yTemp_, i)
{
yTemp_[i] = y0[i] + dx*(a41*dydx0[i] + a42*k2_[i] + a43*k3_[i]);
}
odes.derivatives(x0 + c4*dx, yTemp_, k4_);
odes_.derivatives(x0 + c4*dx, yTemp_, k4_);
forAll(yTemp_, i)
{
@ -124,7 +123,7 @@ Foam::scalar Foam::RKCK45::solve
+ dx*(a51*dydx0[i] + a52*k2_[i] + a53*k3_[i] + a54*k4_[i]);
}
odes.derivatives(x0 + c5*dx, yTemp_, k5_);
odes_.derivatives(x0 + c5*dx, yTemp_, k5_);
forAll(yTemp_, i)
{
@ -133,7 +132,7 @@ Foam::scalar Foam::RKCK45::solve
*(a61*dydx0[i] + a62*k2_[i] + a63*k3_[i] + a64*k4_[i] + a65*k5_[i]);
}
odes.derivatives(x0 + c6*dx, yTemp_, k6_);
odes_.derivatives(x0 + c6*dx, yTemp_, k6_);
forAll(y, i)
{
@ -154,13 +153,12 @@ Foam::scalar Foam::RKCK45::solve
void Foam::RKCK45::solve
(
const ODESystem& odes,
scalar& x,
scalarField& y,
scalar& dxTry
) const
{
adaptiveSolver::solve(odes, x, y, dxTry);
adaptiveSolver::solve(odes_, x, y, dxTry);
}

View File

@ -34,10 +34,7 @@ Description
Cash, J.R.,
Karp, A.H.
ACM Transactions on Mathematical Software, vol. 16, 1990, pp. 201222.
\endverbatim
Based on code from:
\verbatim
"Solving Ordinary Differential Equations I: Nonstiff Problems,
second edition",
Hairer, E.,
@ -110,7 +107,6 @@ public:
//- Solve a single step dx and return the error
scalar solve
(
const ODESystem& ode,
const scalar x0,
const scalarField& y0,
const scalarField& dydx0,
@ -121,7 +117,6 @@ public:
//- Solve the ODE system and the update the state
void solve
(
const ODESystem& ode,
scalar& x,
scalarField& y,
scalar& dxTry

View File

@ -94,7 +94,6 @@ Foam::RKDP45::RKDP45(const ODESystem& ode, const dictionary& dict)
Foam::scalar Foam::RKDP45::solve
(
const ODESystem& odes,
const scalar x0,
const scalarField& y0,
const scalarField& dydx0,
@ -107,21 +106,21 @@ Foam::scalar Foam::RKDP45::solve
yTemp_[i] = y0[i] + a21*dx*dydx0[i];
}
odes.derivatives(x0 + c2*dx, yTemp_, k2_);
odes_.derivatives(x0 + c2*dx, yTemp_, k2_);
forAll(yTemp_, i)
{
yTemp_[i] = y0[i] + dx*(a31*dydx0[i] + a32*k2_[i]);
}
odes.derivatives(x0 + c3*dx, yTemp_, k3_);
odes_.derivatives(x0 + c3*dx, yTemp_, k3_);
forAll(yTemp_, i)
{
yTemp_[i] = y0[i] + dx*(a41*dydx0[i] + a42*k2_[i] + a43*k3_[i]);
}
odes.derivatives(x0 + c4*dx, yTemp_, k4_);
odes_.derivatives(x0 + c4*dx, yTemp_, k4_);
forAll(yTemp_, i)
{
@ -129,7 +128,7 @@ Foam::scalar Foam::RKDP45::solve
+ dx*(a51*dydx0[i] + a52*k2_[i] + a53*k3_[i] + a54*k4_[i]);
}
odes.derivatives(x0 + c5*dx, yTemp_, k5_);
odes_.derivatives(x0 + c5*dx, yTemp_, k5_);
forAll(yTemp_, i)
{
@ -138,7 +137,7 @@ Foam::scalar Foam::RKDP45::solve
*(a61*dydx0[i] + a62*k2_[i] + a63*k3_[i] + a64*k4_[i] + a65*k5_[i]);
}
odes.derivatives(x0 + dx, yTemp_, k6_);
odes_.derivatives(x0 + dx, yTemp_, k6_);
forAll(y, i)
{
@ -147,7 +146,7 @@ Foam::scalar Foam::RKDP45::solve
}
// Reuse k2_ for the derivative of the new state
odes.derivatives(x0 + dx, y, k2_);
odes_.derivatives(x0 + dx, y, k2_);
forAll(err_, i)
{
@ -163,13 +162,12 @@ Foam::scalar Foam::RKDP45::solve
void Foam::RKDP45::solve
(
const ODESystem& odes,
scalar& x,
scalarField& y,
scalar& dxTry
) const
{
adaptiveSolver::solve(odes, x, y, dxTry);
adaptiveSolver::solve(odes_, x, y, dxTry);
}

View File

@ -34,10 +34,7 @@ Description
Prince, P. J.,
Journal of Computational and Applied Mathematics,
6 (1), 1980: pp. 19-26.
\endverbatim
Based on code from:
\verbatim
"Solving Ordinary Differential Equations I: Nonstiff Problems,
second edition",
Hairer, E.,
@ -114,7 +111,6 @@ public:
//- Solve a single step dx and return the error
scalar solve
(
const ODESystem& ode,
const scalar x0,
const scalarField& y0,
const scalarField& dydx0,
@ -125,7 +121,6 @@ public:
//- Solve the ODE system and the update the state
void solve
(
const ODESystem& ode,
scalar& x,
scalarField& y,
scalar& dxTry

View File

@ -90,7 +90,6 @@ Foam::RKF45::RKF45(const ODESystem& ode, const dictionary& dict)
Foam::scalar Foam::RKF45::solve
(
const ODESystem& odes,
const scalar x0,
const scalarField& y0,
const scalarField& dydx0,
@ -103,21 +102,21 @@ Foam::scalar Foam::RKF45::solve
yTemp_[i] = y0[i] + a21*dx*dydx0[i];
}
odes.derivatives(x0 + c2*dx, yTemp_, k2_);
odes_.derivatives(x0 + c2*dx, yTemp_, k2_);
forAll(yTemp_, i)
{
yTemp_[i] = y0[i] + dx*(a31*dydx0[i] + a32*k2_[i]);
}
odes.derivatives(x0 + c3*dx, yTemp_, k3_);
odes_.derivatives(x0 + c3*dx, yTemp_, k3_);
forAll(yTemp_, i)
{
yTemp_[i] = y0[i] + dx*(a41*dydx0[i] + a42*k2_[i] + a43*k3_[i]);
}
odes.derivatives(x0 + c4*dx, yTemp_, k4_);
odes_.derivatives(x0 + c4*dx, yTemp_, k4_);
forAll(yTemp_, i)
{
@ -125,7 +124,7 @@ Foam::scalar Foam::RKF45::solve
+ dx*(a51*dydx0[i] + a52*k2_[i] + a53*k3_[i] + a54*k4_[i]);
}
odes.derivatives(x0 + c5*dx, yTemp_, k5_);
odes_.derivatives(x0 + c5*dx, yTemp_, k5_);
forAll(yTemp_, i)
{
@ -134,7 +133,7 @@ Foam::scalar Foam::RKF45::solve
*(a61*dydx0[i] + a62*k2_[i] + a63*k3_[i] + a64*k4_[i] + a65*k5_[i]);
}
odes.derivatives(x0 + c6*dx, yTemp_, k6_);
odes_.derivatives(x0 + c6*dx, yTemp_, k6_);
// Calculate the 5th-order solution
forAll(y, i)
@ -159,13 +158,12 @@ Foam::scalar Foam::RKF45::solve
void Foam::RKF45::solve
(
const ODESystem& odes,
scalar& x,
scalarField& y,
scalar& dxTry
) const
{
adaptiveSolver::solve(odes, x, y, dxTry);
adaptiveSolver::solve(odes_, x, y, dxTry);
}

View File

@ -34,8 +34,6 @@ Description
Fehlberg, E.,
NASA Technical Report 315, 1969.
Based on code from:
\verbatim
"Solving Ordinary Differential Equations I: Nonstiff Problems,
second edition",
Hairer, E.,
@ -48,31 +46,6 @@ Description
and allows to perform an adapdive step-size control using these two order
without the need of re-evaluation.
\f{align}{
k_1 &= h f(t_k, y_k) \\
k_2 &= h f(t_k + \frac{1}{4}h, y_k + \frac{1}{4}k_1) \\
k_3 &= h f(t_k + \frac{3}{8}h, y_k + \frac{3}{32}k_1 + \frac{9}{32}k_2) \\
k_4 &= h f(t_k + \frac{12}{13}h, y_k + \frac{1932}{2197}k_1
\frac{7200}{2197}k_2 + \frac{7296}{2197}k_3) - \\
k_5 &= h f(t_k + h, y_k + \frac{439}{216}k_1 - 8k_2 + \frac{3680}{513}k_3 -
\frac{845}{4104}k_4) \\
k_6 &= h f(t_k + \frac{1}{2}h, y_k - \frac{8}{27}k_1 + 2k_2 -
\frac{3544}{2565}k_3 + \frac{1859}{4104}k_4 - \frac{11}{40}k_5) \\
\f}
Which yields the following update-steps for the 4th and 5th order:
\f{align}{
\Delta_4 &= \frac{25}{216}k_1 + \frac{1408}{2565}k_3 +
\frac{2197}{4101}k_4 - \frac{1}{5}k_5 \\
\Delta_5 &= \frac{16}{135}k_1 + \frac{6656}{12825}k_3 +
\frac{9}{50}k_5 + \frac{2}{55}k_6
\f}
The difference between the 5th and 4th order (\f$\epsilon = \left|\Delta_5
- \Delta_4\right|\f$) can be used to determine if the stepsize \f$h\f$ needs
to be adjusted.
SourceFiles
RKF45.C
@ -138,7 +111,6 @@ public:
//- Solve a single step dx and return the error
scalar solve
(
const ODESystem& ode,
const scalar x0,
const scalarField& y0,
const scalarField& dydx0,
@ -149,7 +121,6 @@ public:
//- Solve the ODE system and the update the state
void solve
(
const ODESystem& ode,
scalar& x,
scalarField& y,
scalar& dxTry

View File

@ -23,33 +23,33 @@ License
\*---------------------------------------------------------------------------*/
#include "Rosenbrock21.H"
#include "Rosenbrock12.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(Rosenbrock21, 0);
addToRunTimeSelectionTable(ODESolver, Rosenbrock21, dictionary);
defineTypeNameAndDebug(Rosenbrock12, 0);
addToRunTimeSelectionTable(ODESolver, Rosenbrock12, dictionary);
const scalar
Rosenbrock21::gamma = 1 + 1.0/std::sqrt(2.0),
Rosenbrock21::a21 = 1.0/gamma,
Rosenbrock21::c2 = 1.0,
Rosenbrock21::c21 = -2.0/gamma,
Rosenbrock21::b1 = (3.0/2.0)/gamma,
Rosenbrock21::b2 = (1.0/2.0)/gamma,
Rosenbrock21::e1 = b1 - 1.0/gamma,
Rosenbrock21::e2 = b2,
Rosenbrock21::d1 = gamma,
Rosenbrock21::d2 = -gamma;
Rosenbrock12::gamma = 1 + 1.0/std::sqrt(2.0),
Rosenbrock12::a21 = 1.0/gamma,
Rosenbrock12::c2 = 1.0,
Rosenbrock12::c21 = -2.0/gamma,
Rosenbrock12::b1 = (3.0/2.0)/gamma,
Rosenbrock12::b2 = (1.0/2.0)/gamma,
Rosenbrock12::e1 = b1 - 1.0/gamma,
Rosenbrock12::e2 = b2,
Rosenbrock12::d1 = gamma,
Rosenbrock12::d2 = -gamma;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::Rosenbrock21::Rosenbrock21(const ODESystem& ode, const dictionary& dict)
Foam::Rosenbrock12::Rosenbrock12(const ODESystem& ode, const dictionary& dict)
:
ODESolver(ode, dict),
adaptiveSolver(ode, dict),
@ -66,9 +66,8 @@ Foam::Rosenbrock21::Rosenbrock21(const ODESystem& ode, const dictionary& dict)
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::scalar Foam::Rosenbrock21::solve
Foam::scalar Foam::Rosenbrock12::solve
(
const ODESystem& ode,
const scalar x0,
const scalarField& y0,
const scalarField& dydx0,
@ -76,7 +75,7 @@ Foam::scalar Foam::Rosenbrock21::solve
scalarField& y
) const
{
ode.jacobian(x0, y0, dfdx_, dfdy_);
odes_.jacobian(x0, y0, dfdx_, dfdy_);
for (register label i=0; i<n_; i++)
{
@ -104,7 +103,7 @@ Foam::scalar Foam::Rosenbrock21::solve
y[i] = y0[i] + a21*k1_[i];
}
ode.derivatives(x0 + c2*dx, y, dydx_);
odes_.derivatives(x0 + c2*dx, y, dydx_);
forAll(k2_, i)
{
@ -124,15 +123,14 @@ Foam::scalar Foam::Rosenbrock21::solve
}
void Foam::Rosenbrock21::solve
void Foam::Rosenbrock12::solve
(
const ODESystem& odes,
scalar& x,
scalarField& y,
scalar& dxTry
) const
{
adaptiveSolver::solve(odes, x, y, dxTry);
adaptiveSolver::solve(odes_, x, y, dxTry);
}

View File

@ -22,7 +22,7 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::Rosenbrock21
Foam::Rosenbrock12
Description
L-stable embedded Rosenbrock ODE solver of order (1)2.
@ -39,12 +39,12 @@ Description
\endverbatim
SourceFiles
Rosenbrock21.C
Rosenbrock12.C
\*---------------------------------------------------------------------------*/
#ifndef Rosenbrock21_H
#define Rosenbrock21_H
#ifndef Rosenbrock12_H
#define Rosenbrock12_H
#include "ODESolver.H"
#include "adaptiveSolver.H"
@ -55,10 +55,10 @@ namespace Foam
{
/*---------------------------------------------------------------------------*\
Class Rosenbrock21 Declaration
Class Rosenbrock12 Declaration
\*---------------------------------------------------------------------------*/
class Rosenbrock21
class Rosenbrock12
:
public ODESolver,
public adaptiveSolver
@ -87,13 +87,13 @@ class Rosenbrock21
public:
//- Runtime type information
TypeName("Rosenbrock21");
TypeName("Rosenbrock12");
// Constructors
//- Construct from ODE
Rosenbrock21(const ODESystem& ode, const dictionary& dict);
Rosenbrock12(const ODESystem& ode, const dictionary& dict);
// Member Functions
@ -101,7 +101,6 @@ public:
//- Solve a single step dx and return the error
scalar solve
(
const ODESystem& ode,
const scalar x0,
const scalarField& y0,
const scalarField& dydx0,
@ -112,7 +111,6 @@ public:
//- Solve the ODE system and the update the state
void solve
(
const ODESystem& ode,
scalar& x,
scalarField& y,
scalar& dxTry

View File

@ -23,45 +23,45 @@ License
\*---------------------------------------------------------------------------*/
#include "Rosenbrock32.H"
#include "Rosenbrock23.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(Rosenbrock32, 0);
addToRunTimeSelectionTable(ODESolver, Rosenbrock32, dictionary);
defineTypeNameAndDebug(Rosenbrock23, 0);
addToRunTimeSelectionTable(ODESolver, Rosenbrock23, dictionary);
const scalar
Rosenbrock32::a21 = 1,
Rosenbrock32::a31 = 1,
Rosenbrock32::a32 = 0,
Rosenbrock23::a21 = 1,
Rosenbrock23::a31 = 1,
Rosenbrock23::a32 = 0,
Rosenbrock32::c21 = -1.0156171083877702091975600115545,
Rosenbrock32::c31 = 4.0759956452537699824805835358067,
Rosenbrock32::c32 = 9.2076794298330791242156818474003,
Rosenbrock23::c21 = -1.0156171083877702091975600115545,
Rosenbrock23::c31 = 4.0759956452537699824805835358067,
Rosenbrock23::c32 = 9.2076794298330791242156818474003,
Rosenbrock32::b1 = 1,
Rosenbrock32::b2 = 6.1697947043828245592553615689730,
Rosenbrock32::b3 = -0.4277225654321857332623837380651,
Rosenbrock23::b1 = 1,
Rosenbrock23::b2 = 6.1697947043828245592553615689730,
Rosenbrock23::b3 = -0.4277225654321857332623837380651,
Rosenbrock32::e1 = 0.5,
Rosenbrock32::e2 = -2.9079558716805469821718236208017,
Rosenbrock32::e3 = 0.2235406989781156962736090927619,
Rosenbrock23::e1 = 0.5,
Rosenbrock23::e2 = -2.9079558716805469821718236208017,
Rosenbrock23::e3 = 0.2235406989781156962736090927619,
Rosenbrock32::gamma = 0.43586652150845899941601945119356,
Rosenbrock32::c2 = 0.43586652150845899941601945119356,
Rosenbrock23::gamma = 0.43586652150845899941601945119356,
Rosenbrock23::c2 = 0.43586652150845899941601945119356,
Rosenbrock32::d1 = 0.43586652150845899941601945119356,
Rosenbrock32::d2 = 0.24291996454816804366592249683314,
Rosenbrock32::d3 = 2.1851380027664058511513169485832;
Rosenbrock23::d1 = 0.43586652150845899941601945119356,
Rosenbrock23::d2 = 0.24291996454816804366592249683314,
Rosenbrock23::d3 = 2.1851380027664058511513169485832;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::Rosenbrock32::Rosenbrock32(const ODESystem& ode, const dictionary& dict)
Foam::Rosenbrock23::Rosenbrock23(const ODESystem& ode, const dictionary& dict)
:
ODESolver(ode, dict),
adaptiveSolver(ode, dict),
@ -79,9 +79,8 @@ Foam::Rosenbrock32::Rosenbrock32(const ODESystem& ode, const dictionary& dict)
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::scalar Foam::Rosenbrock32::solve
Foam::scalar Foam::Rosenbrock23::solve
(
const ODESystem& ode,
const scalar x0,
const scalarField& y0,
const scalarField& dydx0,
@ -89,7 +88,7 @@ Foam::scalar Foam::Rosenbrock32::solve
scalarField& y
) const
{
ode.jacobian(x0, y0, dfdx_, dfdy_);
odes_.jacobian(x0, y0, dfdx_, dfdy_);
for (register label i=0; i<n_; i++)
{
@ -117,7 +116,7 @@ Foam::scalar Foam::Rosenbrock32::solve
y[i] = y0[i] + a21*k1_[i];
}
ode.derivatives(x0 + c2*dx, y, dydx_);
odes_.derivatives(x0 + c2*dx, y, dydx_);
forAll(k2_, i)
{
@ -146,15 +145,14 @@ Foam::scalar Foam::Rosenbrock32::solve
}
void Foam::Rosenbrock32::solve
void Foam::Rosenbrock23::solve
(
const ODESystem& odes,
scalar& x,
scalarField& y,
scalar& dxTry
) const
{
adaptiveSolver::solve(odes, x, y, dxTry);
adaptiveSolver::solve(odes_, x, y, dxTry);
}

View File

@ -22,7 +22,7 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::Rosenbrock32
Foam::Rosenbrock23
Description
L-stable embedded Rosenbrock ODE solver of order (3)4.
@ -42,12 +42,12 @@ Description
\endverbatim
SourceFiles
Rosenbrock32.C
Rosenbrock23.C
\*---------------------------------------------------------------------------*/
#ifndef Rosenbrock32_H
#define Rosenbrock32_H
#ifndef Rosenbrock23_H
#define Rosenbrock23_H
#include "ODESolver.H"
#include "adaptiveSolver.H"
@ -58,10 +58,10 @@ namespace Foam
{
/*---------------------------------------------------------------------------*\
Class Rosenbrock32 Declaration
Class Rosenbrock23 Declaration
\*---------------------------------------------------------------------------*/
class Rosenbrock32
class Rosenbrock23
:
public ODESolver,
public adaptiveSolver
@ -91,13 +91,13 @@ class Rosenbrock32
public:
//- Runtime type information
TypeName("Rosenbrock32");
TypeName("Rosenbrock23");
// Constructors
//- Construct from ODE
Rosenbrock32(const ODESystem& ode, const dictionary& dict);
Rosenbrock23(const ODESystem& ode, const dictionary& dict);
// Member Functions
@ -105,7 +105,6 @@ public:
//- Solve a single step dx and return the error
scalar solve
(
const ODESystem& ode,
const scalar x0,
const scalarField& y0,
const scalarField& dydx0,
@ -116,7 +115,6 @@ public:
//- Solve the ODE system and the update the state
void solve
(
const ODESystem& ode,
scalar& x,
scalarField& y,
scalar& dxTry

View File

@ -23,89 +23,89 @@ License
\*---------------------------------------------------------------------------*/
#include "Rosenbrock43.H"
#include "Rosenbrock34.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(Rosenbrock43, 0);
addToRunTimeSelectionTable(ODESolver, Rosenbrock43, dictionary);
defineTypeNameAndDebug(Rosenbrock34, 0);
addToRunTimeSelectionTable(ODESolver, Rosenbrock34, dictionary);
const scalar
// L-Stable constants from Hairer et. al.
Rosenbrock43::a21 = 2,
Rosenbrock43::a31 = 1.867943637803922,
Rosenbrock43::a32 = 0.2344449711399156,
Rosenbrock43::c21 = -7.137615036412310,
Rosenbrock43::c31 = 2.580708087951457,
Rosenbrock43::c32 = 0.6515950076447975,
Rosenbrock43::c41 = -2.137148994382534,
Rosenbrock43::c42 = -0.3214669691237626,
Rosenbrock43::c43 = -0.6949742501781779,
Rosenbrock43::b1 = 2.255570073418735,
Rosenbrock43::b2 = 0.2870493262186792,
Rosenbrock43::b3 = 0.435317943184018,
Rosenbrock43::b4 = 1.093502252409163,
Rosenbrock43::e1 = -0.2815431932141155,
Rosenbrock43::e2 = -0.0727619912493892,
Rosenbrock43::e3 = -0.1082196201495311,
Rosenbrock43::e4 = -1.093502252409163,
Rosenbrock43::gamma = 0.57282,
Rosenbrock43::c2 = 1.14564,
Rosenbrock43::c3 = 0.65521686381559,
Rosenbrock43::d1 = 0.57282,
Rosenbrock43::d2 = -1.769193891319233,
Rosenbrock43::d3 = 0.7592633437920482,
Rosenbrock43::d4 = -0.1049021087100450;
// Constants by Shampine
// More accurate than the L-Stable coefficients for small step-size
// but less stable for large step-size
Rosenbrock34::a21 = 2,
Rosenbrock34::a31 = 48.0/25.0,
Rosenbrock34::a32 = 6.0/25.0,
Rosenbrock34::c21 = -8,
Rosenbrock34::c31 = 372.0/25.0,
Rosenbrock34::c32 = 12.0/5.0,
Rosenbrock34::c41 = -112.0/125.0,
Rosenbrock34::c42 = -54.0/125.0,
Rosenbrock34::c43 = -2.0/5.0,
Rosenbrock34::b1 = 19.0/9.0,
Rosenbrock34::b2 = 1.0/2.0,
Rosenbrock34::b3 = 25.0/108.0,
Rosenbrock34::b4 = 125.0/108.0,
Rosenbrock34::e1 = 34.0/108.0,
Rosenbrock34::e2 = 7.0/36.0,
Rosenbrock34::e3 = 0,
Rosenbrock34::e4 = 125.0/108.0,
Rosenbrock34::gamma = 1.0/2.0,
Rosenbrock34::c2 = 1,
Rosenbrock34::c3 = 3.0/5.0,
Rosenbrock34::d1 = 1.0/2.0,
Rosenbrock34::d2 = -3.0/2.0,
Rosenbrock34::d3 = 605.0/250.0,
Rosenbrock34::d4 = 29.0/250.0;
/*
Rosenbrock43::a21 = 2,
Rosenbrock43::a31 = 48.0/25.0,
Rosenbrock43::a32 = 6.0/25.0,
// L-Stable constants from Hairer et. al.
Rosenbrock34::a21 = 2,
Rosenbrock34::a31 = 1.867943637803922,
Rosenbrock34::a32 = 0.2344449711399156,
Rosenbrock43::c21 = -8,
Rosenbrock43::c31 = 372.0/25.0,
Rosenbrock43::c32 = 12.0/5.0,
Rosenbrock34::c21 = -7.137615036412310,
Rosenbrock34::c31 = 2.580708087951457,
Rosenbrock34::c32 = 0.6515950076447975,
Rosenbrock34::c41 = -2.137148994382534,
Rosenbrock34::c42 = -0.3214669691237626,
Rosenbrock34::c43 = -0.6949742501781779,
Rosenbrock43::c41 = -112.0/125.0,
Rosenbrock43::c42 = -54.0/125.0,
Rosenbrock43::c43 = -2.0/5.0,
Rosenbrock34::b1 = 2.255570073418735,
Rosenbrock34::b2 = 0.2870493262186792,
Rosenbrock34::b3 = 0.435317943184018,
Rosenbrock34::b4 = 1.093502252409163,
Rosenbrock43::b1 = 19.0/9.0,
Rosenbrock43::b2 = 1.0/2.0,
Rosenbrock43::b3 = 25.0/108.0,
Rosenbrock43::b4 = 125.0/108.0,
Rosenbrock34::e1 = -0.2815431932141155,
Rosenbrock34::e2 = -0.0727619912493892,
Rosenbrock34::e3 = -0.1082196201495311,
Rosenbrock34::e4 = -1.093502252409163,
Rosenbrock43::e1 = 34.0/108.0,
Rosenbrock43::e2 = 7.0/36.0,
Rosenbrock43::e3 = 0,
Rosenbrock43::e4 = 125.0/108.0,
Rosenbrock34::gamma = 0.57282,
Rosenbrock34::c2 = 1.14564,
Rosenbrock34::c3 = 0.65521686381559,
Rosenbrock43::gamma = 1.0/2.0,
Rosenbrock43::c2 = 1,
Rosenbrock43::c3 = 3.0/5.0,
Rosenbrock43::d1 = 1.0/2.0,
Rosenbrock43::d2 = -3.0/2.0,
Rosenbrock43::d3 = 605.0/250.0,
Rosenbrock43::d4 = 29.0/250.0;
Rosenbrock34::d1 = 0.57282,
Rosenbrock34::d2 = -1.769193891319233,
Rosenbrock34::d3 = 0.7592633437920482,
Rosenbrock34::d4 = -0.1049021087100450;
*/
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::Rosenbrock43::Rosenbrock43(const ODESystem& ode, const dictionary& dict)
Foam::Rosenbrock34::Rosenbrock34(const ODESystem& ode, const dictionary& dict)
:
ODESolver(ode, dict),
adaptiveSolver(ode, dict),
@ -124,9 +124,8 @@ Foam::Rosenbrock43::Rosenbrock43(const ODESystem& ode, const dictionary& dict)
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::scalar Foam::Rosenbrock43::solve
Foam::scalar Foam::Rosenbrock34::solve
(
const ODESystem& ode,
const scalar x0,
const scalarField& y0,
const scalarField& dydx0,
@ -134,7 +133,7 @@ Foam::scalar Foam::Rosenbrock43::solve
scalarField& y
) const
{
ode.jacobian(x0, y0, dfdx_, dfdy_);
odes_.jacobian(x0, y0, dfdx_, dfdy_);
for (register label i=0; i<n_; i++)
{
@ -162,7 +161,7 @@ Foam::scalar Foam::Rosenbrock43::solve
y[i] = y0[i] + a21*k1_[i];
}
ode.derivatives(x0 + c2*dx, y, dydx_);
odes_.derivatives(x0 + c2*dx, y, dydx_);
forAll(k2_, i)
{
@ -177,7 +176,7 @@ Foam::scalar Foam::Rosenbrock43::solve
y[i] = y0[i] + a31*k1_[i] + a32*k2_[i];
}
ode.derivatives(x0 + c3*dx, y, dydx_);
odes_.derivatives(x0 + c3*dx, y, dydx_);
forAll(k3_, i)
{
@ -206,15 +205,14 @@ Foam::scalar Foam::Rosenbrock43::solve
}
void Foam::Rosenbrock43::solve
void Foam::Rosenbrock34::solve
(
const ODESystem& odes,
scalar& x,
scalarField& y,
scalar& dxTry
) const
{
adaptiveSolver::solve(odes, x, y, dxTry);
adaptiveSolver::solve(odes_, x, y, dxTry);
}

View File

@ -22,12 +22,11 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::Rosenbrock43
Foam::Rosenbrock34
Description
L-stable embedded Rosenbrock ODE solver of order (3)4.
Based on code from:
\verbatim
"Solving Ordinary Differential Equations II: Stiff
and Differential-Algebraic Problems, second edition",
@ -37,7 +36,7 @@ Description
Springer-Verlag, Berlin. 1996.
\endverbatim
Also provided are the constants from:
The default constants are from:
\verbatim
"Implementation of Rosenbrock Methods"
Shampine, L. F.,
@ -46,13 +45,15 @@ Description
with which the scheme is more accurate than with the L-Stable coefficients
for small step-size but less stable for large step-size.
The L-Stable scheme constants are provided commented-out in Rosenbrock34.C
SourceFiles
Rosenbrock43.C
Rosenbrock34.C
\*---------------------------------------------------------------------------*/
#ifndef Rosenbrock43_H
#define Rosenbrock43_H
#ifndef Rosenbrock34_H
#define Rosenbrock34_H
#include "ODESolver.H"
#include "adaptiveSolver.H"
@ -63,10 +64,10 @@ namespace Foam
{
/*---------------------------------------------------------------------------*\
Class Rosenbrock43 Declaration
Class Rosenbrock34 Declaration
\*---------------------------------------------------------------------------*/
class Rosenbrock43
class Rosenbrock34
:
public ODESolver,
public adaptiveSolver
@ -98,13 +99,13 @@ class Rosenbrock43
public:
//- Runtime type information
TypeName("Rosenbrock43");
TypeName("Rosenbrock34");
// Constructors
//- Construct from ODE
Rosenbrock43(const ODESystem& ode, const dictionary& dict);
Rosenbrock34(const ODESystem& ode, const dictionary& dict);
// Member Functions
@ -112,7 +113,6 @@ public:
//- Solve a single step dx and return the error
scalar solve
(
const ODESystem& ode,
const scalar x0,
const scalarField& y0,
const scalarField& dydx0,
@ -123,7 +123,6 @@ public:
//- Solve the ODE system and the update the state
void solve
(
const ODESystem& ode,
scalar& x,
scalarField& y,
scalar& dxTry

View File

@ -70,13 +70,12 @@ Foam::SIBS::SIBS(const ODESystem& ode, const dictionary& dict)
void Foam::SIBS::solve
(
const ODESystem& ode,
scalar& x,
scalarField& y,
scalar& dxTry
) const
{
ode.derivatives(x, y, dydx0_);
odes_.derivatives(x, y, dydx0_);
scalar h = dxTry;
bool exitflag = false;
@ -124,7 +123,7 @@ void Foam::SIBS::solve
label k = 0;
yTemp_ = y;
ode.jacobian(x, y, dfdx_, dfdy_);
odes_.jacobian(x, y, dfdx_, dfdy_);
if (x != xNew_ || h != dxTry)
{
@ -151,7 +150,7 @@ void Foam::SIBS::solve
<< exit(FatalError);
}
SIMPR(ode, x, yTemp_, dydx0_, dfdx_, dfdy_, h, nSeq_[k], ySeq_);
SIMPR(x, yTemp_, dydx0_, dfdx_, dfdy_, h, nSeq_[k], ySeq_);
scalar xest = sqr(h/nSeq_[k]);
polyExtrapolate(k, xest, ySeq_, y, yErr_, x_p_, d_p_);

View File

@ -84,7 +84,6 @@ class SIBS
void SIMPR
(
const ODESystem& ode,
const scalar xStart,
const scalarField& y,
const scalarField& dydx,
@ -123,7 +122,6 @@ public:
void solve
(
const ODESystem& ode,
scalar& x,
scalarField& y,
scalar& dxTry

View File

@ -29,7 +29,6 @@ License
void Foam::SIBS::SIMPR
(
const ODESystem& ode,
const scalar xStart,
const scalarField& y,
const scalarField& dydx,
@ -72,7 +71,7 @@ void Foam::SIBS::SIMPR
scalar x = xStart + h;
ode.derivatives(x, ytemp, yEnd);
odes_.derivatives(x, ytemp, yEnd);
for (register label nn=2; nn<=nSteps; nn++)
{
@ -90,7 +89,7 @@ void Foam::SIBS::SIMPR
x += h;
ode.derivatives(x, ytemp, yEnd);
odes_.derivatives(x, ytemp, yEnd);
}
for (register label i=0; i<n_; i++)
{

View File

@ -49,7 +49,6 @@ Foam::Trapezoid::Trapezoid(const ODESystem& ode, const dictionary& dict)
Foam::scalar Foam::Trapezoid::solve
(
const ODESystem& ode,
const scalar x0,
const scalarField& y0,
const scalarField& dydx0,
@ -64,7 +63,7 @@ Foam::scalar Foam::Trapezoid::solve
}
// Evaluate the system for the predicted state
ode.derivatives(x0 + dx, y, err_);
odes_.derivatives(x0 + dx, y, err_);
// Update the state as the average between the prediction and the correction
// and estimate the error from the difference
@ -80,13 +79,12 @@ Foam::scalar Foam::Trapezoid::solve
void Foam::Trapezoid::solve
(
const ODESystem& odes,
scalar& x,
scalarField& y,
scalar& dxTry
) const
{
adaptiveSolver::solve(odes, x, y, dxTry);
adaptiveSolver::solve(odes_, x, y, dxTry);
}

View File

@ -74,7 +74,6 @@ public:
//- Solve a single step dx and return the error
scalar solve
(
const ODESystem& ode,
const scalar x0,
const scalarField& y0,
const scalarField& dydx0,
@ -85,7 +84,6 @@ public:
//- Solve the ODE system and the update the state
void solve
(
const ODESystem& ode,
scalar& x,
scalarField& y,
scalar& dxTry

View File

@ -64,7 +64,7 @@ void Foam::adaptiveSolver::solve
do
{
// Solve step and provide error estimate
err = solve(odes, x, y, dydx0_, dx, yTemp_);
err = solve(x, y, dydx0_, dx, yTemp_);
// If error is large reduce dx
if (err > 1)

View File

@ -77,7 +77,6 @@ public:
//- Solve a single step dx and return the error
virtual scalar solve
(
const ODESystem& ode,
const scalar x0,
const scalarField& y0,
const scalarField& dydx0,

View File

@ -23,35 +23,35 @@ License
\*---------------------------------------------------------------------------*/
#include "rodas32.H"
#include "rodas23.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(rodas32, 0);
addToRunTimeSelectionTable(ODESolver, rodas32, dictionary);
defineTypeNameAndDebug(rodas23, 0);
addToRunTimeSelectionTable(ODESolver, rodas23, dictionary);
const scalar
rodas32::c3 = 1,
rodas32::d1 = 1.0/2.0,
rodas32::d2 = 3.0/2.0,
rodas32::a31 = 2,
rodas32::a41 = 2,
rodas32::c21 = 4,
rodas32::c31 = 1,
rodas32::c32 = -1,
rodas32::c41 = 1,
rodas32::c42 = -1,
rodas32::c43 = -8.0/3.0,
rodas32::gamma = 1.0/2.0;
rodas23::c3 = 1,
rodas23::d1 = 1.0/2.0,
rodas23::d2 = 3.0/2.0,
rodas23::a31 = 2,
rodas23::a41 = 2,
rodas23::c21 = 4,
rodas23::c31 = 1,
rodas23::c32 = -1,
rodas23::c41 = 1,
rodas23::c42 = -1,
rodas23::c43 = -8.0/3.0,
rodas23::gamma = 1.0/2.0;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::rodas32::rodas32(const ODESystem& ode, const dictionary& dict)
Foam::rodas23::rodas23(const ODESystem& ode, const dictionary& dict)
:
ODESolver(ode, dict),
adaptiveSolver(ode, dict),
@ -70,9 +70,8 @@ Foam::rodas32::rodas32(const ODESystem& ode, const dictionary& dict)
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::scalar Foam::rodas32::solve
Foam::scalar Foam::rodas23::solve
(
const ODESystem& ode,
const scalar x0,
const scalarField& y0,
const scalarField& dydx0,
@ -80,7 +79,7 @@ Foam::scalar Foam::rodas32::solve
scalarField& y
) const
{
ode.jacobian(x0, y0, dfdx_, dfdy_);
odes_.jacobian(x0, y0, dfdx_, dfdy_);
for (register label i=0; i<n_; i++)
{
@ -117,7 +116,7 @@ Foam::scalar Foam::rodas32::solve
y[i] = y0[i] + dy_[i];
}
ode.derivatives(x0 + dx, y, dydx_);
odes_.derivatives(x0 + dx, y, dydx_);
forAll(k3_, i)
{
@ -133,7 +132,7 @@ Foam::scalar Foam::rodas32::solve
y[i] = y0[i] + dy_[i];
}
ode.derivatives(x0 + dx, y, dydx_);
odes_.derivatives(x0 + dx, y, dydx_);
forAll(err_, i)
{
@ -151,15 +150,14 @@ Foam::scalar Foam::rodas32::solve
}
void Foam::rodas32::solve
void Foam::rodas23::solve
(
const ODESystem& odes,
scalar& x,
scalarField& y,
scalar& dxTry
) const
{
adaptiveSolver::solve(odes, x, y, dxTry);
adaptiveSolver::solve(odes_, x, y, dxTry);
}

View File

@ -22,7 +22,7 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::rodas32
Foam::rodas23
Description
L-stable, stiffly-accurate embedded Rosenbrock ODE solver of order (2)3.
@ -42,12 +42,12 @@ Description
\endverbatim
SourceFiles
rodas32.C
rodas23.C
\*---------------------------------------------------------------------------*/
#ifndef rodas32_H
#define rodas32_H
#ifndef rodas23_H
#define rodas23_H
#include "ODESolver.H"
#include "adaptiveSolver.H"
@ -58,10 +58,10 @@ namespace Foam
{
/*---------------------------------------------------------------------------*\
Class rodas32 Declaration
Class rodas23 Declaration
\*---------------------------------------------------------------------------*/
class rodas32
class rodas23
:
public ODESolver,
public adaptiveSolver
@ -91,13 +91,13 @@ class rodas32
public:
//- Runtime type information
TypeName("rodas32");
TypeName("rodas23");
// Constructors
//- Construct from ODE
rodas32(const ODESystem& ode, const dictionary& dict);
rodas23(const ODESystem& ode, const dictionary& dict);
// Member Functions
@ -105,7 +105,6 @@ public:
//- Solve a single step dx and return the error
scalar solve
(
const ODESystem& ode,
const scalar x0,
const scalarField& y0,
const scalarField& dydx0,
@ -116,7 +115,6 @@ public:
//- Solve the ODE system and the update the state
void solve
(
const ODESystem& ode,
scalar& x,
scalarField& y,
scalar& dxTry

View File

@ -23,56 +23,56 @@ License
\*---------------------------------------------------------------------------*/
#include "rodas43.H"
#include "rodas34.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(rodas43, 0);
addToRunTimeSelectionTable(ODESolver, rodas43, dictionary);
defineTypeNameAndDebug(rodas34, 0);
addToRunTimeSelectionTable(ODESolver, rodas34, dictionary);
const scalar
rodas43::c2 = 0.386,
rodas43::c3 = 0.21,
rodas43::c4 = 0.63,
rodas43::d1 = 0.25,
rodas43::d2 = -0.1043,
rodas43::d3 = 0.1035,
rodas43::d4 = -0.3620000000000023e-01,
rodas43::a21 = 0.1544e1,
rodas43::a31 = 0.9466785280815826,
rodas43::a32 = 0.2557011698983284,
rodas43::a41 = 0.3314825187068521e1,
rodas43::a42 = 0.2896124015972201e1,
rodas43::a43 = 0.9986419139977817,
rodas43::a51 = 0.1221224509226641e1,
rodas43::a52 = 0.6019134481288629e1,
rodas43::a53 = 0.1253708332932087e2,
rodas43::a54 = -0.6878860361058950,
rodas43::c21 = -0.56688e1,
rodas43::c31 = -0.2430093356833875e1,
rodas43::c32 = -0.2063599157091915,
rodas43::c41 = -0.1073529058151375,
rodas43::c42 = -0.9594562251023355e1,
rodas43::c43 = -0.2047028614809616e2,
rodas43::c51 = 0.7496443313967647e1,
rodas43::c52 = -0.1024680431464352e2,
rodas43::c53 = -0.3399990352819905e2,
rodas43::c54 = 0.1170890893206160e2,
rodas43::c61 = 0.8083246795921522e1,
rodas43::c62 = -0.7981132988064893e1,
rodas43::c63 = -0.3152159432874371e2,
rodas43::c64 = 0.1631930543123136e2,
rodas43::c65 = -0.6058818238834054e1,
rodas43::gamma = 0.25;
rodas34::c2 = 0.386,
rodas34::c3 = 0.21,
rodas34::c4 = 0.63,
rodas34::d1 = 0.25,
rodas34::d2 = -0.1043,
rodas34::d3 = 0.1035,
rodas34::d4 = -0.3620000000000023e-01,
rodas34::a21 = 0.1544e1,
rodas34::a31 = 0.9466785280815826,
rodas34::a32 = 0.2557011698983284,
rodas34::a41 = 0.3314825187068521e1,
rodas34::a42 = 0.2896124015972201e1,
rodas34::a43 = 0.9986419139977817,
rodas34::a51 = 0.1221224509226641e1,
rodas34::a52 = 0.6019134481288629e1,
rodas34::a53 = 0.1253708332932087e2,
rodas34::a54 = -0.6878860361058950,
rodas34::c21 = -0.56688e1,
rodas34::c31 = -0.2430093356833875e1,
rodas34::c32 = -0.2063599157091915,
rodas34::c41 = -0.1073529058151375,
rodas34::c42 = -0.9594562251023355e1,
rodas34::c43 = -0.2047028614809616e2,
rodas34::c51 = 0.7496443313967647e1,
rodas34::c52 = -0.1024680431464352e2,
rodas34::c53 = -0.3399990352819905e2,
rodas34::c54 = 0.1170890893206160e2,
rodas34::c61 = 0.8083246795921522e1,
rodas34::c62 = -0.7981132988064893e1,
rodas34::c63 = -0.3152159432874371e2,
rodas34::c64 = 0.1631930543123136e2,
rodas34::c65 = -0.6058818238834054e1,
rodas34::gamma = 0.25;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::rodas43::rodas43(const ODESystem& ode, const dictionary& dict)
Foam::rodas34::rodas34(const ODESystem& ode, const dictionary& dict)
:
ODESolver(ode, dict),
adaptiveSolver(ode, dict),
@ -93,9 +93,8 @@ Foam::rodas43::rodas43(const ODESystem& ode, const dictionary& dict)
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::scalar Foam::rodas43::solve
Foam::scalar Foam::rodas34::solve
(
const ODESystem& ode,
const scalar x0,
const scalarField& y0,
const scalarField& dydx0,
@ -103,7 +102,7 @@ Foam::scalar Foam::rodas43::solve
scalarField& y
) const
{
ode.jacobian(x0, y0, dfdx_, dfdy_);
odes_.jacobian(x0, y0, dfdx_, dfdy_);
for (register label i=0; i<n_; i++)
{
@ -131,7 +130,7 @@ Foam::scalar Foam::rodas43::solve
y[i] = y0[i] + a21*k1_[i];
}
ode.derivatives(x0 + c2*dx, y, dydx_);
odes_.derivatives(x0 + c2*dx, y, dydx_);
forAll(k2_, i)
{
@ -146,7 +145,7 @@ Foam::scalar Foam::rodas43::solve
y[i] = y0[i] + a31*k1_[i] + a32*k2_[i];
}
ode.derivatives(x0 + c3*dx, y, dydx_);
odes_.derivatives(x0 + c3*dx, y, dydx_);
forAll(k3_, i)
{
@ -161,7 +160,7 @@ Foam::scalar Foam::rodas43::solve
y[i] = y0[i] + a41*k1_[i] + a42*k2_[i] + a43*k3_[i];
}
ode.derivatives(x0 + c4*dx, y, dydx_);
odes_.derivatives(x0 + c4*dx, y, dydx_);
forAll(k4_, i)
{
@ -178,7 +177,7 @@ Foam::scalar Foam::rodas43::solve
y[i] = y0[i] + dy_[i];
}
ode.derivatives(x0 + dx, y, dydx_);
odes_.derivatives(x0 + dx, y, dydx_);
forAll(k5_, i)
{
@ -195,7 +194,7 @@ Foam::scalar Foam::rodas43::solve
y[i] = y0[i] + dy_[i];
}
ode.derivatives(x0 + dx, y, dydx_);
odes_.derivatives(x0 + dx, y, dydx_);
forAll(err_, i)
{
@ -214,15 +213,14 @@ Foam::scalar Foam::rodas43::solve
}
void Foam::rodas43::solve
void Foam::rodas34::solve
(
const ODESystem& odes,
scalar& x,
scalarField& y,
scalar& dxTry
) const
{
adaptiveSolver::solve(odes, x, y, dxTry);
adaptiveSolver::solve(odes_, x, y, dxTry);
}

View File

@ -22,7 +22,7 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::rodas43
Foam::rodas34
Description
L-stable, stiffly-accurate embedded Rosenbrock ODE solver of order (3)4.
@ -38,12 +38,12 @@ Description
\endverbatim
SourceFiles
rodas43.C
rodas34.C
\*---------------------------------------------------------------------------*/
#ifndef rodas43_H
#define rodas43_H
#ifndef rodas34_H
#define rodas34_H
#include "ODESolver.H"
#include "adaptiveSolver.H"
@ -54,10 +54,10 @@ namespace Foam
{
/*---------------------------------------------------------------------------*\
Class rodas43 Declaration
Class rodas34 Declaration
\*---------------------------------------------------------------------------*/
class rodas43
class rodas34
:
public ODESolver,
public adaptiveSolver
@ -92,13 +92,13 @@ class rodas43
public:
//- Runtime type information
TypeName("rodas43");
TypeName("rodas34");
// Constructors
//- Construct from ODE
rodas43(const ODESystem& ode, const dictionary& dict);
rodas34(const ODESystem& ode, const dictionary& dict);
// Member Functions
@ -106,7 +106,6 @@ public:
//- Solve a single step dx and return the error
scalar solve
(
const ODESystem& ode,
const scalar x0,
const scalarField& y0,
const scalarField& dydx0,
@ -117,7 +116,6 @@ public:
//- Solve the ODE system and the update the state
void solve
(
const ODESystem& ode,
scalar& x,
scalarField& y,
scalar& dxTry

View File

@ -35,14 +35,13 @@ namespace Foam
addToRunTimeSelectionTable(ODESolver, seulex, dictionary);
const scalar
seulex::EPS = VSMALL,
seulex::STEPFAC1 = 0.6,
seulex::STEPFAC2 = 0.93,
seulex::STEPFAC3 = 0.1,
seulex::STEPFAC4 = 4.0,
seulex::STEPFAC5 = 0.5,
seulex::KFAC1 = 0.7,
seulex::KFAC2 = 0.9;
seulex::stepFactor1_ = 0.6,
seulex::stepFactor2_ = 0.93,
seulex::stepFactor3_ = 0.1,
seulex::stepFactor4_ = 4.0,
seulex::stepFactor5_ = 0.5,
seulex::kFactor1_ = 0.7,
seulex::kFactor2_ = 0.9;
}
@ -51,150 +50,222 @@ namespace Foam
Foam::seulex::seulex(const ODESystem& ode, const dictionary& dict)
:
ODESolver(ode, dict),
ode_(ode),
nSeq_(IMAXX),
cost_(IMAXX),
jacRedo_(min(1.0e-4, min(relTol_))),
nSeq_(iMaxx_),
cpu_(iMaxx_),
coeff_(iMaxx_, iMaxx_),
theta_(2.0*jacRedo_),
table_(kMaxx_, n_),
dfdx_(n_),
factrl_(IMAXX),
table_(KMAXX,n_),
fSave_((IMAXX-1)*(IMAXX+1)/2 + 2,n_),
dfdy_(n_),
calcJac_(false),
dense_(false),
a_(n_),
coeff_(IMAXX,IMAXX),
pivotIndices_(n_, 0.0),
hOpt_(IMAXX),
work_(IMAXX),
ySaved_(n_),
pivotIndices_(n_),
dxOpt_(iMaxx_),
temp_(iMaxx_),
y0_(n_),
ySequence_(n_),
scale_(n_),
del_(n_),
dy_(n_),
yTemp_(n_),
dyTemp_(n_),
delTemp_(n_)
dydx_(n_)
{
const scalar costfunc = 1.0, costjac = 5.0, costlu = 1.0, costsolve = 1.0;
// The CPU time factors for the major parts of the algorithm
const scalar cpuFunc = 1.0, cpuJac = 5.0, cpuLU = 1.0, cpuSolve = 1.0;
jacRedo_ = min(1.0e-4, min(relTol_));
theta_ = 2.0*jacRedo_;
nSeq_[0] = 2;
nSeq_[1] = 3;
for (label i = 2; i < IMAXX; i++)
for (int i=2; i<iMaxx_; i++)
{
nSeq_[i] = 2*nSeq_[i-2];
}
cost_[0] = costjac + costlu + nSeq_[0]*(costfunc + costsolve);
cpu_[0] = cpuJac + cpuLU + nSeq_[0]*(cpuFunc + cpuSolve);
for (label k=0;k<KMAXX;k++)
for (int k=0; k<kMaxx_; k++)
{
cost_[k+1] = cost_[k] + (nSeq_[k+1]-1)*(costfunc + costsolve) + costlu;
cpu_[k+1] = cpu_[k] + (nSeq_[k+1]-1)*(cpuFunc + cpuSolve) + cpuLU;
}
hnext_ =- VGREAT;
//NOTE: the first element of relTol_ and absTol_ are used here.
scalar logfact =- log10(relTol_[0] + absTol_[0])*0.6 + 0.5;
kTarg_ = min(1, min(KMAXX - 1, label(logfact)));
for (label k = 0; k < IMAXX; k++)
// Set the extrapolation coefficients array
for (int k=0; k<iMaxx_; k++)
{
for (label l = 0; l < k; l++)
for (int l=0; l<k; l++)
{
scalar ratio = scalar(nSeq_[k])/nSeq_[l];
coeff_[k][l] = 1.0/(ratio - 1.0);
}
}
factrl_[0] = 1.0;
for (label k = 0; k < IMAXX - 1; k++)
{
factrl_[k+1] = (k+1)*factrl_[k];
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
bool Foam::seulex::seul
(
const scalar x0,
const scalarField& y0,
const scalar dxTot,
const label k,
scalarField& y,
const scalarField& scale
) const
{
label nSteps = nSeq_[k];
scalar dx = dxTot/nSteps;
for (label i=0; i<n_; i++)
{
for (label j=0; j<n_; j++)
{
a_[i][j] = -dfdy_[i][j];
}
a_[i][i] += 1.0/dx;
}
LUDecompose(a_, pivotIndices_);
scalar xnew = x0 + dx;
odes_.derivatives(xnew, y0, dy_);
LUBacksubstitute(a_, pivotIndices_, dy_);
yTemp_ = y0;
for (label nn=1; nn<nSteps; nn++)
{
yTemp_ += dy_;
xnew += dx;
if (nn == 1 && k<=1)
{
scalar dy1 = 0.0;
for (label i=0; i<n_; i++)
{
dy1 += sqr(dy_[i]/scale[i]);
}
dy1 = sqrt(dy1);
odes_.derivatives(x0 + dx, yTemp_, dydx_);
for (label i=0; i<n_; i++)
{
dy_[i] = dydx_[i] - dy_[i]/dx;
}
LUBacksubstitute(a_, pivotIndices_, dy_);
scalar dy2 = 0.0;
for (label i=0; i<n_; i++)
{
dy2 += sqr(dy_[i]/scale[i]);
}
dy2 = sqrt(dy2);
theta_ = dy2/min(1.0, dy1 + SMALL);
if (theta_ > 1.0)
{
return false;
}
}
odes_.derivatives(xnew, yTemp_, dy_);
LUBacksubstitute(a_, pivotIndices_, dy_);
}
for (label i=0; i<n_; i++)
{
y[i] = yTemp_[i] + dy_[i];
}
return true;
}
void Foam::seulex::extrapolate
(
const label k,
scalarRectangularMatrix& table,
scalarField& y
) const
{
for (int j=k-1; j>0; j--)
{
for (label i=0; i<n_; i++)
{
table[j-1][i] =
table[j][i] + coeff_[k][j]*(table[j][i] - table[j-1][i]);
}
}
for (int i=0; i<n_; i++)
{
y[i] = table[0][i] + coeff_[k][0]*(table[0][i] - y[i]);
}
}
void Foam::seulex::solve
(
const ODESystem& ode,
scalar& x,
scalarField& y,
scalar& dxTry
stepState& step
) const
{
step(dxTry, x, y);
dxTry = hnext_;
}
temp_[0] = GREAT;
scalar dx = step.dxTry;
y0_ = y;
dxOpt_[0] = mag(0.1*dx);
void Foam::seulex::step(const scalar& htry, scalar& x, scalarField& y) const
if (step.first || step.prevReject)
{
static bool first_step = true, last_step = false;
static bool forward, reject = false, prev_reject = false;
static scalar errold;
label i, k;
scalar fac, h, hnew, err;
bool firstk;
work_[0] = 1.e30;
h = htry;
forward = h > 0 ? true : false;
ySaved_ = y;
if (h != hnext_ && !first_step)
{
last_step = true;
}
if (reject)
{
prev_reject = true;
last_step = false;
theta_ = 2.0*jacRedo_;
}
for (i = 0; i < n_; i++)
if (step.first)
{
// NOTE: the first element of relTol_ and absTol_ are used here.
scalar logTol = -log10(relTol_[0] + absTol_[0])*0.6 + 0.5;
kTarg_ = max(1, min(kMaxx_ - 1, int(logTol)));
}
forAll(scale_, i)
{
scale_[i] = absTol_[i] + relTol_[i]*mag(y[i]);
}
reject = false;
firstk = true;
hnew = mag(h);
bool jacUpdated = false;
if (theta_ > jacRedo_ && !calcJac_)
if (theta_ > jacRedo_)
{
ode_.jacobian(x, y, dfdx_, dfdy_);
calcJac_ = true;
odes_.jacobian(x, y, dfdx_, dfdy_);
jacUpdated = true;
}
while (firstk || reject)
int k;
scalar dxNew = mag(dx);
bool firstk = true;
while (firstk || step.reject)
{
h = forward ? hnew : -hnew;
dx = step.forward ? dxNew : -dxNew;
firstk = false;
reject = false;
step.reject = false;
if (mag(h) <= mag(x)*EPS)
if (mag(dx) <= mag(x)*SMALL)
{
WarningIn("seulex::step(const scalar")
<< "step size underflow in step :" << h << endl;
WarningIn("seulex::solve(scalar& x, scalarField& y, stepState&")
<< "step size underflow :" << dx << endl;
}
label ipt=-1;
scalar errOld;
for (k=0; k<=kTarg_+1; k++)
{
bool success = dy(x, ySaved_, h, k, ySequence_, ipt, scale_);
bool success = seul(x, y0_, dx, k, ySequence_, scale_);
if (!success)
{
reject = true;
hnew = mag(h)*STEPFAC5;
step.reject = true;
dxNew = mag(dx)*stepFactor5_;
break;
}
@ -204,45 +275,55 @@ void Foam::seulex::step(const scalar& htry, scalar& x, scalarField& y) const
}
else
{
for (i = 0; i < n_; i++)
forAll(ySequence_, i)
{
table_[k-1][i] = ySequence_[i];
}
}
if (k != 0)
{
polyextr(k, table_, y);
err = 0.0;
for (i = 0; i < n_; i++)
extrapolate(k, table_, y);
scalar err = 0.0;
forAll(scale_, i)
{
scale_[i] = absTol_[i] + relTol_[i]*mag(ySaved_[i]);
scale_[i] = absTol_[i] + relTol_[i]*mag(y0_[i]);
err += sqr((y[i] - table_[0][i])/scale_[i]);
}
err = sqrt(err/n_);
if (err > 1.0/EPS || (k > 1 && err >= errold))
if (err > 1.0/SMALL || (k > 1 && err >= errOld))
{
reject = true;
hnew = mag(h)*STEPFAC5;
step.reject = true;
dxNew = mag(dx)*stepFactor5_;
break;
}
errold = min(4.0*err, 1.0);
errOld = min(4*err, 1);
scalar expo = 1.0/(k + 1);
scalar facmin = pow(STEPFAC3, expo);
scalar facmin = pow(stepFactor3_, expo);
scalar fac;
if (err == 0.0)
{
fac = 1.0/facmin;
}
else
{
fac = STEPFAC2/pow(err/STEPFAC1, expo);
fac = max(facmin/STEPFAC4, min(1.0/facmin, fac));
fac = stepFactor2_/pow(err/stepFactor1_, expo);
fac = max(facmin/stepFactor4_, min(1.0/facmin, fac));
}
hOpt_[k] = mag(h*fac);
work_[k] = cost_[k]/hOpt_[k];
dxOpt_[k] = mag(dx*fac);
temp_[k] = cpu_[k]/dxOpt_[k];
if ((first_step || last_step) && err <= 1.0)
if ((step.first || step.last) && err <= 1.0)
{
break;
}
if (k == kTarg_-1 && !prev_reject && !first_step && !last_step)
if
(
k == kTarg_ - 1
&& !step.prevReject
&& !step.first && !step.last
)
{
if (err <= 1.0)
{
@ -250,16 +331,17 @@ void Foam::seulex::step(const scalar& htry, scalar& x, scalarField& y) const
}
else if (err > nSeq_[kTarg_]*nSeq_[kTarg_ + 1]*4.0)
{
reject = true;
step.reject = true;
kTarg_ = k;
if (kTarg_>1 && work_[k-1] < KFAC1*work_[k])
if (kTarg_>1 && temp_[k-1] < kFactor1_*temp_[k])
{
kTarg_--;
}
hnew = hOpt_[kTarg_];
dxNew = dxOpt_[kTarg_];
break;
}
}
if (k == kTarg_)
{
if (err <= 1.0)
@ -268,51 +350,55 @@ void Foam::seulex::step(const scalar& htry, scalar& x, scalarField& y) const
}
else if (err > nSeq_[k + 1]*2.0)
{
reject = true;
if (kTarg_>1 && work_[k-1] < KFAC1*work_[k])
step.reject = true;
if (kTarg_>1 && temp_[k-1] < kFactor1_*temp_[k])
{
kTarg_--;
}
hnew = hOpt_[kTarg_];
dxNew = dxOpt_[kTarg_];
break;
}
}
if (k == kTarg_+1)
{
if (err > 1.0)
{
reject = true;
if (kTarg_ > 1 && work_[kTarg_-1] < KFAC1*work_[kTarg_])
step.reject = true;
if
(
kTarg_ > 1
&& temp_[kTarg_-1] < kFactor1_*temp_[kTarg_]
)
{
kTarg_--;
}
hnew = hOpt_[kTarg_];
dxNew = dxOpt_[kTarg_];
}
break;
}
}
}
if (reject)
if (step.reject)
{
prev_reject = true;
if (!calcJac_)
step.prevReject = true;
if (!jacUpdated)
{
theta_ = 2.0*jacRedo_;
if (theta_ > jacRedo_ && !calcJac_)
if (theta_ > jacRedo_ && !jacUpdated)
{
ode_.jacobian(x, y, dfdx_, dfdy_);
calcJac_ = true;
odes_.jacobian(x, y, dfdx_, dfdy_);
jacUpdated = true;
}
}
}
}
calcJac_ = false;
jacUpdated = false;
x += h;
hdid_ = h;
first_step = false;
step.dxDid = dx;
x += dx;
label kopt;
if (k == 1)
@ -322,180 +408,56 @@ void Foam::seulex::step(const scalar& htry, scalar& x, scalarField& y) const
else if (k <= kTarg_)
{
kopt=k;
if (work_[k-1] < KFAC1*work_[k])
if (temp_[k-1] < kFactor1_*temp_[k])
{
kopt = k - 1;
}
else if (work_[k] < KFAC2*work_[k - 1])
else if (temp_[k] < kFactor2_*temp_[k - 1])
{
kopt = min(k + 1, KMAXX - 1);
kopt = min(k + 1, kMaxx_ - 1);
}
}
else
{
kopt = k - 1;
if (k > 2 && work_[k-2] < KFAC1*work_[k - 1])
if (k > 2 && temp_[k-2] < kFactor1_*temp_[k - 1])
{
kopt = k - 2;
}
if (work_[k] < KFAC2*work_[kopt])
if (temp_[k] < kFactor2_*temp_[kopt])
{
kopt = min(k, KMAXX - 1);
kopt = min(k, kMaxx_ - 1);
}
}
if (prev_reject)
if (step.prevReject)
{
kTarg_ = min(kopt, k);
hnew = min(mag(h), hOpt_[kTarg_]);
prev_reject = false;
dxNew = min(mag(dx), dxOpt_[kTarg_]);
step.prevReject = false;
}
else
{
if (kopt <= k)
{
hnew = hOpt_[kopt];
dxNew = dxOpt_[kopt];
}
else
{
if (k < kTarg_ && work_[k] < KFAC2*work_[k - 1])
if (k < kTarg_ && temp_[k] < kFactor2_*temp_[k - 1])
{
hnew = hOpt_[k]*cost_[kopt + 1]/cost_[k];
dxNew = dxOpt_[k]*cpu_[kopt + 1]/cpu_[k];
}
else
{
hnew = hOpt_[k]*cost_[kopt]/cost_[k];
dxNew = dxOpt_[k]*cpu_[kopt]/cpu_[k];
}
}
kTarg_ = kopt;
}
if (forward)
{
hnext_ = hnew;
}
else
{
hnext_ =- hnew;
}
step.dxTry = step.forward ? dxNew : -dxNew;
}
bool Foam::seulex::dy
(
const scalar& x,
scalarField& y,
const scalar htot,
const label k,
scalarField& yend,
label& ipt,
scalarField& scale
) const
{
label nstep = nSeq_[k];
scalar h = htot/nstep;
for (label i = 0; i < n_; i++)
{
for (label j = 0; j < n_; j++) a_[i][j] = -dfdy_[i][j];
a_[i][i] += 1.0/h;
}
LUDecompose(a_, pivotIndices_);
scalar xnew = x + h;
ode_.derivatives(xnew, y, del_);
yTemp_ = y;
LUBacksubstitute(a_, pivotIndices_, del_);
if (dense_ && nstep == k + 1)
{
ipt++;
for (label i = 0; i < n_; i++)
{
fSave_[ipt][i] = del_[i];
}
}
for (label nn = 1; nn < nstep; nn++)
{
for (label i=0;i<n_;i++)
{
yTemp_[i] += del_[i];
}
xnew += h;
ode_.derivatives(xnew, yTemp_, yend);
if (nn == 1 && k<=1)
{
scalar del1=0.0;
for (label i = 0; i < n_; i++)
{
del1 += sqr(del_[i]/scale[i]);
}
del1 = sqrt(del1);
ode_.derivatives(x+h, yTemp_, dyTemp_);
for (label i=0;i<n_;i++)
{
del_[i] = dyTemp_[i] - del_[i]/h;
}
LUBacksubstitute(a_, pivotIndices_, del_);
scalar del2 = 0.0;
for (label i = 0; i <n_ ; i++)
{
del2 += sqr(del_[i]/scale[i]);
}
del2 = sqrt(del2);
theta_ = del2 / min(1.0, del1 + SMALL);
if (theta_ > 1.0)
{
return false;
}
}
delTemp_ = yend;
LUBacksubstitute(a_, pivotIndices_, delTemp_);
del_ = delTemp_;
if (dense_ && nn >= nstep-k-1)
{
ipt++;
for (label i=0;i<n_;i++)
{
fSave_[ipt][i]=del_[i];
}
}
}
yend = yTemp_ + del_;
return true;
}
void Foam::seulex::polyextr
(
const label k,
scalarRectangularMatrix& table,
scalarField& last
) const
{
label l=last.size();
for (label j = k - 1; j > 0; j--)
{
for (label i=0; i<l; i++)
{
table[j-1][i] =
table[j][i] + coeff_[k][j]*(table[j][i] - table[j-1][i]);
}
}
for (label i = 0; i < l; i++)
{
last[i] = table[0][i] + coeff_[k][0]*(table[0][i] - last[i]);
}
}
// ************************************************************************* //

View File

@ -28,7 +28,7 @@ Description
An extrapolation-algorithm, based on the linearly implicit Euler method
with step size control and order selection.
The implementation is based on the SEULEX code in
The implementation is based on the SEULEX algorithm in
\verbatim
"Solving Ordinary Differential Equations II: Stiff
and Differential-Algebraic Problems, second edition",
@ -47,8 +47,6 @@ SourceFiles
#define seulex_H
#include "ODESolver.H"
#include "scalarFieldField.H"
#include "scalarMatrices.H"
#include "labelField.H"
@ -65,64 +63,65 @@ class seulex
:
public ODESolver
{
// Private data
//- seulex constants
static const scalar EPS;
// Static constants
static const label KMAXX=12, IMAXX = KMAXX + 1;
static const label kMaxx_ = 12;
static const label iMaxx_ = kMaxx_ + 1;
static const scalar
STEPFAC1, STEPFAC2, STEPFAC3, STEPFAC4, STEPFAC5, KFAC1, KFAC2;
stepFactor1_, stepFactor2_, stepFactor3_,
stepFactor4_, stepFactor5_,
kFactor1_, kFactor2_;
// Evaluated constants
//- Reference to ODESystem
const ODESystem& ode_;
scalar jacRedo_;
labelField nSeq_;
scalarField cpu_;
scalarSquareMatrix coeff_;
// Temporary fields
// Temporary storage
// held to avoid dynamic memory allocation between calls
// and to transfer internal values between functions
mutable scalar theta_;
mutable label kTarg_;
mutable labelField nSeq_;
mutable scalarField cost_, dfdx_, factrl_;
mutable scalarRectangularMatrix table_, fSave_;
mutable scalarRectangularMatrix table_;
mutable scalarField dfdx_;
mutable scalarSquareMatrix dfdy_;
mutable scalar jacRedo_, theta_;
mutable bool calcJac_, dense_;
mutable scalarSquareMatrix a_, coeff_;
mutable scalar hnext_, hdid_;
mutable scalarSquareMatrix a_;
mutable labelList pivotIndices_;
// Fields space for "step" function
mutable scalarField hOpt_ ,work_, ySaved_, ySequence_, scale_;
// Fields space for "solve" function
mutable scalarField dxOpt_, temp_;
mutable scalarField y0_, ySequence_, scale_;
// Fields used in "dy" function
mutable scalarField del_, yTemp_, dyTemp_, delTemp_;
// Fields used in "seul" function
mutable scalarField dy_, yTemp_, dydx_;
// Private Member Functions
void step(const scalar& htry, scalar& x, scalarField& y) const;
bool dy
//- Computes the j-th line of the extrapolation table
bool seul
(
const scalar& x,
scalarField& y,
const scalar htot,
const scalar x0,
const scalarField& y0,
const scalar dxTot,
const label k,
scalarField& yend,
label& ipt,
scalarField& scale
scalarField& y,
const scalarField& scale
) const;
void polyextr
//- Polynomial extrpolation
void extrapolate
(
const label k,
scalarRectangularMatrix& table,
scalarField& last
scalarField& y
) const;
@ -139,12 +138,13 @@ public:
// Member Functions
//- Solve the ODE system and the update the state
void solve
(
const ODESystem& ode,
scalar& x,
scalarField& y,
scalar& dxTry
stepState& step
) const;
};

View File

@ -6,15 +6,16 @@ EXE_INC = \
-I$(LIB_SRC)/sampling/lnInclude \
-I$(LIB_SRC)/transportModels \
-I$(LIB_SRC)/turbulenceModels \
-I$(LIB_SRC)/thermophysicalModels/basic/lnInclude
-I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
-I$(LIB_SRC)/surfMesh/lnInclude
LIB_LIBS = \
-lfiniteVolume \
-lmeshTools \
-lsurfMesh \
-llagrangian \
-lfileFormats \
-lsampling \
-lincompressibleTransportModels \
-lcompressibleTurbulenceModel \
-lincompressibleTurbulenceModel

View File

@ -72,8 +72,8 @@ void Foam::nearWallFields::calcAddressing()
label patchI = iter.key();
const fvPatch& patch = mesh.boundary()[patchI];
vectorField nf = patch.nf();
vectorField faceCellCentres = patch.patch().faceCellCentres();
vectorField nf(patch.nf());
vectorField faceCellCentres(patch.patch().faceCellCentres());
forAll(patch, patchFaceI)
{

View File

@ -70,14 +70,7 @@ void Foam::ode<ChemistryModel>::solve
cTp_[nSpecie] = T;
cTp_[nSpecie+1] = p;
odeSolver_->solve
(
*this,
0,
deltaT,
cTp_,
subDeltaT
);
odeSolver_->solve(0, deltaT, cTp_, subDeltaT);
for (register int i=0; i<nSpecie; i++)
{

View File

@ -8,4 +8,4 @@ ic8h18 : iso-Octane combustion, 874 species, 3796 reactions
Results interpreted in 'validation' sub-folder, where OpenFOAM results
are compared against those predicted by CHEMKIN II.
Overall the best performing ODE solver is seulex followed closely by rodas32.
Overall the best performing ODE solver is seulex followed closely by rodas23.

View File

@ -33,7 +33,7 @@ EulerImplicitCoeffs
odeCoeffs
{
solver seulex; //rodas32;
solver seulex;
absTol 1e-12;
relTol 1e-1;
}

View File

@ -15,9 +15,9 @@ FoamFile
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
numberOfSubdomains 4;
numberOfSubdomains 8;
method hierarchical;
method scotch;
simpleCoeffs
{