chemPointISAT.H
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2016-2020 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 Class
25  Foam::chemPointISAT
26 
27 Description
28  Leaf of the binary tree.
29  The chemPoint stores the composition 'phi', the mapping of this
30  composition Rphi, the mapping gradient matrix A and the matrix describing
31  the Ellipsoid Of Accuracy (EOA).
32 
33  1) When the chemPoint is created the region of accuracy is approximated by
34  an ellipsoid E centered in 'phi' (obtained with the constant):
35  E = {x| ||L^T.(x-phi)|| <= 1},
36  with x a point in the composition space and L^T the transpose of an
37  upper triangular matrix describing the EOA (see below: "Computation of
38  L" ).
39 
40  2) To RETRIEVE the mapping from the chemPoint phi, the query point phiq has
41  to be in the EOA of phi. It follows that, dphi=phiq-phi and to test if
42  phiq is in the ellipsoid there are two methods. First, compare
43  r=||dphi|| with rmin and rmax. If r < rmin, phiq is in the EOA. If r >
44  rmax, phiq is out of the EOA. This operations is O(completeSpaceSize)
45  and is performed first. If rmin < r < rmax, then the second method is
46  used:
47  ||L^T.dphi|| <= 1 to be in the EOA.
48  If phiq is in the EOA, Rphiq is obtained by linear interpolation:
49  Rphiq= Rphi + A.dphi.
50 
51  3) If phiq is not in the EOA, then the mapping is computed. But as the EOA
52  is a conservative approximation of the region of accuracy surrounding
53  the point phi, we could expand it by comparing the computed results with
54  the one obtained by linear interpolation. The error epsGrow is
55  calculated:
56  epsGrow = ||B.(dR - dRl)||,
57  with dR = Rphiq - Rphi, dRl = A.dphi and B the diagonal scale factor
58  matrix. If epsGrow <= tolerance, the EOA is too conservative and a GROW
59  is performed otherwise, the newly computed mapping is associated to the
60  initial composition and added to the tree.
61 
62  4) To GROW the EOA, we expand it to include the previous EOA and the query
63  point phiq. The rank-one matrix method is used. The EOA is transformed
64  to a hypersphere centered at the origin. Then it is expanded to include
65  the transformed point phiq' on its boundary. Then the inverse
66  transformation give the modified matrix L' (see below: "Grow the EOA").
67 
68 
69  Computation of L :
70  In [1], the EOA of the constant approximation is given by
71  E = {x| ||B.A/tolerance.(x-phi)|| <= 1},
72 
73  with B a scale factor diagonal matrix, A the mapping gradient matrix and
74  tolerance the absolute tolerance. If we take the QR decomposition of
75  (B.A)/tolerance= Q.R, with Q an orthogonal matrix and R an upper
76  triangular matrix such that the EOA is described by
77  (phiq-phi0)^T.R^T.R.(phiq-phi0) <= 1
78  L^T = R, both Cholesky decomposition of A^T.B^T.B.A/tolerance^2
79  This representation of the ellipsoid is used in [2] and in order to avoid
80  large value of semi-axe length in certain direction, a Singular Value
81  Decomposition (SVD) is performed on the L matrix:
82  L = UDV^T,
83  with the orthogonal matrix U giving the directions of the principal axes
84  and 1/di the inverse of the element of the diagonal matrix D giving the
85  length of the principal semi-axes. To avoid very large value of those
86  length, di' = max(di, 1/(alphaEOA*sqrt(tolerance))), with alphaEOA = 0.1
87  (see [2]) di' = max(di, 1/2), see [1]. The latter will be used in this
88  implementation. And L' = UD'V^T, with D' the diagonal matrix with the
89  modified di'.
90 
91  Grow the EOA :
92  More details about the minimum-volume ellipsoid covering an ellipsoid E
93  and a point p are found in [3]. Here is the main steps to obtain the
94  modified matrix L' describing the new ellipsoid.
95 
96  1) calculate the point p' in the transformed space :
97  p' = L^T.(p-phi)
98  2) compute the rank-one decomposition:
99  G = I + gamma.p'.p'^T,
100  with gamma = (1/|p'|-1)*1/|p'|^2
101  3) compute L':
102  L' = L.G.
103 
104  References:
105  \verbatim
106  [1] Pope, S. B. (1997).
107  Computationally efficient implementation of combustion chemistry using
108  in situ adaptive tabulation.
109  Combustion Theory and Modelling, 1, 41-63.
110 
111  [2] Lu, L., & Pope, S. B. (2009).
112  An improved algorithm for in situ adaptive tabulation.
113  Journal of Computational Physics, 228(2), 361-386.
114 
115  [3] Pope, S. B. (2008).
116  Algorithms for ellipsoids.
117  Cornell University Report No. FDA, 08-01.
118  \endverbatim
119 
120 \*---------------------------------------------------------------------------*/
121 
122 #ifndef chemPointISAT_H
123 #define chemPointISAT_H
124 
125 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
126 
127 namespace Foam
128 {
129 
130 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
131 
132 template<class CompType, class ThermoType>
133 class binaryNode;
134 
135 template<class CompType, class ThermoType>
136 class TDACChemistryModel;
137 
138 
139 /*---------------------------------------------------------------------------*\
140  Class chemPointISAT Declaration
141 \*---------------------------------------------------------------------------*/
142 
143 template<class CompType, class ThermoType>
144 class chemPointISAT
145 {
146  // Private Data
147 
148  //- Pointer to the chemistryModel object
150 
151  //- Vector storing the composition, temperature and pressure
152  // and deltaT if a variable time step is set on
153  scalarField phi_;
154 
155  //- Vector storing the mapping of the composition phi
156  scalarField Rphi_;
157 
158  //- LT the transpose of the L matrix describing the Ellipsoid Of
159  // Accuracy use List of Lists to be able to change size if DAC is used
160  scalarSquareMatrix LT_;
161 
162  //- A the mapping gradient matrix
164 
165  //- Vector storing the scale factor
166  scalarField scaleFactor_;
167 
168  //- Reference to the node in the binary tree holding this chemPoint
170 
171  //- The size of the composition space (size of the vector phi)
172  label completeSpaceSize_;
173 
174  //- Number of times the element has been grown
175  label nGrowth_;
176 
177  //- Tolerance for the Ellipsoid of accuracy
178  static scalar tolerance_;
179 
180  //- Number of active species stored in the chemPoint
181  label nActiveSpecies_;
182 
183  //- Vectors that store the index conversion between the simplified
184  // and the complete chemical mechanism
185  List<label> simplifiedToCompleteIndex_;
186 
187  label timeTag_;
188  label lastTimeUsed_;
189 
190  bool toRemove_;
191 
192  label maxNumNewDim_;
193 
194  Switch printProportion_;
195 
196  //- Variable to store the number of retrieves the chemPoint
197  // will generate at each time step
198  label numRetrieve_;
199 
200  //- Variable to store the number of time steps the chempoint is allowed
201  // to still live according to the maxChPLifeTime_ parameter
202  label nLifeTime_;
203 
204  List<label> completeToSimplifiedIndex_;
205 
206  //- Number of equations in addition to the species eqs.
207  label nAdditionalEqns_;
208 
209  label idT_;
210  label idp_;
211  label iddeltaT_;
212 
213  //- QR decomposition of a matrix
214  // Input : nCols cols number
215  // R the matrix to decompose
216  // QT an empty matrix that stores the transpose of the Q matrix
217  // R is returned in the given R matrix
218  // which is used to store the ellipsoid of accuracy
219  void qrDecompose
220  (
221  const label nCols,
223  );
224 
225  //- QR update of the matrix A
226  void qrUpdate
227  (
229  const label n,
230  const scalarField& u,
231  const scalarField& v
232  );
233 
234  void rotate
235  (
237  const label i,
238  const scalar a,
239  const scalar b,
240  label n
241  );
242 
243 
244 public:
245 
246  // Constructors
247 
248  //- Construct from components
250  (
252  const scalarField& phi,
253  const scalarField& Rphi,
254  const scalarSquareMatrix& A,
255  const scalarField& scaleFactor,
256  const scalar& tolerance,
257  const label& completeSpaceSize,
258  const dictionary& coeffsDict,
260  );
261 
262  //- Construct from another chemPoint and reference to a binary node
264  (
267  );
268 
269  //- Construct from another chemPoint
271  (
273  );
274 
275 
276  // Member Functions
277 
278  //- Access to the TDACChemistryModel
280  {
281  return chemistry_;
282  }
284  inline label nGrowth()
285  {
286  return nGrowth_;
287  }
289  inline label& completeSpaceSize()
290  {
291  return completeSpaceSize_;
292  }
294  inline const scalarField& phi() const
295  {
296  return phi_;
297  }
299  inline const scalarField& Rphi() const
300  {
301  return Rphi_;
302  }
304  inline const scalarField& scaleFactor()
305  {
306  return scaleFactor_;
307  }
309  inline const scalar& tolerance()
310  {
311  return tolerance_;
312  }
314  static void changeTolerance(scalar newTol)
315  {
316  tolerance_ = newTol;
317  }
320  {
321  return node_;
322  }
324  inline const scalarSquareMatrix& A() const
325  {
326  return A_;
327  }
329  inline scalarSquareMatrix& A()
330  {
331  return A_;
332  }
334  inline const scalarSquareMatrix& LT() const
335  {
336  return LT_;
337  }
339  inline scalarSquareMatrix& LT()
340  {
341  return LT_;
342  }
344  inline label nActiveSpecies()
345  {
346  return nActiveSpecies_;
347  }
350  {
351  return completeToSimplifiedIndex_;
352  }
355  {
356  return simplifiedToCompleteIndex_;
357  }
358 
359  //- Increases the number of retrieves the chempoint has generated
360  void increaseNumRetrieve();
361 
362  //- Resets the number of retrieves at each time step
363  void resetNumRetrieve();
364 
365  //- Increases the "counter" of the chP life
366  void increaseNLifeTime();
367 
370  inline const label& timeTag()
371  {
372  return timeTag_;
373  }
375  inline label& lastTimeUsed()
376  {
377  return lastTimeUsed_;
378  }
380  inline bool& toRemove()
381  {
382  return toRemove_;
383  }
385  inline label& maxNumNewDim()
386  {
387  return maxNumNewDim_;
388  }
390  inline const label& numRetrieve()
391  {
392  return numRetrieve_;
393  }
395  inline const label& nLifeTime()
396  {
397  return nLifeTime_;
398  }
400  inline bool variableTimeStep() const
401  {
402  return chemistry_.variableTimeStep();
403  }
404 
405  // ISAT functions
406 
407  //- To RETRIEVE the mapping from the stored chemPoint phi, the query
408  // point phiq has to be in the EOA of phi.
409  // To test if phiq is in the ellipsoid:
410  // ||L^T.dphi|| <= 1
411  bool inEOA(const scalarField& phiq);
412 
413  //- More details about the minimum-volume ellipsoid covering an
414  // ellipsoid E and a point p are found in [1].
415  // Here is the main steps to obtain the
416  // modified matrix L' describing the new ellipsoid.
417  // 1) calculate the point p' in the transformed space :
418  // p' = L^T.(p-phi)
419  // 2) compute the rank-one decomposition:
420  // G = I + gamma.p'.p'^T,
421  // with gamma = (1/|p'|-1)*1/|p'|^2
422  // 3) compute L':
423  // L'L'^T = (L.G)(L.G)^T,
424  // L'^T is then obtained by QR decomposition of (L.G)^T = G^T.L^T
425  // [1] Stephen B. Pope, "Algorithms for ellipsoids", FDA 08-01,
426  // Cornell University, 2008
427  bool grow(const scalarField& phiq);
428 
429  //- If phiq is not in the EOA, then the mapping is computed.
430  // But as the EOA is a conservative approximation of the region of
431  // accuracy surrounding the point phi, we could expand it by
432  // comparing the computed results with the one obtained by linear
433  // interpolation. The error eps is calculated:
434  // eps = ||B.(dR - dRl)||,
435  // with dR = Rphiq - Rphi, dRl = A.dphi and B the diagonal scale
436  // factor matrix.
437  // If eps <= tolerance, the EOA is too conservative and a GROW is
438  // performed,
439  // otherwise, the newly computed mapping is associated to the
440  // initial composition and added to the tree.
441  bool checkSolution
442  (
443  const scalarField& phiq,
444  const scalarField& Rphiq
445  );
446 };
447 
448 
449 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
450 
451 } // End namespace Foam
452 
453 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
454 
455 #ifdef NoRepository
456  #include "chemPointISAT.C"
457 #endif
458 
459 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
460 
461 #endif
462 
463 // ************************************************************************* //
chemPointISAT(TDACChemistryModel< CompType, ThermoType > &chemistry, const scalarField &phi, const scalarField &Rphi, const scalarSquareMatrix &A, const scalarField &scaleFactor, const scalar &tolerance, const label &completeSpaceSize, const dictionary &coeffsDict, binaryNode< CompType, ThermoType > *node=nullptr)
Construct from components.
const scalar & tolerance()
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
const scalarSquareMatrix & A() const
const scalarSquareMatrix & LT() const
List< label > & simplifiedToCompleteIndex()
binaryNode< CompType, ThermoType > *& node()
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:158
bool checkSolution(const scalarField &phiq, const scalarField &Rphiq)
If phiq is not in the EOA, then the mapping is computed.
Leaf of the binary tree. The chemPoint stores the composition &#39;phi&#39;, the mapping of this composition ...
List< label > & completeToSimplifiedIndex()
A simple wrapper around bool so that it can be read as a word: true/false, on/off, yes/no, y/n, t/f, or none/any.
Definition: Switch.H:60
const label & timeTag()
const label & nLifeTime()
const dimensionedScalar & b
Wien displacement law constant: default SI units: [m K].
Definition: createFields.H:27
const scalarField & scaleFactor()
const label & numRetrieve()
bool grow(const scalarField &phiq)
More details about the minimum-volume ellipsoid covering an.
Node of the binary tree.
Definition: binaryNode.H:49
const scalarField & phi() const
bool variableTimeStep() const
TDACChemistryModel< CompType, ThermoType > & chemistry()
Access to the TDACChemistryModel.
bool variableTimeStep() const
Return true if the time-step is variable and/or non-uniform.
const scalarField & Rphi() const
void resetNumRetrieve()
Resets the number of retrieves at each time step.
#define R(A, B, C, D, E, F, K, M)
void increaseNLifeTime()
Increases the "counter" of the chP life.
label & completeSpaceSize()
void increaseNumRetrieve()
Increases the number of retrieves the chempoint has generated.
bool inEOA(const scalarField &phiq)
To RETRIEVE the mapping from the stored chemPoint phi, the query.
label n
volScalarField & p
static void changeTolerance(scalar newTol)
Namespace for OpenFOAM.