labelRanges.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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011 OpenFOAM Foundation
9  Copyright (C) 2017-2020 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "labelRanges.H"
30 #include "ListOps.H"
31 
32 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
33 
34 namespace Foam
35 {
36 
37  // Print range for debugging purposes
39  {
40  if (range.empty())
41  {
42  os << "empty";
43  }
44  else
45  {
46  os << range << " = " << range.first() << ":" << range.last();
47  }
48  return os;
49  }
50 
51 } // End namespace Foam
52 
53 
54 
55 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
56 
57 void Foam::labelRanges::insertBefore
58 (
59  const label insert,
60  const labelRange& range
61 )
62 {
63  auto& list = static_cast<StorageContainer&>(*this);
64 
65  // Insert via copying up
66  label nElem = list.size();
67 
69  {
70  Info<< "before insert "
71  << nElem << " elements, insert at " << insert << nl
72  << list << endl;
73  }
74 
75  list.resize(nElem+1);
76 
78  {
79  Info<< "copy between " << nElem << " and " << insert << nl;
80  }
81 
82  for (label i = nElem-1; i >= insert; --i)
83  {
85  {
86  Info<< "copy from " << (i) << " to " << (i+1) << nl;
87  }
88 
89  list[i+1] = list[i];
90  }
91 
92  // Finally insert the range
94  {
95  Info<< "finally insert the range at " << insert << nl;
96  }
97 
98  list[insert] = range;
99 }
100 
101 
102 void Foam::labelRanges::purgeEmpty()
103 {
104  auto& list = static_cast<StorageContainer&>(*this);
105 
106  // Purge empty ranges by copying down
107  label nElem = 0;
108 
109  forAll(list, elemi)
110  {
111  if (!list[elemi].empty())
112  {
113  if (nElem != elemi)
114  {
115  list[nElem] = list[elemi];
116  }
117  ++nElem;
118  }
119  }
120 
121  // Truncate
122  list.resize(nElem);
123 }
124 
125 
126 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
127 
129 {
130  is >> *this;
131 }
132 
133 
134 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
135 
137 {
138  if (range.empty())
139  {
140  return false;
141  }
142  else if (this->empty())
143  {
144  this->append(range);
145  return true;
146  }
147 
148  auto& list = static_cast<StorageContainer&>(*this);
149 
150  // Find the correct place for insertion
151  forAll(list, elemi)
152  {
153  labelRange& currRange = list[elemi];
154 
155  if (currRange.overlaps(range, true))
156  {
157  // absorb into the existing (adjacent/overlapping) range
158  currRange.join(range);
159 
160  // Might connect with the next following range(s)
161  for (; elemi < this->size()-1; ++elemi)
162  {
163  labelRange& nextRange = list[elemi+1];
164  if (currRange.overlaps(nextRange, true))
165  {
166  currRange.join(nextRange);
167  nextRange.clear();
168  }
169  else
170  {
171  break;
172  }
173  }
174 
175  // Done - remove any empty ranges that might have been created
176  purgeEmpty();
177  return true;
178  break;
179  }
180  else if (range < currRange)
181  {
182  insertBefore(elemi, range);
183  return true;
184  break;
185  }
186  }
187 
188 
189  // not found: simply append
190  this->append(range);
191 
192  return true;
193 }
194 
195 
197 {
198  bool status = false;
199  if (range.empty() || this->empty())
200  {
201  return status;
202  }
203 
204  auto& list = static_cast<StorageContainer&>(*this);
205 
206  forAll(list, elemi)
207  {
208  labelRange& currRange = list[elemi];
209 
210  if (range.first() > currRange.first())
211  {
212  if (range.last() < currRange.last())
213  {
214  // Removal of range fragments of currRange
215 
216  if (labelRange::debug)
217  {
218  Info<< "Fragment removal ";
219  printRange(Info, range) << " from ";
220  printRange(Info, currRange) << endl;
221  }
222 
223  // left-hand-side fragment: insert before current range
224  label lower = currRange.first();
225  label upper = range.first() - 1;
226 
227  labelRange fragment(lower, upper - lower + 1);
228 
229  // right-hand-side fragment
230  lower = range.last() + 1;
231  upper = currRange.last();
232 
233  currRange.reset(lower, upper - lower + 1);
234  currRange.clampSize();
235  status = true;
236  insertBefore(elemi, fragment);
237 
238  if (labelRange::debug)
239  {
240  Info<< "fragment ";
241  printRange(Info, fragment) << endl;
242  Info<< "yields ";
243  printRange(Info, currRange) << endl;
244  }
245 
246  // fragmentation can only affect a single range
247  // thus we are done
248  break;
249  }
250  else if (range.first() <= currRange.last())
251  {
252  // keep left-hand-side, remove right-hand-side
253 
254  if (labelRange::debug)
255  {
256  Info<< "RHS removal ";
257  printRange(Info, range) << " from ";
258  printRange(Info, currRange) << endl;
259  }
260 
261  const label lower = currRange.first();
262  const label upper = range.first() - 1;
263 
264  currRange.reset(lower, upper - lower + 1);
265  currRange.clampSize();
266  status = true;
267 
268  if (labelRange::debug)
269  {
270  Info<< "yields ";
271  printRange(Info, currRange) << endl;
272  }
273  }
274  }
275  else if (range.first() <= currRange.first())
276  {
277  if (range.last() >= currRange.first())
278  {
279  // remove left-hand-side, keep right-hand-side
280 
281  if (labelRange::debug)
282  {
283  Info<< "LHS removal ";
284  printRange(Info, range) << " from ";
285  printRange(Info, currRange) << endl;
286  }
287 
288  const label lower = range.last() + 1;
289  const label upper = currRange.last();
290 
291  currRange.reset(lower, upper - lower + 1);
292  currRange.clampSize();
293  status = true;
294 
295  if (labelRange::debug)
296  {
297  Info<< "yields ";
298  printRange(Info, currRange) << endl;
299  }
300  }
301  }
302  }
303 
304  purgeEmpty();
305 
306  return status;
307 }
308 
309 
310 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
311 
313 {
314  is >> static_cast<labelRanges::StorageContainer&>(ranges);
315  return is;
316 }
317 
318 
320 {
321  os << static_cast<const labelRanges::StorageContainer&>(ranges);
322  return os;
323 }
324 
325 
326 // ************************************************************************* //
insert
srcOptions insert("case", fileName(rootDirSource/caseDirSource))
Foam::labelRanges::labelRanges
labelRanges()=default
Default construct.
Foam::labelRange::join
labelRange join(const labelRange &range) const
Return a joined range, squashing any gaps in between.
Definition: labelRange.C:119
Foam::DynamicList< Foam::labelRange >
Foam::labelRanges::add
bool add(const labelRange &range)
Add the range to the list.
Definition: labelRanges.C:136
Foam::IntRange::clear
void clear() noexcept
Reset to zero start and zero size.
Definition: IntRangeI.H:471
Foam::operator>>
Istream & operator>>(Istream &, directionInfo &)
Definition: directionInfo.C:230
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
labelRanges.H
Foam::labelRange::reset
void reset(const label beg, const label end, const bool adjustStart) noexcept
Reset start and length, enforces non-negative size.
Definition: labelRangeI.H:102
append
rAUs append(new volScalarField(IOobject::groupName("rAU", phase1.name()), 1.0/(U1Eqn.A()+byDt(max(phase1.residualAlpha() - alpha1, scalar(0)) *rho1))))
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::labelRange::overlaps
bool overlaps(const labelRange &range, bool touches=false) const
Return true if the ranges overlap.
Definition: labelRange.C:96
Foam::operator<<
Ostream & operator<<(Ostream &, const boundaryPatch &p)
Write boundaryPatch as dictionary entries (without surrounding braces)
Definition: boundaryPatch.C:83
Foam::stringOps::lower
string lower(const std::string &s)
Return string copy transformed with std::tolower on each character.
Definition: stringOps.C:1184
Foam::Istream
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:61
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
Foam::labelRanges
A list of labelRange.
Definition: labelRanges.H:59
Foam::printRange
static Ostream & printRange(Ostream &os, const labelRange &range)
Definition: labelRanges.C:38
Foam::labelRange
A range or interval of labels defined by a start and a size.
Definition: labelRange.H:55
os
OBJstream os(runTime.globalPath()/outputName)
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::labelRange::debug
static int debug
Debugging.
Definition: labelRange.H:73
range
scalar range
Definition: LISASMDCalcMethod1.H:12
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::IntRange::first
IntType first() const noexcept
The (inclusive) lower value of the range. Same as start()
Definition: IntRangeI.H:443
Foam::DynamicList< Foam::labelRange >::remove
Foam::labelRange remove()
Remove and return the last element. Fatal on an empty list.
Definition: DynamicListI.H:704
ListOps.H
Various functions to operate on Lists.
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::stringOps::upper
string upper(const std::string &s)
Return string copy transformed with std::toupper on each character.
Definition: stringOps.C:1200
Foam::IntRange::clampSize
void clampSize() noexcept
Enforce non-negative size.
Definition: IntRangeI.H:511
Foam::IntRange::last
IntType last() const noexcept
The (inclusive) upper value of the range.
Definition: IntRangeI.H:450