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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2013-2016 OpenFOAM Foundation
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 Application
27  orientFaceZone
28 
29 Group
30  grpMeshManipulationUtilities
31 
32 Description
33  Corrects the orientation of faceZone.
34 
35  - correct in parallel - excludes coupled faceZones from walk
36  - correct for non-manifold faceZones - restarts walk
37 
38 \*---------------------------------------------------------------------------*/
39 
40 #include "argList.H"
41 #include "Time.H"
42 #include "syncTools.H"
43 #include "patchFaceOrientation.H"
44 #include "PatchEdgeFaceWave.H"
45 #include "orientedSurface.H"
46 #include "globalIndex.H"
47 
48 using namespace Foam;
49 
50 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
51 
52 int main(int argc, char *argv[])
53 {
55  (
56  "Corrects the orientation of faceZone"
57  );
58  #include "addRegionOption.H"
59  argList::addArgument("faceZone");
60  argList::addArgument("point", "A point outside of the mesh");
61 
62  #include "setRootCase.H"
63  #include "createTime.H"
64  #include "createNamedPolyMesh.H"
65 
66  const word zoneName = args[1];
67  const point outsidePoint = args.get<point>(2);
68 
69  Info<< "Orienting faceZone " << zoneName
70  << " such that " << outsidePoint << " is outside"
71  << nl << endl;
72 
73 
74  const faceZone& fZone = mesh.faceZones()[zoneName];
75 
76  if (fZone.checkParallelSync())
77  {
79  << "Face zone " << fZone.name()
80  << " is not parallel synchronised."
81  << " Any coupled face also needs its coupled version to be included"
82  << " and with opposite flipMap."
83  << exit(FatalError);
84  }
85 
86  const labelList& faceLabels = fZone;
87 
89  (
90  IndirectList<face>(mesh.faces(), faceLabels),
91  mesh.points()
92  );
93 
94 
95 
96  const bitSet isMasterFace(syncTools::getMasterFaces(mesh));
97 
98 
99  // Data on all edges and faces
100  List<patchFaceOrientation> allEdgeInfo(patch.nEdges());
101  List<patchFaceOrientation> allFaceInfo(patch.size());
102 
103  // Make sure we don't walk through
104  // - slaves of coupled faces
105  // - non-manifold edges
106  {
107  const polyBoundaryMesh& bm = mesh.boundaryMesh();
108 
109  label nProtected = 0;
110 
111  forAll(faceLabels, facei)
112  {
113  const label meshFacei = faceLabels[facei];
114  const label patchi = bm.whichPatch(meshFacei);
115 
116  if
117  (
118  patchi != -1
119  && bm[patchi].coupled()
120  && !isMasterFace[meshFacei]
121  )
122  {
123  // Slave side. Mark so doesn't get visited.
124  allFaceInfo[facei] = orientedSurface::NOFLIP;
125  nProtected++;
126  }
127  }
128 
129  Info<< "Protected from visiting "
130  << returnReduce(nProtected, sumOp<label>())
131  << " slaves of coupled faces" << nl << endl;
132  }
133  {
134  // Number of (master)faces per edge
135  labelList nMasterFaces(patch.nEdges(), Zero);
136 
137  forAll(faceLabels, facei)
138  {
139  const label meshFacei = faceLabels[facei];
140 
141  if (isMasterFace[meshFacei])
142  {
143  const labelList& fEdges = patch.faceEdges()[facei];
144  forAll(fEdges, fEdgeI)
145  {
146  nMasterFaces[fEdges[fEdgeI]]++;
147  }
148  }
149  }
150 
152  (
153  mesh,
154  patch.meshEdges(mesh.edges(), mesh.pointEdges()),
155  nMasterFaces,
156  plusEqOp<label>(),
157  label(0)
158  );
159 
160 
161  label nProtected = 0;
162 
163  forAll(nMasterFaces, edgeI)
164  {
165  if (nMasterFaces[edgeI] > 2)
166  {
167  allEdgeInfo[edgeI] = orientedSurface::NOFLIP;
168  nProtected++;
169  }
170  }
171 
172  Info<< "Protected from visiting "
173  << returnReduce(nProtected, sumOp<label>())
174  << " non-manifold edges" << nl << endl;
175  }
176 
177 
178 
179  DynamicList<label> changedEdges;
181 
182  const scalar tol = PatchEdgeFaceWave
183  <
186  >::propagationTol();
187 
188  int dummyTrackData;
189 
190  globalIndex globalFaces(patch.size());
191 
192  while (true)
193  {
194  // Pick an unset face
195  label unsetFacei = labelMax;
196  forAll(allFaceInfo, facei)
197  {
198  if (allFaceInfo[facei] == orientedSurface::UNVISITED)
199  {
200  unsetFacei = globalFaces.toGlobal(facei);
201  break;
202  }
203  }
204 
205  reduce(unsetFacei, minOp<label>());
206 
207  if (unsetFacei == labelMax)
208  {
209  break;
210  }
211 
212  label proci = globalFaces.whichProcID(unsetFacei);
213  label seedFacei = globalFaces.toLocal(proci, unsetFacei);
214  Info<< "Seeding from processor " << proci << " face " << seedFacei
215  << endl;
216 
217  if (proci == Pstream::myProcNo())
218  {
219  // Determine orientation of seedFace
220 
221  vector d = outsidePoint-patch.faceCentres()[seedFacei];
222  const vector& fn = patch.faceNormals()[seedFacei];
223 
224  // Set information to correct orientation
225  patchFaceOrientation& faceInfo = allFaceInfo[seedFacei];
226  faceInfo = orientedSurface::NOFLIP;
227 
228  if ((fn&d) < 0)
229  {
230  faceInfo.flip();
231 
232  Pout<< "Face " << seedFacei << " at "
233  << patch.faceCentres()[seedFacei]
234  << " with normal " << fn
235  << " needs to be flipped." << endl;
236  }
237  else
238  {
239  Pout<< "Face " << seedFacei << " at "
240  << patch.faceCentres()[seedFacei]
241  << " with normal " << fn
242  << " points in positive direction (cos = " << (fn&d)/mag(d)
243  << ")" << endl;
244  }
245 
246 
247  const labelList& fEdges = patch.faceEdges()[seedFacei];
248  forAll(fEdges, fEdgeI)
249  {
250  label edgeI = fEdges[fEdgeI];
251 
252  patchFaceOrientation& edgeInfo = allEdgeInfo[edgeI];
253 
254  if
255  (
256  edgeInfo.updateEdge<int>
257  (
258  mesh,
259  patch,
260  edgeI,
261  seedFacei,
262  faceInfo,
263  tol,
264  dummyTrackData
265  )
266  )
267  {
268  changedEdges.append(edgeI);
269  changedInfo.append(edgeInfo);
270  }
271  }
272  }
273 
274 
275  if (returnReduce(changedEdges.size(), sumOp<label>()) == 0)
276  {
277  break;
278  }
279 
280 
281 
282  // Walk
284  <
287  > calc
288  (
289  mesh,
290  patch,
291  changedEdges,
292  changedInfo,
293  allEdgeInfo,
294  allFaceInfo,
295  returnReduce(patch.nEdges(), sumOp<label>())
296  );
297  }
298 
299 
300  // Push master zone info over to slave (since slave faces never visited)
301  {
302  const polyBoundaryMesh& bm = mesh.boundaryMesh();
303 
305 
306  forAll(faceLabels, i)
307  {
308  const label meshFacei = faceLabels[i];
309  if (!mesh.isInternalFace(meshFacei))
310  {
311  neiStatus[meshFacei-mesh.nInternalFaces()] =
312  allFaceInfo[i].flipStatus();
313  }
314  }
316 
317  forAll(faceLabels, i)
318  {
319  const label meshFacei = faceLabels[i];
320  const label patchi = bm.whichPatch(meshFacei);
321 
322  if
323  (
324  patchi != -1
325  && bm[patchi].coupled()
326  && !isMasterFace[meshFacei]
327  )
328  {
329  // Slave side. Take flipped from neighbour
330  label bFacei = meshFacei-mesh.nInternalFaces();
331 
332  if (neiStatus[bFacei] == orientedSurface::NOFLIP)
333  {
334  allFaceInfo[i] = orientedSurface::FLIP;
335  }
336  else if (neiStatus[bFacei] == orientedSurface::FLIP)
337  {
338  allFaceInfo[i] = orientedSurface::NOFLIP;
339  }
340  else
341  {
343  << "Incorrect status for face " << meshFacei
344  << abort(FatalError);
345  }
346  }
347  }
348  }
349 
350 
351  // Convert to flipmap and adapt faceZones
352 
353  boolList newFlipMap(allFaceInfo.size(), false);
354  label nChanged = 0;
355  forAll(allFaceInfo, facei)
356  {
357  if (allFaceInfo[facei] == orientedSurface::NOFLIP)
358  {
359  newFlipMap[facei] = false;
360  }
361  else if (allFaceInfo[facei] == orientedSurface::FLIP)
362  {
363  newFlipMap[facei] = true;
364  }
365  else
366  {
368  << "Problem : unvisited face " << facei
369  << " centre:" << mesh.faceCentres()[faceLabels[facei]]
370  << abort(FatalError);
371  }
372 
373  if (fZone.flipMap()[facei] != newFlipMap[facei])
374  {
375  nChanged++;
376  }
377  }
378 
379  reduce(nChanged, sumOp<label>());
380  if (nChanged > 0)
381  {
382  Info<< "Flipping " << nChanged << " out of "
383  << globalFaces.size() << " faces." << nl << endl;
384 
385  mesh.faceZones()[zoneName].resetAddressing(faceLabels, newFlipMap);
386  if (!mesh.faceZones().write())
387  {
389  << "Failed writing faceZones" << exit(FatalError);
390  }
391  }
392 
393  Info<< "End\n" << endl;
394 
395  return 0;
396 }
397 
398 
399 // ************************************************************************* //
Foam::syncTools::syncEdgeList
static void syncEdgeList(const polyMesh &mesh, List< T > &edgeValues, const CombineOp &cop, const T &nullValue, const TransformOp &top, const FlipOp &fop)
Definition: syncToolsTemplates.C:793
Foam::polyMesh::points
virtual const pointField & points() const
Definition: polyMesh.C:1062
Foam::patchFaceOrientation
Transport of orientation for use in PatchEdgeFaceWave.
Definition: patchFaceOrientation.H:56
Foam::labelMax
constexpr label labelMax
Definition: label.H:55
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:63
Foam::faceZone::flipMap
const boolList & flipMap() const noexcept
Definition: faceZone.H:268
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:88
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:59
Foam::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:59
Foam::Zero
static constexpr const zero Zero
Definition: zero.H:131
Foam::DynamicList< label >
Foam::minOp
Definition: ops.H:218
globalIndex.H
Foam::PatchEdgeFaceWave
Wave propagation of information along patch. Every iteration information goes through one layer of fa...
Definition: PatchEdgeFaceWave.H:68
Foam::patchFaceOrientation::flip
void flip()
Definition: patchFaceOrientationI.H:45
Foam::argList::addNote
static void addNote(const string &note)
Definition: argList.C:405
Foam::syncTools::swapBoundaryFaceList
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &faceValues)
Definition: syncTools.H:441
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Definition: polyMesh.H:440
Foam::endl
Ostream & endl(Ostream &os)
Definition: Ostream.H:381
Foam::primitiveMesh::edges
const edgeList & edges() const
Definition: primitiveMeshEdges.C:498
Foam::syncTools::getMasterFaces
static bitSet getMasterFaces(const polyMesh &mesh)
Definition: syncTools.C:119
Foam::Pout
prefixOSstream Pout
Foam::primitiveMesh::pointEdges
const labelListList & pointEdges() const
Definition: primitiveMeshEdges.C:509
Foam::argList::get
T get(const label index) const
Definition: argListI.H:271
syncTools.H
createNamedPolyMesh.H
Required Variables.
Foam::sumOp
Definition: ops.H:207
Foam::orientedSurface::NOFLIP
@ NOFLIP
Definition: orientedSurface.H:64
forAll
#define forAll(list, i)
Definition: stdFoam.H:349
Foam::argList::addArgument
static void addArgument(const string &argName, const string &usage="")
Definition: argList.C:294
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:45
PatchEdgeFaceWave.H
Foam::patchFaceOrientation::updateEdge
bool updateEdge(const polyMesh &mesh, const indirectPrimitivePatch &patch, const label edgeI, const label facei, const patchFaceOrientation &faceInfo, const scalar tol, TrackingData &td)
Definition: patchFaceOrientationI.H:79
Foam::faceZone
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:60
Foam::Info
messageStream Info
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Definition: DynamicListI.H:504
argList.H
Foam::IndirectList
A List with indirect addressing.
Definition: IndirectList.H:52
addRegionOption.H
Foam::primitiveMesh::nBoundaryFaces
label nBoundaryFaces() const noexcept
Definition: primitiveMeshI.H:77
Foam::polyMesh::faceZones
const faceZoneMesh & faceZones() const noexcept
Definition: polyMesh.H:482
Foam::polyBoundaryMesh::whichPatch
label whichPatch(const label faceIndex) const
Definition: polyBoundaryMesh.C:805
Foam::orientedSurface::UNVISITED
@ UNVISITED
Definition: orientedSurface.H:62
Foam::FatalError
error FatalError
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam
Definition: atmBoundaryLayer.C:26
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:139
Foam::globalIndex
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:64
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
Foam::indirectPrimitivePatch
PrimitivePatch< IndirectList< face >, const pointField & > indirectPrimitivePatch
A PrimitivePatch with an IndirectList for the faces, const reference for the point field.
Definition: indirectPrimitivePatch.H:43
Time.H
Foam::faceZone::checkParallelSync
virtual bool checkParallelSync(const bool report=false) const
Definition: faceZone.C:509
setRootCase.H
Foam::primitiveMesh::isInternalFace
bool isInternalFace(const label faceIndex) const noexcept
Definition: primitiveMeshI.H:96
Foam::polyMesh::faces
virtual const faceList & faces() const
Definition: polyMesh.C:1087
FatalErrorInFunction
#define FatalErrorInFunction
Definition: error.H:465
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=worldComm)
Definition: UPstream.H:459
Foam::nl
constexpr char nl
Definition: Ostream.H:424
Foam::zoneIdentifier::name
const word & name() const noexcept
Definition: zoneIdentifier.H:119
Foam::foamVersion::patch
const std::string patch
Foam::Vector< scalar >
Foam::primitiveMesh::nInternalFaces
label nInternalFaces() const noexcept
Definition: primitiveMeshI.H:71
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:58
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::primitiveMesh::faceCentres
const vectorField & faceCentres() const
Definition: primitiveMeshFaceCentresAndAreas.C:71
createTime.H
patchFaceOrientation.H
Foam::orientedSurface::FLIP
@ FLIP
Definition: orientedSurface.H:63
Foam::plusEqOp
Definition: ops.H:66
coupled
bool coupled(solutionDict.getOrDefault("coupledEnergyField", false))
args
Foam::argList args(argc, argv)
orientedSurface.H
Foam::PrimitivePatch
A list of faces which address into the list of points.
Definition: PrimitivePatch.H:75