mergeOrSplitBaffles.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) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2016-2020 OpenCFD Ltd.
10  Copyright (C) 2026 Keysight Technologies
11 -------------------------------------------------------------------------------
12 License
13  This file is part of OpenFOAM.
14 
15  OpenFOAM is free software: you can redistribute it and/or modify it
16  under the terms of the GNU General Public License as published by
17  the Free Software Foundation, either version 3 of the License, or
18  (at your option) any later version.
19 
20  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
21  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23  for more details.
24 
25  You should have received a copy of the GNU General Public License
26  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
27 
28 Application
29  mergeOrSplitBaffles
30 
31 Group
32  grpMeshManipulationUtilities
33 
34 Description
35  Detects boundary faces that share points (baffles). Either merges them or
36  duplicate the points.
37 
38 Usage
39  \b mergeOrSplitBaffles [OPTION]
40 
41  With no action option, baffles are merged into internal faces (default).
42 
43  Options:
44  - \par -detectOnly
45  Detect baffles and write to faceSet duplicateFaces.
46 
47  - \par -split
48  Detect baffles and duplicate the points (used so the two sides
49  can move independently)
50 
51  - \par -dict <dictionary>
52  Specify a dictionary to read actions from. The dictionary may
53  contain \c detect, \c merge and \c split sub-dictionaries, each
54  with a \c patches entry restricting the action to a list of
55  patches. Note that \c merge is only available via \c -dict; on
56  the command line, merging is the default action and there is
57  therefore no \c -merge flag.
58 
59  - \par -overwrite
60  Overwrite the existing mesh instead of writing to a new time.
61 
62  - \par -region <name>
63  Specify a non-default mesh region.
64 
65 Note
66  - can only handle pairwise boundary faces. So three faces using
67  the same points is not handled (is illegal mesh anyway)
68 
69  - surfaces consisting of duplicate faces can be topologically split
70  if the points on the interior of the surface cannot walk to all the
71  cells that use them in one go.
72 
73  - Parallel operation (where duplicate face is perpendicular to a coupled
74  boundary) is supported but not really tested.
75  (Note that coupled faces themselves are not seen as duplicate faces)
76 
77  - After merging, any patches that no longer hold any face are
78  automatically removed from the boundary file (coupled patches are
79  preserved). This avoids the need for a follow-up \c createPatch run.
80 
81 \*---------------------------------------------------------------------------*/
82 
83 #include "argList.H"
84 #include "Time.H"
85 #include "syncTools.H"
86 #include "faceSet.H"
87 #include "pointSet.H"
88 #include "meshTools.H"
89 #include "polyTopoChange.H"
90 #include "polyRemoveFace.H"
91 #include "polyModifyFace.H"
92 #include "indirectPrimitivePatch.H"
93 #include "processorPolyPatch.H"
94 #include "localPointRegion.H"
95 #include "duplicatePoints.H"
96 #include "ReadFields.H"
97 #include "volFields.H"
98 #include "surfaceFields.H"
99 #include "processorMeshes.H"
100 #include "fvMeshTools.H"
101 
102 using namespace Foam;
103 
104 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
105 
106 void insertDuplicateMerge
107 (
108  const polyMesh& mesh,
109  const labelList& boundaryFaces,
110  const labelList& duplicates,
111  polyTopoChange& meshMod
112 )
113 {
114  const faceList& faces = mesh.faces();
115  const labelList& faceOwner = mesh.faceOwner();
116  const faceZoneMesh& faceZones = mesh.faceZones();
117 
118  forAll(duplicates, bFacei)
119  {
120  label otherFacei = duplicates[bFacei];
121 
122  if (otherFacei != -1 && otherFacei > bFacei)
123  {
124  // Two duplicate faces. Merge.
125 
126  label face0 = boundaryFaces[bFacei];
127  label face1 = boundaryFaces[otherFacei];
128 
129  label own0 = faceOwner[face0];
130  label own1 = faceOwner[face1];
131 
132  if (own0 < own1)
133  {
134  // Use face0 as the new internal face.
135  label zoneID = faceZones.whichZone(face0);
136  bool zoneFlip = false;
137 
138  if (zoneID >= 0)
139  {
140  const faceZone& fZone = faceZones[zoneID];
141  zoneFlip = fZone.flipMap()[fZone.whichFace(face0)];
142  }
143 
144  meshMod.setAction(polyRemoveFace(face1));
145  meshMod.setAction
146  (
148  (
149  faces[face0], // modified face
150  face0, // label of face being modified
151  own0, // owner
152  own1, // neighbour
153  false, // face flip
154  -1, // patch for face
155  false, // remove from zone
156  zoneID, // zone for face
157  zoneFlip // face flip in zone
158  )
159  );
160  }
161  else
162  {
163  // Use face1 as the new internal face.
164  label zoneID = faceZones.whichZone(face1);
165  bool zoneFlip = false;
166 
167  if (zoneID >= 0)
168  {
169  const faceZone& fZone = faceZones[zoneID];
170  zoneFlip = fZone.flipMap()[fZone.whichFace(face1)];
171  }
172 
173  meshMod.setAction(polyRemoveFace(face0));
174  meshMod.setAction
175  (
177  (
178  faces[face1], // modified face
179  face1, // label of face being modified
180  own1, // owner
181  own0, // neighbour
182  false, // face flip
183  -1, // patch for face
184  false, // remove from zone
185  zoneID, // zone for face
186  zoneFlip // face flip in zone
187  )
188  );
189  }
190  }
191  }
192 }
193 
194 
195 label patchSize(const polyMesh& mesh, const labelList& patchIDs)
196 {
198 
199  label sz = 0;
200  forAll(patchIDs, i)
201  {
202  const polyPatch& pp = patches[patchIDs[i]];
203  sz += pp.size();
204  }
205  return sz;
206 }
207 
208 
209 labelList patchFaces(const polyMesh& mesh, const labelList& patchIDs)
210 {
212 
213  labelList faceIDs(patchSize(mesh, patchIDs));
214  label sz = 0;
215  forAll(patchIDs, i)
216  {
217  const polyPatch& pp = patches[patchIDs[i]];
218 
219  forAll(pp, ppi)
220  {
221  faceIDs[sz++] = pp.start()+ppi;
222  }
223  }
224 
225  if (faceIDs.size() != sz)
226  {
228  }
229 
230  return faceIDs;
231 }
232 
233 
234 labelList findBaffles(const polyMesh& mesh, const labelList& boundaryFaces)
235 {
236  // Get all duplicate face labels (in boundaryFaces indices!).
238  (
239  mesh,
240  boundaryFaces
241  );
242 
243 
244  // Check that none are on processor patches
246 
247  forAll(duplicates, bFacei)
248  {
249  if (duplicates[bFacei] != -1)
250  {
251  label facei = boundaryFaces[bFacei];
252  label patchi = patches.whichPatch(facei);
253 
254  if (isA<processorPolyPatch>(patches[patchi]))
255  {
257  << "Duplicate face " << facei
258  << " is on a processorPolyPatch."
259  << "This is not allowed." << nl
260  << "Face:" << facei
261  << " is on patch:" << patches[patchi].name()
262  << abort(FatalError);
263  }
264  }
265  }
266 
267 
268  // Write to faceSet for ease of post-processing.
269  {
270  faceSet duplicateSet
271  (
272  mesh,
273  "duplicateFaces",
274  mesh.nBoundaryFaces()/256
275  );
276 
277  forAll(duplicates, bFacei)
278  {
279  label otherFacei = duplicates[bFacei];
280 
281  if (otherFacei != -1 && otherFacei > bFacei)
282  {
283  duplicateSet.insert(boundaryFaces[bFacei]);
284  duplicateSet.insert(boundaryFaces[otherFacei]);
285  }
286  }
287 
288  Info<< "Writing " << returnReduce(duplicateSet.size(), sumOp<label>())
289  << " duplicate faces to faceSet " << duplicateSet.objectPath()
290  << nl << endl;
291  duplicateSet.write();
292  }
293 
294  return duplicates;
295 }
296 
297 
298 int main(int argc, char *argv[])
299 {
301  (
302  "Detect faces that share points (baffles).\n"
303  "Merge them or duplicate the points."
304  );
305 
306  #include "addOverwriteOption.H"
307  #include "addRegionOption.H"
309  (
310  "dict",
311  "file",
312  "Specify a dictionary to read actions from"
313  );
315  (
316  "detectOnly",
317  "Find baffles only, but do not merge or split them"
318  );
320  (
321  "split",
322  "Topologically split duplicate surfaces"
323  );
324 
325  argList::noFunctionObjects(); // Never use function objects
326 
327  #include "setRootCase.H"
328  #include "createTime.H"
329  #include "createNamedMesh.H"
330 
331  const word oldInstance = mesh.pointsInstance();
333 
334  const bool readDict = args.found("dict");
335  const bool split = args.found("split");
336  const bool overwrite = args.found("overwrite");
337  const bool detectOnly = args.found("detectOnly");
338 
339  if (readDict && (split || detectOnly))
340  {
342  << "Use of dictionary for settings not compatible with"
343  << " using command line arguments for \"split\""
344  << " or \"detectOnly\"" << exit(FatalError);
345  }
346 
347 
348  labelList detectPatchIDs;
349  labelList splitPatchIDs;
350  labelList mergePatchIDs;
351 
352  if (readDict)
353  {
354  const word dictName;
355  #include "setSystemMeshDictionaryIO.H"
356 
357  Info<< "Reading " << dictIO.name() << nl << endl;
359 
360  if (dict.found("detect"))
361  {
362  detectPatchIDs = patches.patchSet
363  (
364  dict.subDict("detect").get<wordRes>("patches")
365  ).sortedToc();
366 
367  Info<< "Detecting baffles on " << detectPatchIDs.size()
368  << " patches with "
369  << returnReduce(patchSize(mesh, detectPatchIDs), sumOp<label>())
370  << " faces" << endl;
371  }
372  if (dict.found("merge"))
373  {
374  mergePatchIDs = patches.patchSet
375  (
376  dict.subDict("merge").get<wordRes>("patches")
377  ).sortedToc();
378 
379  Info<< "Merge baffles on " << mergePatchIDs.size()
380  << " patches with "
381  << returnReduce(patchSize(mesh, mergePatchIDs), sumOp<label>())
382  << " faces" << endl;
383  }
384  if (dict.found("split"))
385  {
386  splitPatchIDs = patches.patchSet
387  (
388  dict.subDict("split").get<wordRes>("patches")
389  ).sortedToc();
390 
391  Info<< "Split baffles on " << splitPatchIDs.size()
392  << " patches with "
393  << returnReduce(patchSize(mesh, splitPatchIDs), sumOp<label>())
394  << " faces" << endl;
395  }
396  }
397  else
398  {
399  if (detectOnly)
400  {
401  detectPatchIDs = identity(patches.size());
402  }
403  else if (split)
404  {
405  splitPatchIDs = identity(patches.size());
406  }
407  else
408  {
409  mergePatchIDs = identity(patches.size());
410  }
411  }
412 
413 
414  if (detectPatchIDs.size())
415  {
416  findBaffles(mesh, patchFaces(mesh, detectPatchIDs));
417 
418  if (detectOnly)
419  {
420  return 0;
421  }
422  }
423 
424 
425 
426  // Read objects in time directory
427  IOobjectList objects(mesh, runTime.timeName());
428 
429  // Read vol fields.
430 
432  ReadFields(mesh, objects, vsFlds);
433 
435  ReadFields(mesh, objects, vvFlds);
436 
438  ReadFields(mesh, objects, vstFlds);
439 
440  PtrList<volSymmTensorField> vsymtFlds;
441  ReadFields(mesh, objects, vsymtFlds);
442 
444  ReadFields(mesh, objects, vtFlds);
445 
446  // Read surface fields.
447 
449  ReadFields(mesh, objects, ssFlds);
450 
452  ReadFields(mesh, objects, svFlds);
453 
455  ReadFields(mesh, objects, sstFlds);
456 
458  ReadFields(mesh, objects, ssymtFlds);
459 
461  ReadFields(mesh, objects, stFlds);
462 
463 
464 
465  if (mergePatchIDs.size())
466  {
467  Info<< "Merging duplicate faces" << nl << endl;
468 
469  // Mesh change engine
470  polyTopoChange meshMod(mesh);
471 
472  const labelList boundaryFaces(patchFaces(mesh, mergePatchIDs));
473 
474  // Get all duplicate face pairs (in boundaryFaces indices!).
475  labelList duplicates(findBaffles(mesh, boundaryFaces));
476 
477  // Merge into internal faces.
478  insertDuplicateMerge(mesh, boundaryFaces, duplicates, meshMod);
479 
480  if (!overwrite)
481  {
482  ++runTime;
483  }
484 
485  // Change the mesh. No inflation.
486  autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false);
487 
488  // Update fields
489  mesh.updateMesh(map());
490 
491  // Move mesh (since morphing does not do this)
492  if (map().hasMotionPoints())
493  {
494  mesh.movePoints(map().preMotionPoints());
495  }
496 
497  // Remove patches that no longer have any face after the merge
498  // (coupled and processor patches are preserved by the helper).
499  // This mirrors the behaviour of createPatch / createBaffles and
500  // removes the need for a follow-up createPatch run.
501  {
502  const wordList oldPatchNames(mesh.boundaryMesh().names());
503 
504  const labelList newToOld
505  (
507  );
508 
509  if (newToOld.size() != oldPatchNames.size())
510  {
511  Info<< "Removing zero-sized patches:" << nl << incrIndent;
512  forAll(oldPatchNames, patchi)
513  {
514  if (!newToOld.found(patchi))
515  {
516  Info<< indent << oldPatchNames[patchi]
517  << " at position " << patchi
518  << endl;
519  }
520  }
521  Info<< decrIndent << endl;
522  }
523  }
524 
525  if (overwrite)
526  {
527  mesh.setInstance(oldInstance);
528  }
529  Info<< "Writing mesh to time " << runTime.timeName() << endl;
530  mesh.write();
531  }
532 
533 
534  if (splitPatchIDs.size())
535  {
536  Info<< "Topologically splitting duplicate surfaces"
537  << ", i.e. duplicating points internal to duplicate surfaces"
538  << nl << endl;
539 
540  // Determine points on split patches
541  DynamicList<label> candidates;
542  {
543  label sz = 0;
544  forAll(splitPatchIDs, i)
545  {
546  sz += patches[splitPatchIDs[i]].nPoints();
547  }
548  candidates.setCapacity(sz);
549 
550  bitSet isCandidate(mesh.nPoints());
551  forAll(splitPatchIDs, i)
552  {
553  const labelList& mp = patches[splitPatchIDs[i]].meshPoints();
554  forAll(mp, mpi)
555  {
556  label pointi = mp[mpi];
557  if (isCandidate.set(pointi))
558  {
559  candidates.append(pointi);
560  }
561  }
562  }
563  }
564 
565 
566  // Analyse which points need to be duplicated
567  localPointRegion regionSide(mesh, candidates);
568 
569  // Point duplication engine
570  duplicatePoints pointDuplicator(mesh);
571 
572  // Mesh change engine
573  polyTopoChange meshMod(mesh);
574 
575  // Insert topo changes
576  pointDuplicator.setRefinement(regionSide, meshMod);
577 
578  if (!overwrite)
579  {
580  ++runTime;
581  }
582 
583  // Change the mesh. No inflation.
584  autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false);
585 
586  // Update fields
587  mesh.updateMesh(map());
588 
589  // Move mesh (since morphing does not do this)
590  if (map().hasMotionPoints())
591  {
592  mesh.movePoints(map().preMotionPoints());
593  }
594 
595  if (overwrite)
596  {
597  mesh.setInstance(oldInstance);
598  }
599  Info<< "Writing mesh to time " << runTime.timeName() << endl;
600  mesh.write();
601 
604 
605  // Dump duplicated points (if any)
606  const labelList& pointMap = map().pointMap();
607 
608  labelList nDupPerPoint(map().nOldPoints(), Zero);
609 
610  pointSet dupPoints(mesh, "duplicatedPoints", 100);
611 
612  forAll(pointMap, pointi)
613  {
614  label oldPointi = pointMap[pointi];
615 
616  nDupPerPoint[oldPointi]++;
617 
618  if (nDupPerPoint[oldPointi] > 1)
619  {
620  dupPoints.insert(map().reversePointMap()[oldPointi]);
621  dupPoints.insert(pointi);
622  }
623  }
624 
625  Info<< "Writing " << returnReduce(dupPoints.size(), sumOp<label>())
626  << " duplicated points to pointSet "
627  << dupPoints.objectPath() << nl << endl;
628 
629  dupPoints.write();
630  }
631 
632  Info<< "End\n" << endl;
633 
634  return 0;
635 }
636 
637 
638 // ************************************************************************* //
Foam::surfaceFields.
Class containing data for face removal.
dictionary dict
static void noFunctionObjects(bool addWithOption=false)
Remove &#39;-noFunctionObjects&#39; option and ignore any occurrences.
Definition: argList.C:562
static void addNote(const string &note)
Add extra notes for the usage information.
Definition: argList.C:477
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:119
Ostream & indent(Ostream &os)
Indent stream.
Definition: Ostream.H:480
A list of face labels.
Definition: faceSet.H:47
wordList ReadFields(const typename GeoMesh::Mesh &mesh, const IOobjectList &objects, PtrList< GeometricField< Type, PatchField, GeoMesh >> &fields, const bool syncPar=true, const bool readOldTime=false)
Read Geometric fields of templated type.
List of IOobjects with searching and retrieving facilities. Implemented as a HashTable, so the various sorted methods should be used if traversing in parallel.
Definition: IOobjectList.H:55
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
Class describing modification of a face.
A set of point labels.
Definition: pointSet.H:47
label nPoints() const noexcept
Number of mesh points.
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:652
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:205
labelHashSet patchSet(const UList< wordRe > &select, const bool warnNotFound=true, const bool useGroups=true) const
Return the set of patch IDs corresponding to the given names.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
const word dictName("faMeshDefinition")
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:518
virtual void movePoints(const pointField &)
Move points, returns volumes swept by faces in motion.
Definition: fvMesh.C:884
Required Classes.
static void addBoolOption(const word &optName, const string &usage="", bool advanced=false)
Add a bool option to validOptions with usage information.
Definition: argList.C:389
void setCapacity(const label len)
Alter the size of the underlying storage.
Definition: DynamicListI.H:310
Field reading functions for post-processing utilities.
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T. FatalIOError if not found, or if the number of tokens is incorrect.
autoPtr< mapPolyMesh > changeMesh(polyMesh &mesh, const labelUList &patchMap, const bool inflate, const bool syncParallel=true, const bool orderCells=false, const bool orderPoints=false)
Inplace changes mesh without change of patches.
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary.
Definition: dictionary.C:441
Takes mesh with &#39;baffles&#39; (= boundary faces sharing points). Determines for selected points on bounda...
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry (const access) with the given keyword.
Definition: dictionaryI.H:104
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:50
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:400
static void removeFiles(const polyMesh &mesh)
Helper: remove all procAddressing files from mesh instance.
Determines the &#39;side&#39; for every face and connected to a singly-connected (through edges) region of fa...
Definition: regionSide.H:59
Required Classes.
static void removeFiles(const polyMesh &)
Helper: remove all sets files from mesh instance.
Definition: topoSet.C:693
const fileName & pointsInstance() const
Return the current instance directory for points.
Definition: polyMesh.C:838
Duplicate points.
virtual void updateMesh(const mapPolyMesh &mpm)
Update mesh corresponding to the given map.
Definition: fvMesh.C:960
dynamicFvMesh & mesh
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition: polyMesh.H:611
A class for handling words, derived from Foam::string.
Definition: word.H:63
wordList names() const
Return a list of patch names.
label size() const noexcept
The number of entries in the list.
Definition: UPtrListI.H:106
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1101
A List of wordRe with additional matching capabilities.
Definition: wordRes.H:53
static void addOption(const word &optName, const string &param="", const string &usage="", bool advanced=false)
Add an option to validOptions with usage information.
Definition: argList.C:400
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
T returnReduce(const T &value, BinaryOp bop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
void append(const T &val)
Copy append an element to the end of this list.
Definition: DynamicList.H:576
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1088
label whichPatch(const label meshFacei) const
Return patch index for a given mesh face index. Uses binary search.
errorManip< error > abort(error &err)
Definition: errorManip.H:139
virtual bool write(const bool writeOnProc=true) const
Write mesh using IO settings from time.
Definition: fvMesh.C:1068
A polyBoundaryMesh is a polyPatch list with registered IO, a reference to the associated polyMesh...
static word timeName(const scalar t, const int precision=precision_)
Return a time name for the given scalar time value formatted with the given precision.
Definition: Time.C:713
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition: polyMesh.H:673
Ostream & decrIndent(Ostream &os)
Decrement the indent level.
Definition: Ostream.H:498
label whichZone(const label objectIndex) const
Given a global object index, return the zone it is in.
Definition: ZoneMesh.C:410
static bool split(const std::string &line, std::string &key, std::string &val)
Definition: cpuInfo.C:32
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:58
void setInstance(const fileName &instance, const IOobjectOption::writeOption wOpt=IOobject::AUTO_WRITE)
Set the instance for mesh files.
Definition: polyMeshIO.C:29
labelList patchIDs
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
Definition: PtrList.H:56
List< Key > sortedToc() const
The table of contents (the keys) in sorted order.
Definition: HashTable.C:156
Direct mesh changes based on v1.3 polyTopoChange syntax.
const polyBoundaryMesh & patches
const boolList & flipMap() const noexcept
Return face flip map.
Definition: faceZone.H:389
static labelList findDuplicateFaces(const primitiveMesh &, const labelList &)
Helper routine to find baffles (two boundary faces using the.
messageStream Info
Information stream (stdout output on master, null elsewhere)
IOobject dictIO
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:76
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:60
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:69
label nBoundaryFaces() const noexcept
Number of boundary faces (== nFaces - nInternalFaces)
Foam::argList args(argc, argv)
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Definition: Ostream.H:489
const dimensionedScalar mp
Proton mass.
bool found(const word &optName) const
Return true if the named option is found.
Definition: argListI.H:171
static labelList removeEmptyPatches(fvMesh &, const bool validBoundary)
Remove zero sized patches. All but processor patches are.
Definition: fvMeshTools.C:442
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
Namespace for OpenFOAM.
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i), works like std::iota() but returning a...
label setAction(const topoAction &action)
For compatibility with polyTopoChange: set topological action.
label whichFace(const label meshFaceID) const
The local index of the given mesh face, -1 if not in the zone.
Definition: faceZone.H:394
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127