meshStructure.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 | Copyright (C) 2013 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "meshStructure.H"
27 #include "FaceCellWave.H"
28 #include "topoDistanceData.H"
29 #include "pointTopoDistanceData.H"
30 #include "PointEdgeWave.H"
31 
32 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
33 
34 namespace Foam
35 {
36 defineTypeNameAndDebug(meshStructure, 0);
37 }
38 
39 
40 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
41 
43 (
44  const polyMesh& mesh,
45  const label layerI,
46  const label cellI
47 ) const
48 {
49  const cell& cFaces = mesh.cells()[cellI];
50 
51  // Count number of side faces
52  label nSide = 0;
53  forAll(cFaces, i)
54  {
55  if (faceToPatchEdgeAddressing_[cFaces[i]] != -1)
56  {
57  nSide++;
58  }
59  }
60 
61  if (nSide != cFaces.size()-2)
62  {
63  return false;
64  }
65 
66  // Check that side faces have correct point layers
67  forAll(cFaces, i)
68  {
69  if (faceToPatchEdgeAddressing_[cFaces[i]] != -1)
70  {
71  const face& f = mesh.faces()[cFaces[i]];
72 
73  label nLayer = 0;
74  label nLayerPlus1 = 0;
75  forAll(f, fp)
76  {
77  label pointI = f[fp];
78  if (pointLayer_[pointI] == layerI)
79  {
80  nLayer++;
81  }
82  else if (pointLayer_[pointI] == layerI+1)
83  {
84  nLayerPlus1++;
85  }
86  }
87 
88  if (f.size() != 4 || (nLayer+nLayerPlus1 != 4))
89  {
90  return false;
91  }
92  }
93  }
94 
95  return true;
96 }
97 
98 
100 (
101  const polyMesh& mesh,
102  const uindirectPrimitivePatch& pp
103 )
104 {
105  // Field on cells and faces.
106  List<topoDistanceData> cellData(mesh.nCells());
107  List<topoDistanceData> faceData(mesh.nFaces());
108 
109  {
110  if (debug)
111  {
112  Info<< typeName << " : seeding "
113  << returnReduce(pp.size(), sumOp<label>()) << " patch faces"
114  << nl << endl;
115  }
116 
117 
118  // Start of changes
119  labelList patchFaces(pp.size());
120  List<topoDistanceData> patchData(pp.size());
121  forAll(pp, patchFaceI)
122  {
123  patchFaces[patchFaceI] = pp.addressing()[patchFaceI];
124  patchData[patchFaceI] = topoDistanceData(patchFaceI, 0);
125  }
126 
127 
128  // Propagate information inwards
129  FaceCellWave<topoDistanceData> distanceCalc
130  (
131  mesh,
132  patchFaces,
133  patchData,
134  faceData,
135  cellData,
136  mesh.globalData().nTotalCells()+1
137  );
138 
139 
140  // Determine cells from face-cell-walk
141  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
142 
143  cellToPatchFaceAddressing_.setSize(mesh.nCells());
144  cellLayer_.setSize(mesh.nCells());
145  forAll(cellToPatchFaceAddressing_, cellI)
146  {
147  cellToPatchFaceAddressing_[cellI] = cellData[cellI].data();
148  cellLayer_[cellI] = cellData[cellI].distance();
149  }
150 
151 
152 
153  // Determine faces from face-cell-walk
154  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
155 
156  faceToPatchFaceAddressing_.setSize(mesh.nFaces());
157  faceToPatchEdgeAddressing_.setSize(mesh.nFaces());
158  faceToPatchEdgeAddressing_ = labelMin;
159  faceLayer_.setSize(mesh.nFaces());
160 
161  forAll(faceToPatchFaceAddressing_, faceI)
162  {
163  label own = mesh.faceOwner()[faceI];
164  label patchFaceI = faceData[faceI].data();
165  label patchDist = faceData[faceI].distance();
166 
167  if (mesh.isInternalFace(faceI))
168  {
169  label nei = mesh.faceNeighbour()[faceI];
170 
171  if (cellData[own].distance() == cellData[nei].distance())
172  {
173  // side face
174  faceToPatchFaceAddressing_[faceI] = 0;
175  faceLayer_[faceI] = cellData[own].distance();
176  }
177  else if (cellData[own].distance() < cellData[nei].distance())
178  {
179  // unturned face
180  faceToPatchFaceAddressing_[faceI] = patchFaceI+1;
181  faceToPatchEdgeAddressing_[faceI] = -1;
182  faceLayer_[faceI] = patchDist;
183  }
184  else
185  {
186  // turned face
187  faceToPatchFaceAddressing_[faceI] = -(patchFaceI+1);
188  faceToPatchEdgeAddressing_[faceI] = -1;
189  faceLayer_[faceI] = patchDist;
190  }
191  }
192  else if (patchDist == cellData[own].distance())
193  {
194  // starting face
195  faceToPatchFaceAddressing_[faceI] = -(patchFaceI+1);
196  faceToPatchEdgeAddressing_[faceI] = -1;
197  faceLayer_[faceI] = patchDist;
198  }
199  else
200  {
201  // unturned face or side face. Cannot be determined until
202  // we determine the point layers. Problem is that both are
203  // the same number of steps away from the initial seed face.
204  }
205  }
206  }
207 
208 
209  // Determine points from separate walk on point-edge
210  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
211 
212  {
213  pointToPatchPointAddressing_.setSize(mesh.nPoints());
214  pointLayer_.setSize(mesh.nPoints());
215 
216  if (debug)
217  {
218  Info<< typeName << " : seeding "
219  << returnReduce(pp.nPoints(), sumOp<label>()) << " patch points"
220  << nl << endl;
221  }
222 
223  // Field on edges and points.
224  List<pointTopoDistanceData> edgeData(mesh.nEdges());
226 
227  // Start of changes
228  labelList patchPoints(pp.nPoints());
229  List<pointTopoDistanceData> patchData(pp.nPoints());
230  forAll(pp.meshPoints(), patchPointI)
231  {
232  patchPoints[patchPointI] = pp.meshPoints()[patchPointI];
233  patchData[patchPointI] = pointTopoDistanceData(patchPointI, 0);
234  }
235 
236 
237  // Walk
239  (
240  mesh,
241  patchPoints,
242  patchData,
243 
244  pointData,
245  edgeData,
246  mesh.globalData().nTotalPoints() // max iterations
247  );
248 
249  forAll(pointData, pointI)
250  {
251  pointToPatchPointAddressing_[pointI] = pointData[pointI].data();
252  pointLayer_[pointI] = pointData[pointI].distance();
253  }
254 
255 
256  // Derive from originating patch points what the patch edges were.
257  EdgeMap<label> pointsToEdge(pp.nEdges());
258  forAll(pp.edges(), edgeI)
259  {
260  pointsToEdge.insert(pp.edges()[edgeI], edgeI);
261  }
262 
263  // Look up on faces
264  forAll(faceToPatchEdgeAddressing_, faceI)
265  {
266  if (faceToPatchEdgeAddressing_[faceI] == labelMin)
267  {
268  // Face not yet done. Check if all points on same level
269  // or if not see what edge it originates from
270 
271  const face& f = mesh.faces()[faceI];
272 
273  label levelI = pointLayer_[f[0]];
274  for (label fp = 1; fp < f.size(); fp++)
275  {
276  if (pointLayer_[f[fp]] != levelI)
277  {
278  levelI = -1;
279  break;
280  }
281  }
282 
283  if (levelI != -1)
284  {
285  // All same level
286  //Pout<< "Horizontal boundary face " << faceI
287  // << " at:" << mesh.faceCentres()[faceI]
288  // << " data:" << faceData[faceI]
289  // << " pointDatas:"
290  // << UIndirectList<pointTopoDistanceData>(pointData, f)
291  // << endl;
292 
293  label patchFaceI = faceData[faceI].data();
294  label patchDist = faceData[faceI].distance();
295 
296  faceToPatchEdgeAddressing_[faceI] = -1;
297  faceToPatchFaceAddressing_[faceI] = patchFaceI+1;
298  faceLayer_[faceI] = patchDist;
299  }
300  else
301  {
302  // Points of face on different levels
303 
304  // See if there is any edge
305  forAll(f, fp)
306  {
307  label pointI = f[fp];
308  label nextPointI = f.nextLabel(fp);
309 
310  EdgeMap<label>::const_iterator fnd = pointsToEdge.find
311  (
312  edge
313  (
314  pointData[pointI].data(),
315  pointData[nextPointI].data()
316  )
317  );
318  if (fnd != pointsToEdge.end())
319  {
320  faceToPatchEdgeAddressing_[faceI] = fnd();
321  faceToPatchFaceAddressing_[faceI] = 0;
322  label own = mesh.faceOwner()[faceI];
323  faceLayer_[faceI] = cellData[own].distance();
324 
325  // Note: could test whether the other edges on the
326  // face are consistent
327  break;
328  }
329  }
330  }
331  }
332  }
333  }
334 
335 
336 
337  // Use maps to find out mesh structure.
338  {
339  label nLayers = gMax(cellLayer_)+1;
340  labelListList layerToCells(invertOneToMany(nLayers, cellLayer_));
341 
342  structured_ = true;
343  forAll(layerToCells, layerI)
344  {
345  const labelList& lCells = layerToCells[layerI];
346 
347  forAll(lCells, lCellI)
348  {
349  label cellI = lCells[lCellI];
350 
351  structured_ = isStructuredCell
352  (
353  mesh,
354  layerI,
355  cellI
356  );
357 
358  if (!structured_)
359  {
360  break;
361  }
362  }
363 
364  if (!structured_)
365  {
366  break;
367  }
368  }
369 
370  reduce(structured_, andOp<bool>());
371  }
372 }
373 
374 
375 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
376 
378 (
379  const polyMesh& mesh,
380  const uindirectPrimitivePatch& pp
381 )
382 {
383  correct(mesh, pp);
384 }
385 
386 
387 // ************************************************************************* //
topoDistanceData.H
Foam::topoDistanceData
For use with FaceCellWave. Determines topological distance to starting faces.
Definition: topoDistanceData.H:53
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:86
Foam::PrimitivePatch::edges
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
Definition: PrimitivePatchTemplate.C:212
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::invertOneToMany
labelListList invertOneToMany(const label len, const labelUList &)
Invert one-to-many map. Unmapped elements will be size 0.
Definition: ListOps.C:67
Foam::PointEdgeWave
Wave propagation of information through grid. Every iteration information goes through one layer of e...
Definition: PointEdgeWave.H:85
Foam::PrimitivePatch::nEdges
label nEdges() const
Return number of edges in patch.
Definition: PrimitivePatchTemplate.H:299
Foam::meshStructure::isStructuredCell
bool isStructuredCell(const polyMesh &mesh, const label layerI, const label cellI) const
Is cell structured.
Definition: meshStructure.C:43
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::meshStructure::meshStructure
meshStructure(const polyMesh &mesh, const uindirectPrimitivePatch &)
Construct null.
Definition: meshStructure.C:378
Foam::HashTable::insert
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
Definition: HashTableI.H:80
Foam::pointData
Variant of pointEdgePoint with some transported additional data. WIP - should be templated on data li...
Definition: pointData.H:53
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
patchFaces
labelList patchFaces(const polyBoundaryMesh &patches, const wordList &names)
Definition: extrudeMesh.C:148
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
Foam::pointTopoDistanceData
For use with PointEdgeWave. Determines topological distance to starting points.
Definition: pointTopoDistanceData.H:54
meshStructure.H
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:43
Foam::labelMin
static const label labelMin
Definition: label.H:61
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::nl
static const char nl
Definition: Ostream.H:260
Foam::Info
messageStream Info
PointEdgeWave.H
correct
fvOptions correct(rho)
Foam::PrimitivePatch::nPoints
label nPoints() const
Return number of points supporting patch faces.
Definition: PrimitivePatchTemplate.H:293
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:18
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
Foam::HashTable::find
iterator find(const Key &)
Find and return an iterator set at the hashedEntry.
Foam::distance
scalar distance(const vector &p1, const vector &p2)
Definition: curveTools.C:12
Foam::List::setSize
void setSize(const label)
Reset size of List.
Foam::FaceCellWave
Wave propagation of information through grid. Every iteration information goes through one layer of c...
Definition: FaceCellWave.H:75
Foam::EdgeMap< label >
Foam::andOp
Definition: ops.H:177
pointTopoDistanceData.H
Foam::sumOp
Definition: ops.H:162
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
FaceCellWave.H
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
Foam::List::size
void size(const label)
Override size to be inconsistent with allocated storage.
Foam::PrimitivePatch::meshPoints
const labelList & meshPoints() const
Return labelList of mesh points in patch.
Definition: PrimitivePatchTemplate.C:392
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::cell
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:56
Foam::data
Database for solution data, solver performance and other reduced data.
Definition: data.H:52
Foam::meshStructure::correct
void correct(const polyMesh &mesh, const uindirectPrimitivePatch &pp)
Calculate all maps.
Definition: meshStructure.C:100
Foam::gMax
Type gMax(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:562
Foam::PrimitivePatch
A list of faces which address into the list of points.
Definition: PrimitivePatchTemplate.H:88