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 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 Description
27  The function renumbers the addressing such that the band of the
28  matrix is reduced. The algorithm uses a simple search through the
29  neighbour list
30 
31  See http://en.wikipedia.org/wiki/Cuthill-McKee_algorithm
32 
33 \*---------------------------------------------------------------------------*/
34 
35 #include "bandCompression.H"
36 #include "SLList.H"
37 #include "IOstreams.H"
38 #include "DynamicList.H"
39 #include "ListOps.H"
40 #include "bitSet.H"
41 
42 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
43 
45 {
46  labelList newOrder(cellCellAddressing.size());
47 
48  // the business bit of the renumbering
49  SLList<label> nextCell;
50 
51  bitSet visited(cellCellAddressing.size());
52 
53  label cellInOrder = 0;
54 
55 
56  // Work arrays. Kept outside of loop to minimise allocations.
57  // - neighbour cells
58  DynamicList<label> nbrs;
59  // - corresponding weights
60  DynamicList<label> weights;
61 
62  // - ordering
63  labelList order;
64 
65 
66  while (true)
67  {
68  // For a disconnected region find the lowest connected cell.
69 
70  label currentCell = -1;
71  label minWeight = labelMax;
72 
73  forAll(visited, celli)
74  {
75  // find the lowest connected cell that has not been visited yet
76  if (!visited[celli])
77  {
78  if (cellCellAddressing[celli].size() < minWeight)
79  {
80  minWeight = cellCellAddressing[celli].size();
81  currentCell = celli;
82  }
83  }
84  }
85 
86 
87  if (currentCell == -1)
88  {
89  break;
90  }
91 
92 
93  // Starting from currentCell walk breadth-first
94 
95 
96  // use this cell as a start
97  nextCell.append(currentCell);
98 
99  // loop through the nextCell list. Add the first cell into the
100  // cell order if it has not already been visited and ask for its
101  // neighbours. If the neighbour in question has not been visited,
102  // add it to the end of the nextCell list
103 
104  while (nextCell.size())
105  {
106  currentCell = nextCell.removeHead();
107 
108  if (visited.set(currentCell))
109  {
110  // On first visit...
111 
112  // add into cellOrder
113  newOrder[cellInOrder] = currentCell;
114  cellInOrder++;
115 
116  // find if the neighbours have been visited
117  const labelList& neighbours = cellCellAddressing[currentCell];
118 
119  // Add in increasing order of connectivity
120 
121  // 1. Count neighbours of unvisited neighbours
122  nbrs.clear();
123  weights.clear();
124 
125  forAll(neighbours, nI)
126  {
127  label nbr = neighbours[nI];
128  if (!visited[nbr])
129  {
130  // not visited, add to the list
131  nbrs.append(nbr);
132  weights.append(cellCellAddressing[nbr].size());
133  }
134  }
135  // 2. Sort in ascending order
136  sortedOrder(weights, order);
137  // 3. Add in sorted order
138  forAll(order, i)
139  {
140  nextCell.append(nbrs[i]);
141  }
142  }
143  }
144  }
145 
146  return newOrder;
147 }
148 
149 
151 (
152  const labelList& cellCells,
153  const labelList& offsets
154 )
155 {
156  // Count number of neighbours
157  labelList numNbrs(offsets.size()-1, Zero);
158  forAll(numNbrs, celli)
159  {
160  label start = offsets[celli];
161  label end = offsets[celli+1];
162 
163  for (label facei = start; facei < end; facei++)
164  {
165  numNbrs[celli]++;
166  numNbrs[cellCells[facei]]++;
167  }
168  }
169 
170 
171  labelList newOrder(offsets.size()-1);
172 
173  // the business bit of the renumbering
174  SLList<label> nextCell;
175 
176  bitSet visited(offsets.size()-1);
177 
178  label cellInOrder = 0;
179 
180 
181  // Work arrays. Kept outside of loop to minimise allocations.
182  // - neighbour cells
183  DynamicList<label> nbrs;
184  // - corresponding weights
185  DynamicList<label> weights;
186 
187  // - ordering
188  labelList order;
189 
190 
191  while (true)
192  {
193  // For a disconnected region find the lowest connected cell.
194 
195  label currentCell = -1;
196  label minWeight = labelMax;
197 
198  forAll(visited, celli)
199  {
200  // find the lowest connected cell that has not been visited yet
201  if (!visited[celli])
202  {
203  if (numNbrs[celli] < minWeight)
204  {
205  minWeight = numNbrs[celli];
206  currentCell = celli;
207  }
208  }
209  }
210 
211 
212  if (currentCell == -1)
213  {
214  break;
215  }
216 
217 
218  // Starting from currentCell walk breadth-first
219 
220 
221  // use this cell as a start
222  nextCell.append(currentCell);
223 
224  // loop through the nextCell list. Add the first cell into the
225  // cell order if it has not already been visited and ask for its
226  // neighbours. If the neighbour in question has not been visited,
227  // add it to the end of the nextCell list
228 
229  while (nextCell.size())
230  {
231  currentCell = nextCell.removeHead();
232 
233  if (!visited[currentCell])
234  {
235  visited.set(currentCell);
236 
237  // add into cellOrder
238  newOrder[cellInOrder] = currentCell;
239  cellInOrder++;
240 
241  // Add in increasing order of connectivity
242 
243  // 1. Count neighbours of unvisited neighbours
244  nbrs.clear();
245  weights.clear();
246 
247  label start = offsets[currentCell];
248  label end = offsets[currentCell+1];
249 
250  for (label facei = start; facei < end; facei++)
251  {
252  label nbr = cellCells[facei];
253  if (!visited[nbr])
254  {
255  // not visited, add to the list
256  nbrs.append(nbr);
257  weights.append(numNbrs[nbr]);
258  }
259  }
260  // 2. Sort in ascending order
261  sortedOrder(weights, order);
262  // 3. Add in sorted order
263  forAll(order, i)
264  {
265  nextCell.append(nbrs[i]);
266  }
267  }
268  }
269  }
270 
271  return newOrder;
272 }
273 
274 
275 // ************************************************************************* //
IOstreams.H
Useful combination of include files which define Sin, Sout and Serr and the use of IO streams general...
Foam::labelMax
constexpr label labelMax
Definition: label.H:61
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:63
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::DynamicList< label >
Foam::bandCompression
labelList bandCompression(const labelListList &addressing)
Renumbers the addressing to reduce the band of the matrix.
Definition: bandCompression.C:44
Foam::List::append
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:175
bitSet.H
Foam::DynamicList::clear
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:391
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::LList
Template class for non-intrusive linked lists.
Definition: LList.H:54
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Append an element to the end of this list.
Definition: DynamicListI.H:511
stdFoam::end
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:121
bandCompression.H
The bandCompression function renumbers the addressing such that the band of the matrix is reduced....
SLList.H
Non-intrusive singly-linked list.
Foam::List< label >
DynamicList.H
ListOps.H
Various functions to operate on Lists.
Foam::sortedOrder
labelList sortedOrder(const UList< T > &input)
Return the (stable) sort order for the list.