SIBS.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "SIBS.H"
28 
29 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
30 
31 namespace Foam
32 {
33  defineTypeNameAndDebug(SIBS, 0);
34  addToRunTimeSelectionTable(ODESolver, SIBS, dictionary);
35 
36  const label SIBS::nSeq_[iMaxX_] = {2, 6, 10, 14, 22, 34, 50, 70};
37 
38  const scalar
39  SIBS::safe1 = 0.25,
40  SIBS::safe2 = 0.7,
41  SIBS::redMax = 1.0e-5,
42  SIBS::redMin = 0.7,
43  SIBS::scaleMX = 0.1;
44 }
45 
46 
47 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
48 
50 :
51  ODESolver(ode, dict),
52  a_(iMaxX_, 0.0),
53  alpha_(kMaxX_, 0.0),
54  d_p_(n_, kMaxX_, 0.0),
55  x_p_(kMaxX_, 0.0),
56  err_(kMaxX_, 0.0),
57 
58  yTemp_(n_, 0.0),
59  ySeq_(n_, 0.0),
60  yErr_(n_, 0.0),
61  dydx0_(n_),
62  dfdx_(n_, 0.0),
63  dfdy_(n_, 0.0),
64  first_(1),
65  epsOld_(-1.0)
66 {}
67 
68 
69 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
70 
72 (
73  scalar& x,
74  scalarField& y,
75  scalar& dxTry
76 ) const
77 {
78  odes_.derivatives(x, y, dydx0_);
79 
80  scalar h = dxTry;
81  bool exitflag = false;
82 
83  if (relTol_[0] != epsOld_)
84  {
85  dxTry = xNew_ = -GREAT;
86  scalar eps1 = safe1*relTol_[0];
87  a_[0] = nSeq_[0] + 1;
88 
89  for (label k=0; k<kMaxX_; k++)
90  {
91  a_[k + 1] = a_[k] + nSeq_[k + 1];
92  }
93 
94  for (label iq = 1; iq<kMaxX_; iq++)
95  {
96  for (label k=0; k<iq; k++)
97  {
98  alpha_[k][iq] =
99  pow(eps1, (a_[k + 1] - a_[iq + 1])
100  /((a_[iq + 1] - a_[0] + 1.0)*(2*k + 3)));
101  }
102  }
103 
104  epsOld_ = relTol_[0];
105  a_[0] += n_;
106 
107  for (label k=0; k<kMaxX_; k++)
108  {
109  a_[k + 1] = a_[k] + nSeq_[k + 1];
110  }
111 
112  for (kOpt_ = 1; kOpt_<kMaxX_ - 1; kOpt_++)
113  {
114  if (a_[kOpt_ + 1] > a_[kOpt_]*alpha_[kOpt_ - 1][kOpt_])
115  {
116  break;
117  }
118  }
119 
120  kMax_ = kOpt_;
121  }
122 
123  label k = 0;
124  yTemp_ = y;
125 
126  odes_.jacobian(x, y, dfdx_, dfdy_);
127 
128  if (x != xNew_ || h != dxTry)
129  {
130  first_ = 1;
131  kOpt_ = kMax_;
132  }
133 
134  label km=0;
135  label reduct=0;
136  scalar maxErr = SMALL;
137 
138  for (;;)
139  {
140  scalar red = 1.0;
141 
142  for (k=0; k <= kMax_; k++)
143  {
144  xNew_ = x + h;
145 
146  if (xNew_ == x)
147  {
149  << "step size underflow"
150  << exit(FatalError);
151  }
152 
153  SIMPR(x, yTemp_, dydx0_, dfdx_, dfdy_, h, nSeq_[k], ySeq_);
154  scalar xest = sqr(h/nSeq_[k]);
155 
156  polyExtrapolate(k, xest, ySeq_, y, yErr_, x_p_, d_p_);
157 
158  if (k != 0)
159  {
160  maxErr = SMALL;
161  for (label i=0; i<n_; i++)
162  {
163  maxErr = max
164  (
165  maxErr,
166  mag(yErr_[i])/(absTol_[i] + relTol_[i]*mag(yTemp_[i]))
167  );
168  }
169  km = k - 1;
170  err_[km] = pow(maxErr/safe1, 1.0/(2*km + 3));
171  }
172 
173  if (k != 0 && (k >= kOpt_ - 1 || first_))
174  {
175  if (maxErr < 1.0)
176  {
177  exitflag = true;
178  break;
179  }
180 
181  if (k == kMax_ || k == kOpt_ + 1)
182  {
183  red = safe2/err_[km];
184  break;
185  }
186  else if (k == kOpt_ && alpha_[kOpt_ - 1][kOpt_] < err_[km])
187  {
188  red = 1.0/err_[km];
189  break;
190  }
191  else if (kOpt_ == kMax_ && alpha_[km][kMax_ - 1] < err_[km])
192  {
193  red = alpha_[km][kMax_ - 1]*safe2/err_[km];
194  break;
195  }
196  else if (alpha_[km][kOpt_] < err_[km])
197  {
198  red = alpha_[km][kOpt_ - 1]/err_[km];
199  break;
200  }
201  }
202  }
203 
204  if (exitflag)
205  {
206  break;
207  }
208 
209  red = min(red, redMin);
210  red = max(red, redMax);
211  h *= red;
212  reduct = 1;
213  }
214 
215  x = xNew_;
216  first_ = 0;
217  scalar wrkmin = GREAT;
218  scalar scale = 1.0;
219 
220  for (label kk=0; kk<=km; kk++)
221  {
222  scalar fact = max(err_[kk], scaleMX);
223  scalar work = fact*a_[kk + 1];
224  if (work < wrkmin)
225  {
226  scale = fact;
227  wrkmin = work;
228  kOpt_ = kk + 1;
229  }
230  }
231 
232  dxTry = h/scale;
233 
234  if (kOpt_ >= k && kOpt_ != kMax_ && !reduct)
235  {
236  scalar fact = max(scale/alpha_[kOpt_ - 1][kOpt_], scaleMX);
237  if (a_[kOpt_ + 1]*fact <= wrkmin)
238  {
239  dxTry = h/fact;
240  kOpt_++;
241  }
242  }
243 }
244 
245 
246 // ************************************************************************* //
dictionary dict
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Abstract base class for the systems of ordinary differential equations.
Definition: ODESystem.H:46
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
error FatalError
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:137
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
dimensionedSymmTensor sqr(const dimensionedVector &dv)
label k
Boltzmann constant.
An ODE solver for chemistry.
Definition: ode.H:50
Macros for easy insertion into run-time selection tables.
virtual void jacobian(const scalar x, const scalarField &y, scalarField &dfdx, scalarSquareMatrix &dfdy) const =0
Calculate the Jacobian of the system.
scalar y
const ODESystem & odes_
Reference to ODESystem.
Definition: ODESolver.H:58
addToRunTimeSelectionTable(ensightPart, ensightPartCells, istream)
defineTypeNameAndDebug(combustionModel, 0)
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
const dimensionedScalar h
Planck constant.
Definition: createFields.H:6
SIBS(const ODESystem &ode, const dictionary &dict)
Construct from ODE.
Definition: SIBS.C:49
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
scalarField relTol_
Relative convergence tolerance per step.
Definition: ODESolver.H:67
Abstract base-class for ODE system solvers.
Definition: ODESolver.H:50
scalarField absTol_
Absolute convergence tolerance per step.
Definition: ODESolver.H:64
dimensioned< scalar > mag(const dimensioned< Type > &)
void solve(scalar &x, scalarField &y, scalar &dxTry) const
Solve the ODE system as far as possible upto dxTry.
Definition: SIBS.C:72
label n_
Size of the ODESystem.
Definition: ODESolver.H:61
virtual void derivatives(const scalar x, const scalarField &y, scalarField &dydx) const =0
Calculate the derivatives in dydx.
Namespace for OpenFOAM.