Loading...
Searching...
No Matches
bandCompression.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) 2022-2024 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
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 "bandCompression.H"
30#include "bitSet.H"
31#include "polyMesh.H"
32#include "globalMeshData.H"
33#include "CircularBuffer.H"
34#include "CompactListList.H"
35#include "DynamicList.H"
36#include "IOstreams.H"
37
38// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
39
40namespace
41{
42
43// Process connections with the Cuthill-McKee algorithm.
44// The connections are CompactListList<label> or a labelListList.
45template<class ConnectionListListType>
46Foam::labelList cuthill_mckee_algorithm
47(
48 const ConnectionListListType& cellCellAddressing
49)
50{
51 using namespace Foam;
52
53 const label nOldCells(cellCellAddressing.size());
54
55 // Which cells are visited/unvisited
56 bitSet unvisited(nOldCells, true);
57
58 // The new output order
59 labelList newOrder(nOldCells);
60
61
62 // Various work arrays
63 // ~~~~~~~~~~~~~~~~~~~
64
65 // Neighbour cells
66 DynamicList<label> nbrCells;
67
68 // Neighbour ordering
69 DynamicList<label> nbrOrder;
70
71 // Corresponding weights for neighbour cells
72 DynamicList<label> weights;
73
74 // FIFO buffer for renumbering.
75 CircularBuffer<label> queuedCells(1024);
76
77 label cellInOrder = 0;
78
79 while (true)
80 {
81 // For a disconnected region find the lowest connected cell.
82 label currCelli = -1;
83 label minCount = labelMax;
84
85 for (const label celli : unvisited)
86 {
87 const label nbrCount = cellCellAddressing[celli].size();
88
89 if (minCount > nbrCount)
90 {
91 minCount = nbrCount;
92 currCelli = celli;
93 }
94 }
95
96 if (currCelli == -1)
97 {
98 break;
99 }
100
101
102 // Starting from currCelli - walk breadth-first
103
104 queuedCells.push_back(currCelli);
105
106 // Loop through queuedCells list. Add the first cell into the
107 // cell order if it has not already been visited and ask for its
108 // neighbours. If the neighbour in question has not been visited,
109 // add it to the end of the queuedCells list
110
111 while (!queuedCells.empty())
112 {
113 // Process as FIFO
114 currCelli = queuedCells.front();
115 queuedCells.pop_front();
116
117 if (unvisited.test(currCelli))
118 {
119 // First visit...
120 unvisited.unset(currCelli);
121
122 // Add into cellOrder
123 newOrder[cellInOrder] = currCelli;
124 ++cellInOrder;
125
126 // Add in increasing order of connectivity
127
128 // 1. Count neighbours of unvisited neighbours
129 nbrCells.clear();
130 weights.clear();
131
132 // Find if the neighbours have been visited
133 const auto& neighbours = cellCellAddressing[currCelli];
134
135 for (const label nbr : neighbours)
136 {
137 const label nbrCount = cellCellAddressing[nbr].size();
138
139 if (unvisited.test(nbr))
140 {
141 // Not visited (or removed), add to the list
142 nbrCells.push_back(nbr);
143 weights.push_back(nbrCount);
144 }
145 }
146
147 // Resize DynamicList prior to sortedOrder
148 nbrOrder.resize_nocopy(weights.size());
149
150 // 2. Ascending order
151 Foam::sortedOrder(weights, nbrOrder);
152
153 // 3. Add to FIFO in sorted order
154 for (const label nbrIdx : nbrOrder)
155 {
156 queuedCells.push_back(nbrCells[nbrIdx]);
157 }
158 }
159 }
160 }
161
162 // Debug:
163 // - the peak capacity of queuedCells approximates the
164 // maximum intermediate bandwidth
165 #if 0
166 Pout<< "bandCompression: peak-capacity=" << queuedCells.capacity() << nl;
167 #endif
168
169 // Now we have new-to-old in newOrder.
170 return newOrder;
172
173} // End anonymous namespace
174
175
176// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
177
179(
180 const labelUList& cellCells,
181 const labelUList& offsets
182)
183{
184 // Protect against zero-sized offset list
185 const label nOldCells = Foam::max(0, (offsets.size()-1));
186
187 // Count number of neighbours
188 labelList numNbrs(nOldCells, Foam::zero{});
189 for (label celli = 0; celli < nOldCells; ++celli)
190 {
191 const label beg = offsets[celli];
192 const label end = offsets[celli+1];
193
194 for (label idx = beg; idx < end; ++idx)
195 {
196 ++numNbrs[celli];
197 ++numNbrs[cellCells[idx]];
198 }
199 }
200
201
202 // Which cells are visited/unvisited
203 bitSet unvisited(nOldCells, true);
204
205 // The new output order
206 labelList newOrder(nOldCells);
207
208
209 // Various work arrays
210 // ~~~~~~~~~~~~~~~~~~~
211
212 // Neighbour cells
213 DynamicList<label> nbrCells;
214
215 // Neighbour ordering
216 DynamicList<label> nbrOrder;
217
218 // Corresponding weights for neighbour cells
219 DynamicList<label> weights;
220
221 // FIFO buffer for renumbering.
222 CircularBuffer<label> queuedCells(1024);
223
224
225 label cellInOrder = 0;
226
227 while (true)
228 {
229 // Find lowest connected cell that has not been visited yet
230 label currCelli = -1;
231 label minCount = labelMax;
232
233 for (const label celli : unvisited)
234 {
235 const label nbrCount = numNbrs[celli];
236
237 if (minCount > nbrCount)
238 {
239 minCount = nbrCount;
240 currCelli = celli;
241 }
242 }
243
244 if (currCelli == -1)
245 {
246 break;
247 }
248
249
250 // Starting from currCellii - walk breadth-first
251
252 queuedCells.push_back(currCelli);
253
254 // loop through the nextCell list. Add the first cell into the
255 // cell order if it has not already been visited and ask for its
256 // neighbours. If the neighbour in question has not been visited,
257 // add it to the end of the nextCell list
258
259 // Loop through queuedCells list. Add the first cell into the
260 // cell order if it has not already been visited and ask for its
261 // neighbours. If the neighbour in question has not been visited,
262 // add it to the end of the queuedCells list
263
264 while (!queuedCells.empty())
265 {
266 // Process as FIFO
267 currCelli = queuedCells.front();
268 queuedCells.pop_front();
269
270 if (unvisited.test(currCelli))
271 {
272 // First visit...
273 unvisited.unset(currCelli);
274
275 // Add into cellOrder
276 newOrder[cellInOrder] = currCelli;
277 ++cellInOrder;
278
279 // Add in increasing order of connectivity
280
281 // 1. Count neighbours of unvisited neighbours
282 nbrCells.clear();
283 weights.clear();
284
285 const label beg = offsets[currCelli];
286 const label end = offsets[currCelli+1];
287
288 for (label idx = beg; idx < end; ++idx)
289 {
290 const label nbr = cellCells[idx];
291 const label nbrCount = numNbrs[nbr];
292
293 if (unvisited.test(nbr))
294 {
295 // Not visited (or removed), add to the list
296 nbrCells.push_back(nbr);
297 weights.push_back(nbrCount);
298 }
299 }
300
301 // Resize DynamicList prior to sortedOrder
302 nbrOrder.resize_nocopy(weights.size());
303
304 // 2. Ascending order
305 Foam::sortedOrder(weights, nbrOrder);
306
307 // 3. Add to FIFO in sorted order
308 for (const label nbrIdx : nbrOrder)
309 {
310 queuedCells.push_back(nbrCells[nbrIdx]);
311 }
312 }
313 }
314 }
315
316 // Debug:
317 // - the peak capacity of queuedCells approximates the
318 // maximum intermediate bandwidth
319 #if 0
320 Pout<< "bandCompression: peak-capacity=" << queuedCells.capacity() << nl;
321 #endif
322
323 // Now we have new-to-old in newOrder.
324 return newOrder;
325}
326
327
328// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
329
331{
332 // Local mesh connectivity
335
336 return cuthill_mckee_algorithm(cellCells);
337}
338
339
341(
342 const CompactListList<label>& cellCellAddressing
343)
344{
345 return cuthill_mckee_algorithm(cellCellAddressing);
346}
347
348
350(
351 const labelListList& cellCellAddressing
352)
353{
354 return cuthill_mckee_algorithm(cellCellAddressing);
355}
356
357
358// ************************************************************************* //
Useful combination of include files which define Sin, Sout and Serr and the use of IO streams general...
The bandCompression function renumbers the addressing such that the band of the matrix is reduced....
A simple list of objects of type <T> that is intended to be used as a circular buffer (eg,...
void pop_front(label n=1)
Shrink by moving the front of the buffer 1 or more times.
bool empty() const noexcept
Empty or exhausted buffer.
label capacity() const noexcept
Size of the underlying storage.
void push_back(const T &val)
Copy append an element to the end of the buffer.
T & front()
Access the first element (front). Requires !empty().
A packed storage of objects of type <T> using an offset table for access.
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
void resize_nocopy(const label len)
Alter addressable list size, allocating new space if required without necessarily recovering old cont...
void push_back(const T &val)
Copy append an element to the end of this list.
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition bitSet.H:61
static void calcCellCells(const polyMesh &mesh, const labelUList &agglom, const label nLocalCoarse, const bool parallel, CompactListList< label > &cellCells)
Determine (local or global) cellCells from mesh agglomeration.
Mesh consisting of general polyhedral cells.
Definition polyMesh.H:79
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition zero.H:58
dynamicFvMesh & mesh
const char * end
Definition SVGTools.H:223
labelList bandCompression(const polyMesh &mesh)
Renumber (mesh) addressing to reduce the band of the mesh connectivity, using the Cuthill-McKee algor...
Namespace for OpenFOAM.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:40
List< labelList > labelListList
List of labelList.
Definition labelList.H:38
List< label > labelList
A List of labels.
Definition List.H:62
constexpr label labelMax
Definition label.H:55
labelList sortedOrder(const UList< T > &input)
Return the (stable) sort order for the list.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
UList< label > labelUList
A UList of labels.
Definition UList.H:75
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50