edgeFaceCirculatorI.H
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) 2019 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 "primitiveMesh.H"
30 
31 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
32 
33 inline const Foam::primitiveMesh& Foam::edgeFaceCirculator::mesh() const
34 {
35  return *meshPtr_;
36 }
37 
38 
39 void Foam::edgeFaceCirculator::setEnd()
40 {
41  faceLabel_ = -1;
42  index_ = -1;
43 }
44 
45 
46 void Foam::edgeFaceCirculator::setFace
47 (
48  const label facei,
49  const label celli
50 )
51 {
52  faceLabel_ = facei;
53 
54  if (!isBoundaryEdge_ && !mesh().isInternalFace(facei))
55  {
57  << "Edge is not defined as boundary edge but still walked to"
58  << " boundary face:" << facei << " on cell:" << celli
59  << abort(FatalError);
60  }
61 }
62 
63 
64 void Foam::edgeFaceCirculator::otherFace(const label celli)
65 {
66  const face& f = mesh().faces()[faceLabel_];
67  label v0 = f[index_];
68  label v1 = f.nextLabel(index_);
69 
70  const cell& cFaces = mesh().cells()[celli];
71 
72  forAll(cFaces, i)
73  {
74  label faceB = cFaces[i];
75 
76  if (faceB != faceLabel_)
77  {
78  label fp = getMinIndex(mesh().faces()[faceB], v0, v1);
79 
80  if (fp >= 0)
81  {
82  index_ = fp;
83  setFace(faceB, celli);
84  return;
85  }
86  }
87  }
88 
90  << "Could not find next face stepping"
91  << " through cell along edge." << endl
92  << "face:" << faceLabel_ << " index in face:" << index_
93  << " edge:" << mesh().points()[v0] << mesh().points()[v1]
94  << abort(FatalError);
95 }
96 
97 
98 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
99 
100 Foam::edgeFaceCirculator::edgeFaceCirculator()
101 :
102  meshPtr_(nullptr),
103  faceLabel_(-1),
104  ownerSide_(false),
105  index_(-1),
106  isBoundaryEdge_(false),
107  startFaceLabel_(0)
108 {}
109 
110 
111 Foam::edgeFaceCirculator::edgeFaceCirculator
112 (
113  const primitiveMesh& mesh,
114  const label faceLabel,
115  const bool ownerSide,
116  const label index,
117  const bool isBoundaryEdge
118 )
119 :
120  meshPtr_(&mesh),
121  faceLabel_(faceLabel),
122  ownerSide_(ownerSide),
123  index_(index),
124  isBoundaryEdge_(isBoundaryEdge),
125  startFaceLabel_(faceLabel_)
126 {}
127 
128 
129 Foam::edgeFaceCirculator::edgeFaceCirculator(const edgeFaceCirculator& circ)
130 :
131  meshPtr_(circ.meshPtr_),
132  faceLabel_(circ.faceLabel_),
133  ownerSide_(circ.ownerSide_),
134  index_(circ.index_),
135  isBoundaryEdge_(circ.isBoundaryEdge_),
136  startFaceLabel_(circ.startFaceLabel_)
137 {}
138 
139 
140 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
141 
143 (
144  const face& f,
145  const label v0,
146  const label v1
147 )
148 {
149  label fp = f.find(v0);
150 
151  if (fp != -1)
152  {
153  label fpMin1 = f.rcIndex(fp);
154 
155  if (f[fpMin1] == v1)
156  {
157  fp = fpMin1;
158  }
159  else
160  {
161  label fpPlus1 = f.fcIndex(fp);
162 
163  if (f[fpPlus1] != v1)
164  {
165  fp = -1;
166  }
167  }
168  }
169  return fp;
170 }
171 
172 
174 {
175  return faceLabel_;
176 }
177 
178 
180 {
181  return
182  (
183  faceLabel_ >= 0
184  && meshPtr_
185  && meshPtr_->isInternalFace(faceLabel_)
186  );
187 }
188 
189 
191 {
192  return ownerSide_;
193 }
194 
195 
197 {
198  return index_;
199 }
200 
201 
203 {
204  if (ownerSide_)
205  {
206  return mesh().faceOwner()[faceLabel_];
207  }
208  else if (mesh().isInternalFace(faceLabel_))
209  {
210  return mesh().faceNeighbour()[faceLabel_];
211  }
212 
213  return -1;
214 }
215 
216 
217 bool Foam::edgeFaceCirculator::sameOrder(const label v0, const label v1) const
218 {
219  const face& f = mesh().faces()[faceLabel_];
220 
221  label fp = getMinIndex(f, v0, v1);
222 
223  if (fp != index_)
224  {
226  << "v0:" << v1 << " and v1:" << v1
227  << " not on position:" << index_ << " on face:" << faceLabel_
228  << " verts:" << f << " or not consecutive." << abort(FatalError);
229  }
230 
231  // If we are neighbour the face would point into us so the min index would
232  // be v0.
233  return ownerSide_ != (f[index_] == v0);
234 }
235 
236 
238 {
239  if (isBoundaryEdge_)
240  {
241  // Boundary edge. Step until we're on boundary face and ownerSide
242  label i = 0;
243 
244  while (true)
245  {
246  if (mesh().isInternalFace(faceLabel_))
247  {
248  if (ownerSide_)
249  {
250  label celli = mesh().faceNeighbour()[faceLabel_];
251  otherFace(celli);
252  // Maintain reverse direction of walking
253  ownerSide_ = (mesh().faceOwner()[faceLabel_] == celli);
254  }
255  else
256  {
257  label celli = mesh().faceOwner()[faceLabel_];
258  otherFace(celli);
259  // Maintain reverse direction of walking
260  ownerSide_ = (mesh().faceOwner()[faceLabel_] == celli);
261  }
262  }
263  else if (ownerSide_)
264  {
265  break;
266  }
267  else
268  {
269  label celli = mesh().faceOwner()[faceLabel_];
270  otherFace(celli);
271  // Maintain reverse direction of walking
272  ownerSide_ = (mesh().faceOwner()[faceLabel_] == celli);
273  }
274 
275  i++;
276 
277  if (i >= 1000)
278  {
279  const face& f = mesh().faces()[faceLabel_];
280 
282  << "Walked " << i << " cells around edge "
283  << mesh().points()[f[index_]]
284  << mesh().points()[f.nextLabel(index_)]
285  << " without reaching a boundary face."
286  << " Are you sure this is a boundary edge?"
287  << abort(FatalError);
288  }
289  }
290 
291  // Set up for correct walking
292  ownerSide_ = true;
293  startFaceLabel_ = faceLabel_;
294  }
295  else
296  {
297  // Internal edge. Walk until we hit minimum face label.
298  label minFacei = faceLabel_;
299  bool minOwnerSide = ownerSide_;
300  label minIndex = index_;
301 
302  while (true)
303  {
304  operator++();
305 
306  if (operator==(end()))
307  {
308  break;
309  }
310 
311  if (!mesh().isInternalFace(faceLabel_))
312  {
313  const face& f = mesh().faces()[faceLabel_];
314 
316  << "Reached boundary face " << faceLabel_
317  << " when walking around internal edge "
318  << mesh().points()[f[index_]]
319  << mesh().points()[f.nextLabel(index_)]
320  << "." << endl
321  << "Are you sure this is an internal edge?"
322  << abort(FatalError);
323  }
324 
325  if (faceLabel_ < minFacei)
326  {
327  minFacei = faceLabel_;
328  minOwnerSide = ownerSide_;
329  minIndex = index_;
330  }
331  }
332 
333  faceLabel_ = minFacei;
334  ownerSide_ = minOwnerSide;
335  index_ = minIndex;
336  startFaceLabel_ = faceLabel_;
337  }
338 }
339 
340 
342 {
343  faceLabel_ = circ.faceLabel_;
344  ownerSide_ = circ.ownerSide_;
345  index_ = circ.index_;
346  isBoundaryEdge_ = circ.isBoundaryEdge_;
347  startFaceLabel_ = circ.startFaceLabel_;
348 }
349 
350 
352 {
353  return faceLabel_ == circ.faceLabel_ && index_ == circ.index_;
354 
357  //if (faceLabel_ == -1 && circ.faceLabel_ == -1)
358  //{
359  // // both endConstIter
360  // return true;
361  //}
362  //
363  //return
364  // faceLabel_ == circ.faceLabel_
365  // && ownerSide_ == circ.ownerSide_
366  // && index_ == circ.index_;
367  // && startFaceLabel_ == circ.startFaceLabel_;
368 }
369 
370 
372 {
373  return !(*this == circ);
374 }
375 
376 
377 //- Step to next face.
380 {
381  if (faceLabel_ == -1)
382  {
384  << "Already reached end(). Cannot walk any further."
385  << abort(FatalError);
386  }
387  else if (ownerSide_)
388  {
389  // Step to owner
390  label celli = mesh().faceOwner()[faceLabel_];
391  otherFace(celli);
392  // Maintain direction of walking
393  ownerSide_ = (mesh().faceOwner()[faceLabel_] != celli);
394 
395  // Check for internal edge : ends on starting face.
396  if (!isBoundaryEdge_ && faceLabel_ == startFaceLabel_)
397  {
398  setEnd();
399  }
400  }
401  else if (mesh().isInternalFace(faceLabel_))
402  {
403  // Step to neighbour
404  label celli = mesh().faceNeighbour()[faceLabel_];
405  otherFace(celli);
406  // Maintain direction of walking
407  ownerSide_ = (mesh().faceOwner()[faceLabel_] != celli);
408 
409  // Check for internal edge : ends on starting face.
410  if (!isBoundaryEdge_ && faceLabel_ == startFaceLabel_)
411  {
412  setEnd();
413  }
414  }
415  else
416  {
417  // neighbour side of boundary face reached. Mark as endConstIter.
418  setEnd();
419  }
420 
421  return *this;
422 }
423 
424 
426 {
427  edgeFaceCirculator iter
428  (
429  *meshPtr_,
430  faceLabel_,
431  ownerSide_,
432  index_,
433  isBoundaryEdge_
434  );
435 
436  if (isBoundaryEdge_)
437  {
438  iter.setCanonical();
439  }
440  return iter;
441 }
442 
443 
445 {
446  edgeFaceCirculator iter
447  (
448  *meshPtr_,
449  faceLabel_,
450  ownerSide_,
451  index_,
452  isBoundaryEdge_
453  );
454 
455  if (isBoundaryEdge_)
456  {
457  iter.setCanonical();
458  }
459  return iter;
460 }
461 
462 
464 {
465  return edgeFaceCirculator();
466 }
467 
469 {
470  return edgeFaceCirculator();
471 }
472 
473 
474 // ************************************************************************* //
Foam::edgeFaceCirculator::operator=
void operator=(const edgeFaceCirculator &iter)
Definition: edgeFaceCirculatorI.H:341
Foam::polyMesh::points
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1069
Foam::meshTools::otherFace
label otherFace(const primitiveMesh &mesh, const label celli, const label facei, const label edgeI)
Return face on cell using edgeI but not facei. Throws error.
Definition: meshTools.C:555
Foam::edgeFaceCirculator::ownerSide
bool ownerSide() const
Definition: edgeFaceCirculatorI.H:190
Foam::edgeFaceCirculator::operator!=
bool operator!=(const edgeFaceCirculator &iter) const
Definition: edgeFaceCirculatorI.H:371
Foam::primitiveMesh::cells
const cellList & cells() const
Definition: primitiveMeshCells.C:138
Foam::edgeFaceCirculator::operator++
edgeFaceCirculator & operator++()
Step to next face. Uses no edge addressing!
Definition: edgeFaceCirculatorI.H:379
primitiveMesh.H
Foam::edgeFaceCirculator::index
label index() const
Definition: edgeFaceCirculatorI.H:196
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::edgeFaceCirculator::getMinIndex
static label getMinIndex(const face &f, const label v0, const label v1)
Helper: find index in face of edge or -1. Index is such that edge is.
Definition: edgeFaceCirculatorI.H:143
Foam::edgeFaceCirculator
Walks from starting face around edge.
Definition: edgeFaceCirculator.H:88
Foam::edgeFaceCirculator::setCanonical
void setCanonical()
Set edge to a unique state so different ones can be compared.
Definition: edgeFaceCirculatorI.H:237
Foam::polyMesh::faceOwner
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1107
Foam::FatalError
error FatalError
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
stdFoam::end
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:121
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
Foam::edgeFaceCirculator::sameOrder
bool sameOrder(const label v0, const label v1) const
Helper: return true if normal of generated face points along.
Definition: edgeFaceCirculatorI.H:217
Foam::edgeFaceCirculator::operator==
bool operator==(const edgeFaceCirculator &iter) const
Definition: edgeFaceCirculatorI.H:351
Foam::polyMesh::faces
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1094
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::edgeFaceCirculator::cbegin
edgeFaceCirculator cbegin() const
Definition: edgeFaceCirculatorI.H:444
f
labelList f(nPoints)
Foam::edgeFaceCirculator::cellLabel
label cellLabel() const
Helper: get the neighbouring cell according to the ownerSide.
Definition: edgeFaceCirculatorI.H:202
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:72
Foam::edgeFaceCirculator::isInternalFace
bool isInternalFace() const
Return true if the face label corresponds to an internal face.
Definition: edgeFaceCirculatorI.H:179
Foam::edgeFaceCirculator::cend
const edgeFaceCirculator cend() const
Definition: edgeFaceCirculatorI.H:468
Foam::edgeFaceCirculator::begin
edgeFaceCirculator begin() const
Iterator set to the beginning face. For internal edges this is.
Definition: edgeFaceCirculatorI.H:425
Foam::edgeFaceCirculator::faceLabel
label faceLabel() const
Return the face label, -1 for end iterator.
Definition: edgeFaceCirculatorI.H:173
Foam::polyMesh::faceNeighbour
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1113
Foam::edgeFaceCirculator::end
const edgeFaceCirculator end() const
Iterator set to beyond the end of the walk.
Definition: edgeFaceCirculatorI.H:463
Foam::primitiveMesh
Cell-face mesh analysis engine.
Definition: primitiveMesh.H:78