orientFaceZone.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2013-2018 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 // ************************************************************************* //
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:434
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
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.
const faceZoneMesh & faceZones() const
Return face zone mesh.
Definition: polyMesh.H:476
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
error FatalError
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
label nInternalFaces() const
const labelListList & pointEdges() const
label nFaces() const
Wave propagation of information along patch. Every iteration information goes through one layer of fa...
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:163
const boolList & flipMap() const
Return face flip map.
Definition: faceZone.H:248
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:429
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:256
virtual bool checkParallelSync(const bool report=false) const
Check whether all procs have faces synchronised. Return.
Definition: faceZone.C:425
static SLList< string > validArgs
A list of valid (mandatory) arguments.
Definition: argList.H:153
Transport of orientation for use in PatchEdgeFaceWave.
PrimitivePatch< IndirectList< face >, const pointField & > indirectPrimitivePatch
Foam::indirectPrimitivePatch.
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:1131
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:296
void flip()
Reverse orientation.
static const label labelMax
Definition: label.H:62
const word & name() const
Return name.
Definition: zone.H:147
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1156
errorManip< error > abort(error &err)
Definition: errorManip.H:131
Foam::polyBoundaryMesh.
bool isInternalFace(const label faceIndex) const
Return true if given face label is internal to the mesh.
static const char nl
Definition: Ostream.H:265
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
const edgeList & edges() const
Return mesh edges. Uses calcEdges.
const vectorField & faceCentres() const
A bit-packed bool list.
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
T argRead(const label index) const
Read a value from the argument at index.
Definition: argListI.H:177
messageStream Info
dimensioned< scalar > mag(const dimensioned< Type > &)
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 bool write(const bool write=true) const
Write using setting from DB.
Foam::argList args(argc, argv)
A List with indirect addressing.
Definition: IndirectList.H:101
label whichPatch(const label faceIndex) const
Return patch index for a given face label.
Namespace for OpenFOAM.