binaryTreeI.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-2022 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 "demandDrivenData.H"
27 
28 // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
29 
30 inline void Foam::binaryTree::insertNode
31 (
32  chemPointISAT*& phi0,
33  binaryNode*& newNode
34 )
35 {
36  if (phi0 == phi0->node()->leafRight())// phi0 is on the right
37  {
38  phi0->node()->leafRight() = nullptr;
39  phi0->node()->nodeRight() = newNode;
40  return;
41  }
42  else if (phi0 == phi0->node()->leafLeft())// phi0 is on the left
43  {
44  phi0->node()->leafLeft() = nullptr;
45  phi0->node()->nodeLeft() = newNode;
46  return;
47 
48  }
49 
50  // if we reach this point, there is an issue with the addressing
52  << "trying to insert a node with a wrong pointer to a chemPoint"
53  << exit(FatalError);
54 }
55 
56 
57 inline void Foam::binaryTree::deleteSubTree(binaryNode* subTreeRoot)
58 {
59  if (subTreeRoot != nullptr)
60  {
61  deleteDemandDrivenData(subTreeRoot->leafLeft());
62  deleteDemandDrivenData(subTreeRoot->leafRight());
63  deleteSubTree(subTreeRoot->nodeLeft());
64  deleteSubTree(subTreeRoot->nodeRight());
65  deleteDemandDrivenData(subTreeRoot);
66  }
67 }
68 
69 
70 inline void Foam::binaryTree::deleteSubTree()
71 {
72  deleteSubTree(root_);
73 }
74 
75 
76 inline void Foam::binaryTree::transplant(binaryNode* u, binaryNode* v)
77 {
78  if (v != nullptr)
79  {
80  // u is root_
81  if (u->parent() == nullptr)
82  {
83  root_ = v;
84  }
85  // u is on the left of its parent
86  else if (u == u->parent()->nodeLeft())
87  {
88  u->parent()->nodeLeft() = v;
89  }
90  // u is ont the right of its parent
91  else if (u == u->parent()->nodeRight())
92  {
93  u->parent()->nodeRight() = v;
94  }
95  else
96  {
98  << "wrong addressing of the initial node"
99  << exit(FatalError);
100  }
101  v->parent() = u->parent();
102  }
103  else
104  {
106  << "trying to transplant a nullptr node"
107  << exit(FatalError);
108  }
109 }
110 
111 
112 inline Foam::chemPointISAT* Foam::binaryTree::chemPSibling(binaryNode* y)
113 {
114  if (y->parent() != nullptr)
115  {
116  if (y == y->parent()->nodeLeft())// y is on the left, return right side
117  {
118  // might return nullptr if the right side is a node
119  return y->parent()->leafRight();
120  }
121  else if (y == y->parent()->nodeRight())
122  {
123  return y->parent()->leafLeft();
124  }
125  else
126  {
128  << "wrong addressing of the initial node"
129  << exit(FatalError);
130  return nullptr;
131  }
132  }
133 
134  // the binaryNode is root_ and has no sibling
135  return nullptr;
136 }
137 
138 
139 inline Foam::chemPointISAT* Foam::binaryTree::chemPSibling(chemPointISAT* x)
140 {
141  if (size_>1)
142  {
143  if (x == x->node()->leafLeft())
144  {
145  // x is on the left, return right side
146  // might return nullptr if the right side is a node
147  return x->node()->leafRight();
148  }
149  else if (x == x->node()->leafRight())
150  {
151  // x is on the right, return left side
152  return x->node()->leafLeft();
153  }
154  else
155  {
157  << "wrong addressing of the initial leaf"
158  << exit(FatalError);
159  return nullptr;
160  }
161  }
162 
163  // there is only one leaf attached to the root_, no sibling
164  return nullptr;
165 }
166 
167 
168 inline Foam::binaryNode* Foam::binaryTree::nodeSibling(binaryNode* y)
169 {
170  if (y->parent()!=nullptr)
171  {
172  if (y == y->parent()->nodeLeft())
173  {
174  // y is on the left, return right side
175  return y->parent()->nodeRight();
176  }
177  else if (y == y->parent()->nodeRight())
178  {
179  return y->parent()->nodeLeft();
180  }
181  else
182  {
184  << "wrong addressing of the initial node"
185  << exit(FatalError);
186  return nullptr;
187  }
188  }
189  return nullptr;
190 }
191 
192 
193 Foam::binaryNode* Foam::binaryTree::nodeSibling(chemPointISAT* x)
194 {
195  if (size_>1)
196  {
197  if (x == x->node()->leafLeft())
198  {
199  // x is on the left, return right side
200  return x->node()->nodeRight();
201  }
202  else if (x == x->node()->leafRight())
203  {
204  // x is on the right, return left side
205  return x->node()->nodeLeft();
206  }
207  else
208  {
210  << "wrong addressing of the initial leaf"
211  << exit(FatalError);
212  return nullptr;
213  }
214  }
215  return nullptr;
216 }
217 
218 
219 inline void Foam::binaryTree::deleteAllNode(binaryNode* subTreeRoot)
220 {
221  if (subTreeRoot != nullptr)
222  {
223  deleteAllNode(subTreeRoot->nodeLeft());
224  deleteAllNode(subTreeRoot->nodeRight());
225  deleteDemandDrivenData(subTreeRoot);
226  }
227 }
228 
229 
230 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
231 
233 {
234  return size_;
235 }
236 
237 
239 {
240  // when we reach the leaf, we return 0
241  if (subTreeRoot == nullptr)
242  {
243  return 0;
244  }
245  else
246  {
247  return
248  1
249  + max
250  (
251  depth(subTreeRoot->nodeLeft()),
252  depth(subTreeRoot->nodeRight())
253  );
254  }
255 }
256 
257 
259 {
260  return depth(root_);
261 }
262 
263 
265 {
266  return root_;
267 }
268 
269 
271 {
272  return maxNLeafs_;
273 }
274 
275 
277 (
278  const scalarField& phiq,
279  binaryNode* node,
280  chemPointISAT*& nearest
281 )
282 {
283  if (size_ > 1)
284  {
285  scalar vPhi=0.0;
286  const scalarField& v = node->v();
287  const scalar& a = node->a();
288  // compute v*phi
289  for (label i=0; i<phiq.size(); i++) vPhi += phiq[i]*v[i];
290 
291 
292  if (vPhi > a) // on right side (side of the newly added point)
293  {
294  if (node->nodeRight()!=nullptr)
295  {
296  binaryTreeSearch(phiq, node->nodeRight(), nearest);
297  }
298  else // the terminal node is reached, store leaf on the right
299  {
300  nearest = node->leafRight();
301  return;
302  }
303  }
304  else // on left side (side of the previously stored point)
305  {
306  if (node->nodeLeft()!=nullptr)
307  {
308  binaryTreeSearch(phiq, node->nodeLeft(), nearest);
309  }
310  else // the terminal node is reached, return element on right
311  {
312  nearest = node->leafLeft();
313  return;
314  }
315  }
316  }
317  // only one point stored (left element of the root)
318  else if (size_ == 1)
319  {
320  nearest = root_->leafLeft();
321  }
322  else // no point stored
323  {
324  nearest = nullptr;
325  }
326 }
327 
328 
330 {
331  if (subTreeRoot!=nullptr)
332  {
333  while(subTreeRoot->nodeLeft() != nullptr)
334  {
335  subTreeRoot = subTreeRoot->nodeLeft();
336  }
337  return subTreeRoot->leafLeft();
338  }
339  else
340  {
341  return nullptr;
342  }
343 }
344 
345 
347 {
348  // Recursively delete the element in the subTree
349  deleteSubTree();
350 
351  // Reset root node (should already be nullptr)
352  root_ = nullptr;
353 
354  // Reset size_
355  size_ = 0;
356 }
357 
358 
360 {
361  return size_ >= maxNLeafs_;
362 }
363 
364 
366 {
367  // Has to go along each chemPointISAT of the tree
368  if (size_ > 0)
369  {
370  // First finds the first leaf
371  chemPointISAT* chP0 = treeMin();
372  chP0->resetNumRetrieve();
373 
374  // Then go to each successor
375  chemPointISAT* nextChP = treeSuccessor(chP0);
376  while (nextChP != nullptr)
377  {
378  nextChP->resetNumRetrieve();
379  nextChP = treeSuccessor(nextChP);
380  }
381  }
382 }
383 
384 
385 // ************************************************************************* //
scalar y
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
Node of the binary tree.
Definition: binaryNode.H:49
chemPointISAT *& leafLeft()
Access.
Definition: binaryNode.H:138
const scalarField & v() const
Topology.
Definition: binaryNode.H:165
binaryNode *& nodeRight()
Definition: binaryNode.H:153
chemPointISAT *& leafRight()
Definition: binaryNode.H:143
binaryNode *& nodeLeft()
Definition: binaryNode.H:148
const scalar & a() const
Definition: binaryNode.H:170
void resetNumRetrieve()
Definition: binaryTreeI.H:365
binaryNode * root()
Definition: binaryTreeI.H:264
chemPointISAT * treeMin()
Definition: binaryTree.H:205
bool isFull()
ListFull.
Definition: binaryTreeI.H:359
label size() const
Member functions.
Definition: binaryTreeI.H:232
void binaryTreeSearch(const scalarField &phiq, binaryNode *node, chemPointISAT *&nearest)
Definition: binaryTreeI.H:277
void deleteAllNode()
Definition: binaryTree.H:198
label maxNLeafs() const
Definition: binaryTreeI.H:270
void clear()
Removes every entries of the tree and delete the associated objects.
Definition: binaryTreeI.H:346
label depth() const
Definition: binaryTreeI.H:258
Leaf of the binary tree. The chemPoint stores the composition 'phi', the mapping of this composition ...
void resetNumRetrieve()
Resets the number of retrieves at each time step.
Template functions to aid in the implementation of demand driven data.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
const dimensionedScalar phi0
Magnetic flux quantum: default SI units: [Wb].
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
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
void deleteDemandDrivenData(DataPtr &dataPtr)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
error FatalError