orientFaceZone.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-2016 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 Application
25  orientFaceZone
26 
27 Description
28  Corrects orientation of faceZone.
29 
30  - correct in parallel - excludes coupled faceZones from walk
31  - correct for non-manifold faceZones - restarts walk
32 
33 \*---------------------------------------------------------------------------*/
34 
35 #include "argList.H"
36 #include "Time.H"
37 #include "syncTools.H"
38 #include "patchFaceOrientation.H"
39 #include "PatchEdgeFaceWave.H"
40 #include "orientedSurface.H"
41 #include "globalIndex.H"
42 
43 using namespace Foam;
44 
45 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
46 
47 int main(int argc, char *argv[])
48 {
49  #include "addRegionOption.H"
50  argList::validArgs.append("faceZone");
51  argList::validArgs.append("outsidePoint");
52 
53  #include "setRootCase.H"
54  #include "createTime.H"
55  #include "createNamedPolyMesh.H"
56 
57  const word zoneName = args[1];
58  const point outsidePoint = args.argRead<point>(2);
59 
60  Info<< "Orienting faceZone " << zoneName
61  << " such that " << outsidePoint << " is outside"
62  << nl << endl;
63 
64 
65  const faceZone& fZone = mesh.faceZones()[zoneName];
66 
67  if (fZone.checkParallelSync())
68  {
70  << "Face zone " << fZone.name()
71  << " is not parallel synchronised."
72  << " Any coupled face also needs its coupled version to be included"
73  << " and with opposite flipMap."
74  << exit(FatalError);
75  }
76 
77  const labelList& faceLabels = fZone;
78 
79  const indirectPrimitivePatch patch
80  (
81  IndirectList<face>(mesh.faces(), faceLabels),
82  mesh.points()
83  );
84 
85 
86 
87  const PackedBoolList isMasterFace(syncTools::getMasterFaces(mesh));
88 
89 
90  // Data on all edges and faces
91  List<patchFaceOrientation> allEdgeInfo(patch.nEdges());
92  List<patchFaceOrientation> allFaceInfo(patch.size());
93 
94  // Make sure we don't walk through
95  // - slaves of coupled faces
96  // - non-manifold edges
97  {
98  const polyBoundaryMesh& bm = mesh.boundaryMesh();
99 
100  label nProtected = 0;
101 
102  forAll(faceLabels, facei)
103  {
104  const label meshFacei = faceLabels[facei];
105  const label patchi = bm.whichPatch(meshFacei);
106 
107  if
108  (
109  patchi != -1
110  && bm[patchi].coupled()
111  && !isMasterFace[meshFacei]
112  )
113  {
114  // Slave side. Mark so doesn't get visited.
115  allFaceInfo[facei] = orientedSurface::NOFLIP;
116  nProtected++;
117  }
118  }
119 
120  Info<< "Protected from visiting "
121  << returnReduce(nProtected, sumOp<label>())
122  << " slaves of coupled faces" << nl << endl;
123  }
124  {
125  // Number of (master)faces per edge
126  labelList nMasterFaces(patch.nEdges(), 0);
127 
128  forAll(faceLabels, facei)
129  {
130  const label meshFacei = faceLabels[facei];
131 
132  if (isMasterFace[meshFacei])
133  {
134  const labelList& fEdges = patch.faceEdges()[facei];
135  forAll(fEdges, fEdgeI)
136  {
137  nMasterFaces[fEdges[fEdgeI]]++;
138  }
139  }
140  }
141 
143  (
144  mesh,
145  patch.meshEdges(mesh.edges(), mesh.pointEdges()),
146  nMasterFaces,
147  plusEqOp<label>(),
148  label(0)
149  );
150 
151 
152  label nProtected = 0;
153 
154  forAll(nMasterFaces, edgeI)
155  {
156  if (nMasterFaces[edgeI] > 2)
157  {
158  allEdgeInfo[edgeI] = orientedSurface::NOFLIP;
159  nProtected++;
160  }
161  }
162 
163  Info<< "Protected from visiting "
164  << returnReduce(nProtected, sumOp<label>())
165  << " non-manifold edges" << nl << endl;
166  }
167 
168 
169 
170  DynamicList<label> changedEdges;
172 
173  const scalar tol = PatchEdgeFaceWave
174  <
177  >::propagationTol();
178 
179  int dummyTrackData;
180 
181  globalIndex globalFaces(patch.size());
182 
183  while (true)
184  {
185  // Pick an unset face
186  label unsetFacei = labelMax;
187  forAll(allFaceInfo, facei)
188  {
189  if (allFaceInfo[facei] == orientedSurface::UNVISITED)
190  {
191  unsetFacei = globalFaces.toGlobal(facei);
192  break;
193  }
194  }
195 
196  reduce(unsetFacei, minOp<label>());
197 
198  if (unsetFacei == labelMax)
199  {
200  break;
201  }
202 
203  label proci = globalFaces.whichProcID(unsetFacei);
204  label seedFacei = globalFaces.toLocal(proci, unsetFacei);
205  Info<< "Seeding from processor " << proci << " face " << seedFacei
206  << endl;
207 
208  if (proci == Pstream::myProcNo())
209  {
210  // Determine orientation of seedFace
211 
212  vector d = outsidePoint-patch.faceCentres()[seedFacei];
213  const vector& fn = patch.faceNormals()[seedFacei];
214 
215  // Set information to correct orientation
216  patchFaceOrientation& faceInfo = allFaceInfo[seedFacei];
217  faceInfo = orientedSurface::NOFLIP;
218 
219  if ((fn&d) < 0)
220  {
221  faceInfo.flip();
222 
223  Pout<< "Face " << seedFacei << " at "
224  << patch.faceCentres()[seedFacei]
225  << " with normal " << fn
226  << " needs to be flipped." << endl;
227  }
228  else
229  {
230  Pout<< "Face " << seedFacei << " at "
231  << patch.faceCentres()[seedFacei]
232  << " with normal " << fn
233  << " points in positive direction (cos = " << (fn&d)/mag(d)
234  << ")" << endl;
235  }
236 
237 
238  const labelList& fEdges = patch.faceEdges()[seedFacei];
239  forAll(fEdges, fEdgeI)
240  {
241  label edgeI = fEdges[fEdgeI];
242 
243  patchFaceOrientation& edgeInfo = allEdgeInfo[edgeI];
244 
245  if
246  (
247  edgeInfo.updateEdge<int>
248  (
249  mesh,
250  patch,
251  edgeI,
252  seedFacei,
253  faceInfo,
254  tol,
255  dummyTrackData
256  )
257  )
258  {
259  changedEdges.append(edgeI);
260  changedInfo.append(edgeInfo);
261  }
262  }
263  }
264 
265 
266  if (returnReduce(changedEdges.size(), sumOp<label>()) == 0)
267  {
268  break;
269  }
270 
271 
272 
273  // Walk
275  <
278  > calc
279  (
280  mesh,
281  patch,
282  changedEdges,
283  changedInfo,
284  allEdgeInfo,
285  allFaceInfo,
286  returnReduce(patch.nEdges(), sumOp<label>())
287  );
288  }
289 
290 
291  // Push master zone info over to slave (since slave faces never visited)
292  {
293  const polyBoundaryMesh& bm = mesh.boundaryMesh();
294 
295  labelList neiStatus
296  (
299  );
300 
301  forAll(faceLabels, i)
302  {
303  const label meshFacei = faceLabels[i];
304  if (!mesh.isInternalFace(meshFacei))
305  {
306  neiStatus[meshFacei-mesh.nInternalFaces()] =
307  allFaceInfo[i].flipStatus();
308  }
309  }
311 
312  forAll(faceLabels, i)
313  {
314  const label meshFacei = faceLabels[i];
315  const label patchi = bm.whichPatch(meshFacei);
316 
317  if
318  (
319  patchi != -1
320  && bm[patchi].coupled()
321  && !isMasterFace[meshFacei]
322  )
323  {
324  // Slave side. Take flipped from neighbour
325  label bFacei = meshFacei-mesh.nInternalFaces();
326 
327  if (neiStatus[bFacei] == orientedSurface::NOFLIP)
328  {
329  allFaceInfo[i] = orientedSurface::FLIP;
330  }
331  else if (neiStatus[bFacei] == orientedSurface::FLIP)
332  {
333  allFaceInfo[i] = orientedSurface::NOFLIP;
334  }
335  else
336  {
338  << "Incorrect status for face " << meshFacei
339  << abort(FatalError);
340  }
341  }
342  }
343  }
344 
345 
346  // Convert to flipmap and adapt faceZones
347 
348  boolList newFlipMap(allFaceInfo.size(), false);
349  label nChanged = 0;
350  forAll(allFaceInfo, facei)
351  {
352  if (allFaceInfo[facei] == orientedSurface::NOFLIP)
353  {
354  newFlipMap[facei] = false;
355  }
356  else if (allFaceInfo[facei] == orientedSurface::FLIP)
357  {
358  newFlipMap[facei] = true;
359  }
360  else
361  {
363  << "Problem : unvisited face " << facei
364  << " centre:" << mesh.faceCentres()[faceLabels[facei]]
365  << abort(FatalError);
366  }
367 
368  if (fZone.flipMap()[facei] != newFlipMap[facei])
369  {
370  nChanged++;
371  }
372  }
373 
374  reduce(nChanged, sumOp<label>());
375  if (nChanged > 0)
376  {
377  Info<< "Flipping " << nChanged << " out of "
378  << globalFaces.size() << " faces." << nl << endl;
379 
380  mesh.faceZones()[zoneName].resetAddressing(faceLabels, newFlipMap);
381  if (!mesh.faceZones().write())
382  {
384  << "Failed writing faceZones" << exit(FatalError);
385  }
386  }
387 
388  Info<< "End\n" << endl;
389 
390  return 0;
391 }
392 
393 
394 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
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
bool updateEdge(const polyMesh &mesh, const indirectPrimitivePatch &patch, const label edgeI, const label facei, const patchFaceOrientation &faceInfo, const scalar tol, TrackingData &td)
Influence of face on edge.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
const boolList & flipMap() const
Return face flip map.
Definition: faceZone.H:253
error FatalError
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
Wave propagation of information along patch. Every iteration information goes through one layer of fa...
const edgeList & edges() const
Return mesh edges. Uses calcEdges.
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:76
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:417
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:253
static SLList< string > validArgs
A list of valid (mandatory) arguments.
Definition: argList.H:154
Transport of orientation for use in PatchEdgeFaceWave.
const vectorField & faceCentres() const
bool isInternalFace(const label faceIndex) const
Return true if given face label is internal to the mesh.
PrimitivePatch< face, IndirectList, const pointField & > indirectPrimitivePatch
Foam::indirectPrimitivePatch.
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:421
static PackedBoolList getMasterFaces(const polyMesh &)
Get per face whether it is uncoupled or a master of a.
Definition: syncTools.C:153
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:979
const word & name() const
Return name.
Definition: zone.H:150
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:63
dynamicFvMesh & mesh
static void syncEdgeList(const polyMesh &, List< T > &, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronize values on all mesh edges.
A class for handling words, derived from string.
Definition: word.H:59
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Definition: DynamicListI.H:292
void flip()
Reverse orientation.
static const label labelMax
Definition: label.H:62
const labelListList & pointEdges() const
virtual bool checkParallelSync(const bool report=false) const
Check whether all procs have faces synchronised. Return.
Definition: faceZone.C:424
errorManip< error > abort(error &err)
Definition: errorManip.H:131
Foam::polyBoundaryMesh.
prefixOSstream Pout(cout,"Pout")
Definition: IOstreams.H:53
static const char nl
Definition: Ostream.H:262
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
T argRead(const label index) const
Read a value from the argument at index.
Definition: argListI.H:177
label nFaces() const
A bit-packed bool list.
label whichPatch(const label faceIndex) const
Return patch index for a given face label.
virtual bool write() const
Write using setting from DB.
messageStream Info
dimensioned< scalar > mag(const dimensioned< Type > &)
const faceZoneMesh & faceZones() const
Return face zone mesh.
Definition: polyMesh.H:463
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &l)
Swap coupled boundary face values.
Definition: syncTools.H:430
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:64
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1004
Foam::argList args(argc, argv)
label nInternalFaces() const
A List with indirect addressing.
Definition: IndirectList.H:102
Namespace for OpenFOAM.