globalIndex.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-2016 OpenFOAM Foundation
9  Copyright (C) 2018-2022 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 "globalIndex.H"
30 #include "labelRange.H"
31 
32 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
33 
34 void Foam::globalIndex::reportOverflowAndExit
35 (
36  const label idx,
37  const labelUList& localLens
38 )
39 {
41  << "Overflow : sum of sizes exceeds labelMax ("
42  << labelMax << ") after index " << idx;
43 
44  if (!localLens.empty())
45  {
46  FatalError << " of " << flatOutput(localLens);
47  }
48 
50  << nl
51  << "Please recompile with larger datatype for label." << nl
52  << exit(FatalError);
53 }
54 
55 
58 (
59  const labelUList& localLens,
60  const bool checkOverflow
61 )
62 {
64 
65  const label len = localLens.size();
66 
67  if (len)
68  {
69  values.resize(len+1);
70 
71  label start = 0;
72  for (label i = 0; i < len; ++i)
73  {
74  values[i] = start;
75  start += localLens[i];
76 
77  if (checkOverflow && start < values[i])
78  {
79  reportOverflowAndExit(i, localLens);
80  }
81  }
82  values[len] = start;
83  }
84 
85  return values;
86 }
87 
88 
91 (
92  const labelUList& localLens,
93  const bool checkOverflow
94 )
95 {
97 
98  const label len = localLens.size();
99 
100  if (len)
101  {
102  values.resize(len);
103 
104  label start = 0;
105  for (label i = 0; i < len; ++i)
106  {
107  values[i].reset(start, localLens[i]);
108  start += localLens[i];
109 
110  if (checkOverflow && start < values[i].start())
111  {
112  reportOverflowAndExit(i, localLens);
113  }
114  }
115  }
117  return values;
118 }
119 
120 
121 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
122 
124 {
125  is >> offsets_;
126 }
127 
128 
129 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
130 
132 Foam::globalIndex::bin
133 (
134  const labelUList& offsets,
135  const labelUList& globalIds,
136  labelList& order,
137  DynamicList<label>& validBins
138 )
139 {
140  sortedOrder(globalIds, order);
141  validBins.clear();
142 
143  CompactListList<label> bins;
144 
145  if (globalIds.size())
146  {
147  labelList& binOffsets = bins.offsets();
148  binOffsets.resize(offsets.size(), Zero);
149 
150  labelList& binValues = bins.values();
151  binValues = UIndirectList<label>(globalIds, order);
152 
153  const label id = binValues[0];
154  label proci = findLower(offsets, id+1);
155 
156  validBins.append(proci);
157  label binSize = 1;
158 
159  for (label i = 1; i < order.size(); i++)
160  {
161  const label id = binValues[i];
162 
163  if (id < offsets[proci+1])
164  {
165  binSize++;
166  }
167  else
168  {
169  // Not local. Reset proci
170  label oldProci = proci;
171  proci = findLower(offsets, id+1);
172 
173  // Set offsets
174  for (label j = oldProci+1; j < proci; ++j)
175  {
176  binOffsets[j] = binOffsets[oldProci]+binSize;
177  }
178  binOffsets[proci] = i;
179  validBins.append(proci);
180  binSize = 1;
181  }
182  }
183 
184  for (label j = proci+1; j < binOffsets.size(); ++j)
185  {
186  binOffsets[j] = binOffsets[proci]+binSize;
187  }
188  }
189 
190  return bins;
191 }
192 
193 
195 (
196  const label localSize,
197  const label comm,
198  const bool parallel
199 )
200 {
201  labelList localLens;
202 
203  const label len = Pstream::nProcs(comm);
204 
205  if (len)
206  {
207  if (parallel && UPstream::parRun())
208  {
209  localLens = UPstream::listGatherValues(localSize, comm);
210  Pstream::broadcast(localLens, comm);
211  }
212  else
213  {
214  // Non-parallel branch: use localSize on-proc, zero elsewhere
215 
216  localLens.resize(len, Zero);
217  localLens[Pstream::myProcNo(comm)] = localSize;
218  }
219 
220  reset(localLens, true); // checkOverflow = true
221  }
222  else
223  {
224  // Nothing to do
225  offsets_.clear();
226  }
227 }
228 
229 
231 (
232  const labelUList& localLens,
233  const bool checkOverflow
234 )
235 {
236  const label len = localLens.size();
237 
238  if (len)
239  {
240  offsets_.resize_nocopy(len+1);
241 
242  label start = 0;
243  for (label i = 0; i < len; ++i)
244  {
245  offsets_[i] = start;
246  start += localLens[i];
247 
248  if (checkOverflow && start < offsets_[i])
249  {
250  reportOverflowAndExit(i, localLens);
251  }
252  }
253  offsets_[len] = start;
254  }
255  else
256  {
257  offsets_.clear();
258  }
259 }
260 
261 
262 void Foam::globalIndex::setLocalSize(const label proci, const label len)
263 {
264  if (proci >= 0 && proci+1 < offsets_.size() && len >= 0)
265  {
266  const label delta = (len - (offsets_[proci+1] - offsets_[proci]));
267 
268  // TBD: additional overflow check
269  if (delta)
270  {
271  for (label i = proci+1; i < offsets_.size(); ++i)
272  {
273  offsets_[i] += delta;
274  }
275  }
276  }
277 }
278 
279 
281 {
283 
284  const label len = (offsets_.size() - 1);
285 
286  if (len < 1)
287  {
288  return values;
289  }
290 
291  values.resize(len);
292 
293  for (label proci=0; proci < len; ++proci)
294  {
295  values[proci] = offsets_[proci+1] - offsets_[proci];
296  }
297 
298  return values;
299 }
300 
301 
304 {
305  List<labelRange> values;
306 
307  const label len = (offsets_.size() - 1);
308 
309  if (len < 1)
310  {
311  return values;
312  }
313 
314  values.resize(len);
315 
316  for (label proci=0; proci < len; ++proci)
317  {
318  values[proci].reset
319  (
320  offsets_[proci],
321  (offsets_[proci+1] - offsets_[proci])
322  );
323  }
324 
325  return values;
326 }
327 
328 
329 Foam::label Foam::globalIndex::maxNonLocalSize(const label proci) const
330 {
331  const label len = (offsets_.size() - 1);
332 
333  if (len < 1)
334  {
335  return 0;
336  }
337 
338  label maxLen = 0;
339 
340  for (label i=0; i < len; ++i)
341  {
342  if (i != proci)
343  {
344  const label localLen = (offsets_[i+1] - offsets_[i]);
345  maxLen = max(maxLen, localLen);
346  }
347  }
349  return maxLen;
350 }
351 
352 
353 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
356 {
357  return is >> gi.offsets_;
358 }
359 
360 
361 Foam::Ostream& Foam::operator<<(Ostream& os, const globalIndex& gi)
362 {
363  return os << gi.offsets_;
364 }
365 
366 
367 // ************************************************************************* //
scalar delta
void reset(const label localSize, const label comm=UPstream::worldComm, const bool parallel=UPstream::parRun())
Reset from local size, using gather/broadcast with default/specified communicator if parallel...
Definition: globalIndex.C:188
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:118
label findLower(const ListType &input, const T &val, const label start, const ComparePredicate &comp)
Binary search to find the index of the last element in a sorted list that is less than value...
static List< labelRange > calcRanges(const labelUList &localLens, const bool checkOverflow=false)
Calculate ranges (offset/size) from a list of local sizes, with optional check for label overflow...
Definition: globalIndex.C:84
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:132
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
List< labelRange > ranges() const
Return start/size ranges for all data.
Definition: globalIndex.C:296
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:578
labelList sortedOrder(const UList< T > &input)
Return the (stable) sort order for the list.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
static List< T > listGatherValues(const T &localValue, const label communicator=worldComm)
Gather individual values into list locations.
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:639
static int myProcNo(const label communicator=worldComm)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:688
labelList localSizes() const
The local sizes.
Definition: globalIndex.C:273
UList< label > labelUList
A UList of labels.
Definition: UList.H:80
static void broadcast(Type &value, const label comm=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all processes in communicator.
globalIndex() noexcept=default
Default construct (empty)
List< T > values(const HashTable< T, Key, Hash > &tbl, const bool doSort=false)
List of values from HashTable, optionally sorted.
Definition: HashOps.H:164
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:63
static label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator) is 1 for serial run.
Definition: UPstream.H:656
Istream & operator>>(Istream &, directionInfo &)
void setLocalSize(const label proci, const label len)
Alter local size for given processor.
Definition: globalIndex.C:255
A packed storage unstructured matrix of objects of type <T> using an offset table for access...
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:55
OBJstream os(runTime.globalPath()/outputName)
Ostream & operator<<(Ostream &, const boundaryPatch &p)
Write boundaryPatch as dictionary entries (without surrounding braces)
Definition: boundaryPatch.C:76
constexpr label labelMax
Definition: label.H:55
List< label > labelList
A List of labels.
Definition: List.H:62
static labelList calcOffsets(const labelUList &localLens, const bool checkOverflow=false)
Calculate offsets from a list of local sizes, with optional check for label overflow.
Definition: globalIndex.C:51
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:225
label maxNonLocalSize() const
The max of localSizes, excluding current processor.
Definition: globalIndexI.H:238
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:157