primitiveMeshEdges.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | foam-extend: Open Source CFD
4  \\ / O peration | Version: 3.2
5  \\ / A nd | Web: http://www.foam-extend.org
6  \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
8 License
9  This file is part of foam-extend.
10 
11  foam-extend is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by the
13  Free Software Foundation, either version 3 of the License, or (at your
14  option) any later version.
15 
16  foam-extend is distributed in the hope that it will be useful, but
17  WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "primitiveMesh.H"
27 #include "DynamicList.H"
28 #include "demandDrivenData.H"
29 #include "SortableList.H"
30 #include "ListOps.H"
31 
32 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
33 
34 // Returns edgeI between two points.
36 (
39 
40  const label pointI,
41  const label nextPointI
42 )
43 {
44  // Find connection between pointI and nextPointI
45  forAll(pe[pointI], ppI)
46  {
47  label eI = pe[pointI][ppI];
48 
49  const edge& e = es[eI];
50 
51  if (e.start() == nextPointI || e.end() == nextPointI)
52  {
53  return eI;
54  }
55  }
56 
57  // Make new edge.
58  label edgeI = es.size();
59  pe[pointI].append(edgeI);
60  pe[nextPointI].append(edgeI);
61  if (pointI < nextPointI)
62  {
63  es.append(edge(pointI, nextPointI));
64  }
65  else
66  {
67  es.append(edge(nextPointI, pointI));
68  }
69 
70  return edgeI;
71 }
72 
73 
75 {
76  if (debug)
77  {
78  Pout<< "primitiveMesh::calcEdges() : "
79  << "calculating edges, pointEdges and faceEdges"
80  << endl;
81  }
82 
83  // It is an error to attempt to recalculate edges
84  // if the pointer is already set
85  if (edgesPtr_ || fePtr_)
86  {
87  FatalErrorIn("primitiveMesh::calcEdges(const bool) const")
88  << "edges or faceEdges already calculated"
89  << abort(FatalError);
90  }
91  else
92  {
93  // Note: replaced with the original and correct algorithm
94  // which preserved correct ordering for edges list
95  // Version 1.5.x, 1.5-dev were wrong, with failures in parallel
96  // point-based data exchange. Fixed in 1.6-ext and
97  // consecutive versions
98  // HJ, 27/Aug/2010
99 
100  // ALGORITHM:
101  // Go through the pointFace list. Go through the list of faces for
102  // that point and ask for edges. If the edge has got the point
103  // in question AND the second point in the edge is larger than
104  // the first, add the edge to the list. At the same time,
105  // add the edge label to the listof edges for the current face
106  // (faceEdges) and log the other face as the neighbour of this face.
107 
108  const faceList& f = faces();
109 
110  const labelListList& pf = pointFaces();
111 
112  fePtr_ = new labelListList(nFaces());
113  labelListList& fe = *fePtr_;
114 
115  // count the maximum number of edges
116  label maxEdges = 0;
117 
118  // create a list of edges for each face and store for efficiency
119  edgeListList edgesOfFace(nFaces());
120 
121  forAll (f, faceI)
122  {
123  edgesOfFace[faceI] = f[faceI].edges();
124 
125  maxEdges += f[faceI].nEdges();
126 
127  labelList& curFE = fe[faceI];
128 
129  curFE.setSize(f[faceI].nEdges());
130 
131  forAll (curFE, curFEI)
132  {
133  curFE[curFEI] = -1;
134  }
135  }
136 
137  // EDGE CALCULATION
138 
139  edgesPtr_ = new edgeList(maxEdges);
140  edgeList& e = *edgesPtr_;
141  label nEdges = 0;
142 
143  forAll (pf, pointI)
144  {
145  const labelList& curFaces = pf[pointI];
146 
147  // create a list of labels to keep the neighbours that
148  // have already been added
149  DynamicList<label, edgesPerPoint_> addedNeighbours;
151  faceGivingNeighbour;
153  edgeOfFaceGivingNeighbour;
154 
155  forAll (curFaces, faceI)
156  {
157  // get the edges
158  const edgeList& fEdges = edgesOfFace[curFaces[faceI]];
159 
160  // for every edge
161  forAll(fEdges, edgeI)
162  {
163  const edge& ends = fEdges[edgeI];
164 
165  // does the edge has got the point in question
166  bool found = false;
167  label secondPoint = -1;
168 
169  if (ends.start() == pointI)
170  {
171  found = true;
172  secondPoint = ends.end();
173  }
174 
175  if (ends.end() == pointI)
176  {
177  found = true;
178  secondPoint = ends.start();
179  }
180 
181  // if the edge has got the point and second label is larger
182  // than first, it is a candidate for adding
183  if (found && (secondPoint > pointI))
184  {
185  // check if the edge has already been added
186  bool added = false;
187 
188  forAll (addedNeighbours, eopI)
189  {
190  if (secondPoint == addedNeighbours[eopI])
191  {
192  // Edge is already added. New face sharing it
193  added = true;
194 
195  // Remember the face and edge giving neighbour
196  faceGivingNeighbour[eopI].append
197  (curFaces[faceI]);
198 
199  edgeOfFaceGivingNeighbour[eopI].append(edgeI);
200 
201  break;
202  }
203  }
204 
205  // If not added, add the edge to the list
206  if (!added)
207  {
208  addedNeighbours.append(secondPoint);
209 
210  // Remember the face and subShape giving neighbour
211  faceGivingNeighbour(addedNeighbours.size() - 1)
212  .append(curFaces[faceI]);
213  edgeOfFaceGivingNeighbour
214  (addedNeighbours.size() - 1).append(edgeI);
215  }
216  }
217  }
218  }
219 
220  // All edges for the current point found. Before adding them to the
221  // list, it is necessary to sort them in the increasing order of
222  // neighbouring point.
223 
224  // Make real list out of SLList to simplify the manipulation.
225  // Also, make another list to "remember" how the original list was
226  // reshuffled.
227  labelList shuffleList(addedNeighbours.size());
228 
229  forAll (shuffleList, i)
230  {
231  shuffleList[i] = i;
232  }
233 
234  // Use a simple sort to sort the addedNeighbours list.
235  // Other two lists mimic the same behaviour
236  label i, j, a, b;
237 
238  for (j = 1; j <= addedNeighbours.size() - 1; j++)
239  {
240  a = addedNeighbours[j];
241  b = shuffleList[j];
242 
243  i = j - 1;
244 
245  while (i >= 0 && addedNeighbours[i] > a)
246  {
247  addedNeighbours[i + 1] = addedNeighbours[i];
248  shuffleList[i + 1] = shuffleList[i];
249  i--;
250  }
251 
252  addedNeighbours[i + 1] = a;
253  shuffleList[i + 1] = b;
254  }
255 
256  labelList reshuffleList(shuffleList.size());
257 
258  forAll(shuffleList, i)
259  {
260  reshuffleList[shuffleList[i]] = i;
261  }
262 
263  // Reshuffle other lists
264 
265  labelListList fgn(faceGivingNeighbour.size());
266 
267  forAll (faceGivingNeighbour, i)
268  {
269  fgn[reshuffleList[i]].transfer
270  (
271  faceGivingNeighbour[i].shrink()
272  );
273  }
274 
275  labelListList eofgn(edgeOfFaceGivingNeighbour.size());
276 
277  forAll (edgeOfFaceGivingNeighbour, i)
278  {
279  eofgn[reshuffleList[i]].transfer
280  (
281  edgeOfFaceGivingNeighbour[i].shrink()
282  );
283  }
284 
285  // adding the edges
286  forAll(addedNeighbours, edgeI)
287  {
288  const labelList& curFgn = fgn[edgeI];
289  const labelList& curEofgn = eofgn[edgeI];
290 
291  forAll (curFgn, fgnI)
292  {
293  fe[curFgn[fgnI]][curEofgn[fgnI]] = nEdges;
294  }
295 
296  e[nEdges] = edge(pointI, addedNeighbours[edgeI]);
297  nEdges++;
298  }
299  }
300 
301  // reset the size
302  e.setSize(nEdges);
303  }
304 }
305 
306 // Removed ordered edges: reverting to correct parallelisation
307 // of edge data. HJ, 17/Aug/2010
308 // void primitiveMesh::calcOrderedEdges() const
309 
310 
312 (
313  const labelList& list1,
314  const labelList& list2
315 )
316 {
317  label result = -1;
318 
319  labelList::const_iterator iter1 = list1.begin();
320  labelList::const_iterator iter2 = list2.begin();
321 
322  while (iter1 != list1.end() && iter2 != list2.end())
323  {
324  if( *iter1 < *iter2)
325  {
326  ++iter1;
327  }
328  else if (*iter1 > *iter2)
329  {
330  ++iter2;
331  }
332  else
333  {
334  result = *iter1;
335  break;
336  }
337  }
338  if (result == -1)
339  {
341  (
342  "primitiveMesh::findFirstCommonElementFromSortedLists"
343  "(const labelList&, const labelList&)"
344  ) << "No common elements in lists " << list1 << " and " << list2
345  << abort(FatalError);
346  }
347  return result;
348 }
349 
350 
351 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
352 
354 {
355  if (!edgesPtr_)
356  {
357  // 1.6.x merge: reverting to correct code
358  // HJ, 17/Aug/2010
359  calcEdges();
360  }
361 
362  return *edgesPtr_;
363 }
364 
365 
367 {
368  if (!fePtr_)
369  {
370  // 1.6.x merge: reverting to correct code
371  // HJ, 17/Aug/2010
372  calcEdges();
373  }
374 
375  return *fePtr_;
376 }
377 
378 
380 {
381  deleteDemandDrivenData(edgesPtr_);
382  deleteDemandDrivenData(fePtr_);
383  labels_.clear();
384  labelSet_.clear();
385 }
386 
387 
389 (
390  const label faceI,
391  dynamicLabelList& storage
392 ) const
393 {
394  if (hasFaceEdges())
395  {
396  return faceEdges()[faceI];
397  }
398  else
399  {
400  const labelListList& pointEs = pointEdges();
401  const face& f = faces()[faceI];
402 
403  storage.clear();
404  if (f.size() > storage.capacity())
405  {
406  storage.setCapacity(f.size());
407  }
408 
409  forAll(f, fp)
410  {
411  storage.append
412  (
413  findFirstCommonElementFromSortedLists
414  (
415  pointEs[f[fp]],
416  pointEs[f.nextLabel(fp)]
417  )
418  );
419  }
420 
421  return storage;
422  }
423 }
424 
425 
427 {
428  return faceEdges(faceI, labels_);
429 }
430 
431 
433 (
434  const label cellI,
435  dynamicLabelList& storage
436 ) const
437 {
438  if (hasCellEdges())
439  {
440  return cellEdges()[cellI];
441  }
442  else
443  {
444  const labelList& cFaces = cells()[cellI];
445 
446  labelSet_.clear();
447 
448  forAll(cFaces, i)
449  {
450  const labelList& fe = faceEdges(cFaces[i]);
451 
452  forAll(fe, feI)
453  {
454  labelSet_.insert(fe[feI]);
455  }
456  }
457 
458  storage.clear();
459 
460  if (labelSet_.size() > storage.capacity())
461  {
462  storage.setCapacity(labelSet_.size());
463  }
464 
465  forAllConstIter(labelHashSet, labelSet_, iter)
466  {
467  storage.append(iter.key());
468  }
469 
470  return storage;
471  }
472 }
473 
474 
476 {
477  return cellEdges(cellI, labels_);
478 }
479 
480 
481 // ************************************************************************* //
Foam::primitiveMesh::fePtr_
labelListList * fePtr_
Face-edges.
Definition: primitiveMesh.H:137
Foam::edgeList
List< edge > edgeList
Definition: edgeList.H:38
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::DynamicList
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:56
Foam::primitiveMesh::faces
virtual const faceList & faces() const =0
Return faces.
demandDrivenData.H
Template functions to aid in the implementation of demand driven data.
Foam::primitiveMesh::pointFaces
const labelListList & pointFaces() const
Definition: primitiveMeshPointFaces.C:32
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:58
Foam::List::transfer
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Foam::primitiveMesh::edges
const edgeList & edges() const
Return mesh edges. Uses calcEdges.
Definition: primitiveMeshEdges.C:353
Foam::HashSet< label, Hash< label > >
Foam::primitiveMesh::nEdges
label nEdges() const
Definition: primitiveMeshI.H:41
Foam::primitiveMesh::calcEdges
void calcEdges() const
Calculate edges, pointEdges and faceEdges.
Definition: primitiveMeshEdges.C:74
forAllConstIter
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:39
Foam::edge::end
label end() const
Return end vertex label.
Definition: edgeI.H:92
Foam::deleteDemandDrivenData
void deleteDemandDrivenData(DataPtr &dataPtr)
Definition: demandDrivenData.H:40
SortableList.H
Foam::label
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
Foam::constant::physicoChemical::b
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:28
Foam::primitiveMesh::cellEdges
const labelListList & cellEdges() const
Definition: primitiveMeshCellEdges.C:118
Foam::List::append
void append(const T &)
Append an element at the end of the list.
primitiveMesh.H
Foam::primitiveMesh::faceEdges
const labelListList & faceEdges() const
Definition: primitiveMeshEdges.C:366
Foam::FatalError
error FatalError
Foam::primitiveMesh::clearOutEdges
void clearOutEdges()
During edge calculation, a larger set of data is assembled.
Definition: primitiveMeshEdges.C:379
Foam::primitiveMesh::findFirstCommonElementFromSortedLists
static label findFirstCommonElementFromSortedLists(const labelList &, const labelList &)
For on-the-fly addressing calculation.
Definition: primitiveMeshEdges.C:312
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:131
Foam::e
const double e
Elementary charge.
Definition: doubleFloat.H:94
Foam::DynamicList::append
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
found
bool found
Definition: TABSMDCalcMethod2.H:32
Foam::List::setSize
void setSize(const label)
Reset size of List.
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:57
Foam::primitiveMesh::nFaces
label nFaces() const
Definition: primitiveMeshI.H:58
Foam::edge::start
label start() const
Return start vertex label.
Definition: edgeI.H:81
Foam::Pout
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
f
labelList f(nPoints)
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
Foam::primitiveMesh::edgesPtr_
edgeList * edgesPtr_
Edges are ordered in upper triangular order.
Definition: primitiveMesh.H:110
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: doubleFloat.H:94
Foam::List::clear
void clear()
Clear the list, i.e. set size to zero.
Definition: List.C:379
Foam::primitiveMesh::getEdge
static label getEdge(List< dynamicLabelList > &, DynamicList< edge > &, const label, const label)
Helper:
Definition: primitiveMeshEdges.C:36
FatalErrorIn
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition: error.H:313
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
DynamicList.H
cells
const cellShapeList & cells
Definition: gmvOutputHeader.H:3
ListOps.H
Various functions to operate on Lists.
Foam::List::size
void size(const label)
Override size to be inconsistent with allocated storage.