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  if (ODESolver::resize())
74  {
75  resizeField(yTemp_);
76  resizeField(ySeq_);
77  resizeField(yErr_);
78  resizeField(dydx0_);
79  resizeField(dfdx_);
80  resizeMatrix(dfdy_);
81 
82  return true;
83  }
84  else
85  {
86  return false;
87  }
88 }
89 
90 
92 (
93  scalar& x,
94  scalarField& y,
95  scalar& dxTry
96 ) const
97 {
98  odes_.derivatives(x, y, dydx0_);
99 
100  scalar h = dxTry;
101  bool exitflag = false;
102 
103  if (relTol_[0] != epsOld_)
104  {
105  dxTry = xNew_ = -GREAT;
106  scalar eps1 = safe1*relTol_[0];
107  a_[0] = nSeq_[0] + 1;
108 
109  for (label k=0; k<kMaxX_; k++)
110  {
111  a_[k + 1] = a_[k] + nSeq_[k + 1];
112  }
113 
114  for (label iq = 1; iq<kMaxX_; iq++)
115  {
116  for (label k=0; k<iq; k++)
117  {
118  alpha_[k][iq] =
119  pow(eps1, (a_[k + 1] - a_[iq + 1])
120  /((a_[iq + 1] - a_[0] + 1.0)*(2*k + 3)));
121  }
122  }
123 
124  epsOld_ = relTol_[0];
125  a_[0] += n_;
126 
127  for (label k=0; k<kMaxX_; k++)
128  {
129  a_[k + 1] = a_[k] + nSeq_[k + 1];
130  }
131 
132  for (kOpt_ = 1; kOpt_<kMaxX_ - 1; kOpt_++)
133  {
134  if (a_[kOpt_ + 1] > a_[kOpt_]*alpha_[kOpt_ - 1][kOpt_])
135  {
136  break;
137  }
138  }
139 
140  kMax_ = kOpt_;
141  }
142 
143  label k = 0;
144  yTemp_ = y;
145 
146  odes_.jacobian(x, y, dfdx_, dfdy_);
147 
148  if (x != xNew_ || h != dxTry)
149  {
150  first_ = 1;
151  kOpt_ = kMax_;
152  }
153 
154  label km=0;
155  label reduct=0;
156  scalar maxErr = SMALL;
157 
158  for (;;)
159  {
160  scalar red = 1.0;
161 
162  for (k=0; k <= kMax_; k++)
163  {
164  xNew_ = x + h;
165 
166  if (xNew_ == x)
167  {
169  << "step size underflow"
170  << exit(FatalError);
171  }
172 
173  SIMPR(x, yTemp_, dydx0_, dfdx_, dfdy_, h, nSeq_[k], ySeq_);
174  scalar xest = sqr(h/nSeq_[k]);
175 
176  polyExtrapolate(k, xest, ySeq_, y, yErr_, x_p_, d_p_);
177 
178  if (k != 0)
179  {
180  maxErr = SMALL;
181  for (label i=0; i<n_; i++)
182  {
183  maxErr = max
184  (
185  maxErr,
186  mag(yErr_[i])/(absTol_[i] + relTol_[i]*mag(yTemp_[i]))
187  );
188  }
189  km = k - 1;
190  err_[km] = pow(maxErr/safe1, 1.0/(2*km + 3));
191  }
192 
193  if (k != 0 && (k >= kOpt_ - 1 || first_))
194  {
195  if (maxErr < 1.0)
196  {
197  exitflag = true;
198  break;
199  }
200 
201  if (k == kMax_ || k == kOpt_ + 1)
202  {
203  red = safe2/err_[km];
204  break;
205  }
206  else if (k == kOpt_ && alpha_[kOpt_ - 1][kOpt_] < err_[km])
207  {
208  red = 1.0/err_[km];
209  break;
210  }
211  else if (kOpt_ == kMax_ && alpha_[km][kMax_ - 1] < err_[km])
212  {
213  red = alpha_[km][kMax_ - 1]*safe2/err_[km];
214  break;
215  }
216  else if (alpha_[km][kOpt_] < err_[km])
217  {
218  red = alpha_[km][kOpt_ - 1]/err_[km];
219  break;
220  }
221  }
222  }
223 
224  if (exitflag)
225  {
226  break;
227  }
228 
229  red = min(red, redMin);
230  red = max(red, redMax);
231  h *= red;
232  reduct = 1;
233  }
234 
235  x = xNew_;
236  first_ = 0;
237  scalar wrkmin = GREAT;
238  scalar scale = 1.0;
239 
240  for (label kk=0; kk<=km; kk++)
241  {
242  scalar fact = max(err_[kk], scaleMX);
243  scalar work = fact*a_[kk + 1];
244  if (work < wrkmin)
245  {
246  scale = fact;
247  wrkmin = work;
248  kOpt_ = kk + 1;
249  }
250  }
251 
252  dxTry = h/scale;
253 
254  if (kOpt_ >= k && kOpt_ != kMax_ && !reduct)
255  {
256  scalar fact = max(scale/alpha_[kOpt_ - 1][kOpt_], scaleMX);
257  if (a_[kOpt_ + 1]*fact <= wrkmin)
258  {
259  dxTry = h/fact;
260  kOpt_++;
261  }
262  }
263 }
264 
265 
266 // ************************************************************************* //
dictionary dict
virtual void solve(scalar &x, scalarField &y, scalar &dxTry) const
Solve the ODE system as far as possible upto dxTry.
Definition: SIBS.C:92
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
virtual bool resize()=0
Resize the ODE solver.
Definition: ODESolver.C:89
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
void resizeMatrix(scalarSquareMatrix &m) const
Definition: ODESolverI.H:61
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 > &)
SIBS(const ODESystem &ode, const dictionary &dict)
Construct from ODE system.
Definition: SIBS.C:49
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
volScalarField & h
Planck constant.
scalarField relTol_
Relative convergence tolerance per step.
Definition: ODESolver.H:70
Abstract base-class for ODE system solvers.
Definition: ODESolver.H:50
scalarField absTol_
Absolute convergence tolerance per step.
Definition: ODESolver.H:67
dimensioned< scalar > mag(const dimensioned< Type > &)
static void resizeField(UList< Type > &f, const label n)
Definition: ODESolverI.H:48
virtual bool resize()
Resize the ODE solver.
Definition: SIBS.C:71
label n_
Size of the ODESystem (adjustable)
Definition: ODESolver.H:64
virtual void derivatives(const scalar x, const scalarField &y, scalarField &dydx) const =0
Calculate the derivatives in dydx.
Namespace for OpenFOAM.