surfaceMeshExtract.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) 2017-2021 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 Application
28  surfaceMeshExtract
29 
30 Group
31  grpSurfaceUtilities
32 
33 Description
34  Extract patch or faceZone surfaces from a polyMesh.
35  Depending on output surface format triangulates faces.
36 
37  Region numbers on faces no guaranteed to be the same as the patch indices.
38 
39  Optionally only extracts named patches.
40 
41  If run in parallel, processor patches get filtered out by default and
42  the mesh is merged (based on topology).
43 
44 \*---------------------------------------------------------------------------*/
45 
46 #include "MeshedSurface.H"
47 #include "UnsortedMeshedSurface.H"
48 #include "argList.H"
49 #include "Time.H"
50 #include "polyMesh.H"
51 #include "emptyPolyPatch.H"
52 #include "processorPolyPatch.H"
53 #include "ListListOps.H"
55 #include "globalMeshData.H"
56 #include "globalIndex.H"
57 #include "timeSelector.H"
58 
59 using namespace Foam;
60 
61 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
62 
63 labelList getSelectedPatches
64 (
66  const wordRes& allow,
67  const wordRes& deny
68 )
69 {
70  // Name-based selection
71  labelList indices
72  (
74  (
75  patches,
76  allow,
77  deny,
79  )
80  );
81 
82 
83  // Remove undesirable patches
84 
85  label count = 0;
86  for (const label patchi : indices)
87  {
88  const polyPatch& pp = patches[patchi];
89 
90  if (isType<emptyPolyPatch>(pp))
91  {
92  continue;
93  }
94  else if (Pstream::parRun() && bool(isA<processorPolyPatch>(pp)))
95  {
96  break; // No processor patches for parallel output
97  }
98 
99  indices[count] = patchi;
100  ++count;
101  }
102 
103  indices.resize(count);
104 
105  return indices;
106 }
107 
108 
109 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
110 
111 int main(int argc, char *argv[])
112 {
114  (
115  "Extract patch or faceZone surfaces from a polyMesh."
116  " The name is historical, it only triangulates faces"
117  " when the output format requires it."
118  );
120 
121  // Less frequently used - reduce some clutter
122  argList::setAdvanced("decomposeParDict");
123  argList::setAdvanced("noFunctionObjects");
124 
125  argList::addArgument("output", "The output surface file");
126 
127  #include "addRegionOption.H"
129  (
130  "excludeProcPatches",
131  "Exclude processor patches"
132  );
134  (
135  "faceZones",
136  "wordRes",
137  "Specify single or multiple faceZones to extract\n"
138  "Eg, 'cells' or '( slice \"mfp-.*\" )'"
139  );
141  (
142  "patches",
143  "wordRes",
144  "Specify single patch or multiple patches to extract.\n"
145  "Eg, 'top' or '( front \".*back\" )'"
146  );
148  (
149  "excludePatches",
150  "wordRes",
151  "Specify single patch or multiple patches to exclude from writing."
152  " Eg, 'outlet' or '( inlet \".*Wall\" )'",
153  true // mark as an advanced option
154  );
155 
156  #include "setRootCase.H"
157  #include "createTime.H"
158 
159  const auto userOutFileName = args.get<fileName>(1);
160 
161  if (!userOutFileName.hasExt())
162  {
164  << "Missing extension on output name " << userOutFileName
165  << exit(FatalError);
166  }
167 
168  Info<< "Extracting surface from boundaryMesh ..." << nl << nl;
169 
170  const bool includeProcPatches =
171  !(
172  args.found("excludeProcPatches")
173  || Pstream::parRun()
174  );
175 
176  if (includeProcPatches)
177  {
178  Info<< "Including all processor patches." << nl << endl;
179  }
180  else if (Pstream::parRun())
181  {
182  Info<< "Excluding all processor patches." << nl << endl;
183  }
184 
185  wordRes includePatches, excludePatches;
186  if (args.readListIfPresent<wordRe>("patches", includePatches))
187  {
188  Info<< "Including patches " << flatOutput(includePatches)
189  << nl << endl;
190  }
191  if (args.readListIfPresent<wordRe>("excludePatches", excludePatches))
192  {
193  Info<< "Excluding patches " << flatOutput(excludePatches)
194  << nl << endl;
195  }
196 
197  // Non-mandatory
198  const wordRes selectedFaceZones(args.getList<wordRe>("faceZones", false));
199  if (selectedFaceZones.size())
200  {
201  Info<< "Including faceZones " << flatOutput(selectedFaceZones)
202  << nl << endl;
203  }
204 
205  Info<< "Reading mesh from time " << runTime.value() << endl;
206 
207  #include "createNamedPolyMesh.H"
208 
209  // User specified times
211 
212  forAll(timeDirs, timeIndex)
213  {
214  runTime.setTime(timeDirs[timeIndex], timeIndex);
215  Info<< "Time [" << timeIndex << "] = " << runTime.timeName();
216 
217  fileName outFileName;
218  if (timeDirs.size() == 1)
219  {
220  outFileName = userOutFileName;
221  }
222  else
223  {
225  if (timeIndex && meshState == polyMesh::UNCHANGED)
226  {
227  Info<<" ... no mesh change." << nl;
228  continue;
229  }
230 
231  // The filename based on the original, but with additional
232  // time information. The extension was previously checked that
233  // it exists
234  const auto dot = userOutFileName.rfind('.');
235 
236  outFileName =
237  userOutFileName.substr(0, dot) + "_"
238  + Foam::name(runTime.value()) + "."
239  + userOutFileName.ext();
240  }
241 
242  Info<< nl;
243 
244  // Create local surface from:
245  // - explicitly named patches only (-patches (at your option)
246  // - all patches (default in sequential mode)
247  // - all non-processor patches (default in parallel mode)
248  // - all non-processor patches (sequential mode, -excludeProcPatches
249  // (at your option)
250 
251  // Construct table of patches to include.
253 
255  (
256  (includePatches.size() || excludePatches.size())
257  ? getSelectedPatches(bMesh, includePatches, excludePatches)
258  : includeProcPatches
259  ? identity(bMesh.size())
261  );
262 
263  labelList faceZoneIds;
264 
265  const faceZoneMesh& fzm = mesh.faceZones();
266 
267  if (selectedFaceZones.size())
268  {
269  faceZoneIds = fzm.indices(selectedFaceZones);
270 
271  Info<< "Additionally extracting faceZones "
272  << fzm.names(selectedFaceZones) << nl;
273  }
274 
275 
276  // From (name of) patch to compact 'zone' index
277  HashTable<label> compactZoneID(1024);
278  // Mesh face and compact zone indx
279  DynamicList<label> faceLabels;
280  DynamicList<label> compactZones;
281 
282  {
283  // Collect sizes. Hash on names to handle local-only patches (e.g.
284  // processor patches)
285  HashTable<label> patchSize(1024);
286  label nFaces = 0;
287  for (const label patchi : patchIds)
288  {
289  const polyPatch& pp = bMesh[patchi];
290  patchSize.insert(pp.name(), pp.size());
291  nFaces += pp.size();
292  }
293 
294  HashTable<label> zoneSize(1024);
295  for (const label zonei : faceZoneIds)
296  {
297  const faceZone& pp = fzm[zonei];
298  zoneSize.insert(pp.name(), pp.size());
299  nFaces += pp.size();
300  }
301 
302 
305 
306 
307  // Allocate compact numbering for all patches/faceZones
308  forAllConstIters(patchSize, iter)
309  {
310  compactZoneID.insert(iter.key(), compactZoneID.size());
311  }
312 
313  forAllConstIters(zoneSize, iter)
314  {
315  compactZoneID.insert(iter.key(), compactZoneID.size());
316  }
317 
318 
319  Pstream::mapCombineScatter(compactZoneID);
320 
321 
322  // Rework HashTable into labelList just for speed of conversion
323  labelList patchToCompactZone(bMesh.size(), -1);
324  labelList faceZoneToCompactZone(bMesh.size(), -1);
325  forAllConstIters(compactZoneID, iter)
326  {
327  label patchi = bMesh.findPatchID(iter.key());
328  if (patchi != -1)
329  {
330  patchToCompactZone[patchi] = iter.val();
331  }
332  else
333  {
334  label zoneI = fzm.findZoneID(iter.key());
335  faceZoneToCompactZone[zoneI] = iter.val();
336  }
337  }
338 
339 
340  faceLabels.setCapacity(nFaces);
341  compactZones.setCapacity(nFaces);
342 
343  // Collect faces on patches
344  for (const label patchi : patchIds)
345  {
346  const polyPatch& pp = bMesh[patchi];
347  forAll(pp, i)
348  {
349  faceLabels.append(pp.start()+i);
350  compactZones.append(patchToCompactZone[pp.index()]);
351  }
352  }
353  // Collect faces on faceZones
354  for (const label zonei : faceZoneIds)
355  {
356  const faceZone& pp = fzm[zonei];
357  forAll(pp, i)
358  {
359  faceLabels.append(pp[i]);
360  compactZones.append(faceZoneToCompactZone[pp.index()]);
361  }
362  }
363  }
364 
365 
366  // Addressing engine for all faces
367  uindirectPrimitivePatch allBoundary
368  (
369  UIndirectList<face>(mesh.faces(), faceLabels),
370  mesh.points()
371  );
372 
373 
374  // Find correspondence to master points
375  labelList pointToGlobal;
376  labelList uniqueMeshPoints;
378  (
379  allBoundary.meshPoints(),
380  allBoundary.meshPointMap(),
381  pointToGlobal,
382  uniqueMeshPoints
383  );
384 
385  // Gather all unique points on master
386  List<pointField> gatheredPoints(Pstream::nProcs());
387  gatheredPoints[Pstream::myProcNo()] = pointField
388  (
389  mesh.points(),
390  uniqueMeshPoints
391  );
392  Pstream::gatherList(gatheredPoints);
393 
394  // Gather all faces
395  List<faceList> gatheredFaces(Pstream::nProcs());
396  gatheredFaces[Pstream::myProcNo()] = allBoundary.localFaces();
397  forAll(gatheredFaces[Pstream::myProcNo()], i)
398  {
400  (
401  pointToGlobal,
402  gatheredFaces[Pstream::myProcNo()][i]
403  );
404  }
405  Pstream::gatherList(gatheredFaces);
406 
407  // Gather all ZoneIDs
408  List<labelList> gatheredZones(Pstream::nProcs());
409  gatheredZones[Pstream::myProcNo()].transfer(compactZones);
410  Pstream::gatherList(gatheredZones);
411 
412  // On master combine all points, faces, zones
413  if (Pstream::master())
414  {
415  pointField allPoints = ListListOps::combine<pointField>
416  (
417  gatheredPoints,
419  );
420  gatheredPoints.clear();
421 
422  faceList allFaces = ListListOps::combine<faceList>
423  (
424  gatheredFaces,
426  );
427  gatheredFaces.clear();
428 
429  labelList allZones = ListListOps::combine<labelList>
430  (
431  gatheredZones,
433  );
434  gatheredZones.clear();
435 
436 
437  // Zones
438  surfZoneIdentifierList surfZones(compactZoneID.size());
439  forAllConstIters(compactZoneID, iter)
440  {
441  surfZones[*iter] = surfZoneIdentifier(iter.key(), *iter);
442  Info<< "surfZone " << *iter
443  << " : " << surfZones[*iter].name()
444  << endl;
445  }
446 
447  UnsortedMeshedSurface<face> unsortedFace
448  (
449  std::move(allPoints),
450  std::move(allFaces),
451  std::move(allZones),
452  surfZones
453  );
454 
455 
456  MeshedSurface<face> sortedFace(unsortedFace);
457 
458  fileName globalCasePath
459  (
460  outFileName.isAbsolute()
461  ? outFileName
462  : (
464  ? runTime.globalPath()/outFileName
465  : runTime.path()/outFileName
466  )
467  );
468 
469  Info<< "Writing merged surface to " << globalCasePath << endl;
470 
471  sortedFace.write(globalCasePath);
472  }
473  }
474 
475  Info<< "End\n" << endl;
476 
477  return 0;
478 }
479 
480 
481 // ************************************************************************* //
Foam::Pstream::mapCombineGather
static void mapCombineGather(const List< commsStruct > &comms, Container &Values, const CombineOp &cop, const int tag, const label comm)
Definition: combineGatherScatter.C:545
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
runTime
engineTime & runTime
Definition: createEngineTime.H:13
Foam::polyMesh::points
virtual const pointField & points() const
Definition: polyMesh.C:1062
Foam::accessOp
Definition: UList.H:683
Foam::fileName
A class for handling file names.
Definition: fileName.H:71
uindirectPrimitivePatch.H
Foam::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:59
Foam::DynamicList< label >
ListListOps.H
globalMeshData.H
globalIndex.H
Foam::TimePaths::processorCase
bool processorCase() const noexcept
Definition: TimePathsI.H:29
Foam::Time::timeName
static word timeName(const scalar t, const int precision=precision_)
Definition: Time.C:773
Foam::dot
void dot(FieldField< Field1, typename innerProduct< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
Definition: FieldFieldFunctions.C:937
Foam::argList::addNote
static void addNote(const string &note)
Definition: argList.C:405
Foam::UPstream::master
static bool master(const label communicator=worldComm)
Definition: UPstream.H:453
Foam::argList::readListIfPresent
bool readListIfPresent(const word &optName, List< T > &list) const
Definition: argListI.H:387
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Definition: polyMesh.H:440
Foam::endl
Ostream & endl(Ostream &os)
Definition: Ostream.H:381
Foam::dimensioned::value
const Type & value() const
Definition: dimensionedType.C:427
Foam::word::ext
word ext() const
Definition: word.C:119
polyMesh.H
Foam::argList::get
T get(const label index) const
Definition: argListI.H:271
Foam::wordRe
A wordRe is a Foam::word, but can contain a regular expression for matching words or strings.
Definition: wordRe.H:78
createNamedPolyMesh.H
Required Variables.
Foam::inplaceRenumber
void inplaceRenumber(const labelUList &oldToNew, IntListType &input)
Definition: ListOpsTemplates.C:54
Foam::surfZoneIdentifier
Identifies a surface patch/zone by name and index, with optional geometric type.
Definition: surfZoneIdentifier.H:55
Foam::DynamicList::setCapacity
void setCapacity(const label len)
Definition: DynamicListI.H:296
Foam::ZoneMesh::indices
labelList indices(const wordRe &matcher, const bool useGroups=true) const
forAll
#define forAll(list, i)
Definition: stdFoam.H:349
Foam::globalMeshData::mergePoints
autoPtr< globalIndex > mergePoints(labelList &pointToGlobal, labelList &uniquePoints) const
Definition: globalMeshData.C:2367
Foam::fvMesh::readUpdate
virtual readUpdateState readUpdate()
Definition: fvMesh.C:641
UnsortedMeshedSurface.H
Foam::argList::addArgument
static void addArgument(const string &argName, const string &usage="")
Definition: argList.C:294
patchIds
labelList patchIds
Definition: convertProcessorPatches.H:61
Foam::Field
Generic templated field type.
Definition: Field.H:59
Foam::faceZone
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:60
Foam::UnsortedMeshedSurface
A surface geometry mesh, in which the surface zone information is conveyed by the 'zoneId' associated...
Definition: MeshedSurface.H:79
Foam::Info
messageStream Info
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:64
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Definition: DynamicListI.H:504
argList.H
addRegionOption.H
Foam::ZoneMesh< faceZone, polyMesh >
Foam::polyMesh::UNCHANGED
@ UNCHANGED
Definition: polyMesh.H:88
Foam::polyMesh::faceZones
const faceZoneMesh & faceZones() const noexcept
Definition: polyMesh.H:482
Foam::nameOp
Definition: word.H:247
Foam::argList::setAdvanced
static void setAdvanced(const word &optName, bool advanced=true)
Definition: argList.C:347
Foam::stringListOps::findMatching
labelList findMatching(const StringListType &input, const wordRes &allow, const wordRes &deny=wordRes(), AccessOp aop=noOp())
Foam::FatalError
error FatalError
processorPolyPatch.H
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::Ostream::write
virtual bool write(const token &tok)=0
Foam
Definition: atmBoundaryLayer.C:26
Foam::flatOutput
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Definition: FlatOutput.H:217
Foam::patchIdentifier::index
label index() const noexcept
Definition: patchIdentifier.H:143
Foam::ZoneMesh::findZoneID
label findZoneID(const word &zoneName) const
Definition: ZoneMesh.C:512
Foam::polyPatch::start
label start() const
Definition: polyPatch.H:357
emptyPolyPatch.H
Foam::ZoneMesh::names
wordList names() const
Definition: ZoneMesh.C:298
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
Foam::zoneIdentifier::index
label index() const noexcept
Definition: zoneIdentifier.H:131
Foam::polyMesh::readUpdateState
readUpdateState
Definition: polyMesh.H:86
Foam::HashTable< label >
Foam::argList::addBoolOption
static void addBoolOption(const word &optName, const string &usage="", bool advanced=false)
Definition: argList.C:317
Time.H
Foam::autoPtr
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: HashPtrTable.H:49
setRootCase.H
Foam::polyMesh::faces
virtual const faceList & faces() const
Definition: polyMesh.C:1087
FatalErrorInFunction
#define FatalErrorInFunction
Definition: error.H:465
Foam::Pstream::gatherList
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Definition: gatherScatterList.C:46
nNonProcessor
const label nNonProcessor
Definition: printMeshSummary.H:23
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=worldComm)
Definition: UPstream.H:459
Foam::nl
constexpr char nl
Definition: Ostream.H:424
Foam::Time::path
fileName path() const
Definition: Time.H:354
forAllConstIters
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
Foam::Pstream::mapCombineScatter
static void mapCombineScatter(const List< commsStruct > &comms, Container &Values, const int tag, const label comm)
Definition: combineGatherScatter.C:660
Foam::zoneIdentifier::name
const word & name() const noexcept
Definition: zoneIdentifier.H:119
Foam::BitOps::count
unsigned int count(const UList< bool > &bools, const bool val=true)
Definition: BitOps.H:75
Foam::timeSelector::addOptions
static void addOptions(const bool constant=true, const bool withZero=false)
Definition: timeSelector.C:95
Foam::UPstream::parRun
static bool & parRun() noexcept
Definition: UPstream.H:429
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::Time::setTime
virtual void setTime(const Time &t)
Definition: Time.C:996
Foam::identity
labelList identity(const label len, label start=0)
Definition: labelList.C:31
Foam::wordRes
A List of wordRe with additional matching capabilities.
Definition: wordRes.H:47
timeSelector.H
createTime.H
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:59
Foam::argList::getList
List< T > getList(const label index) const
Foam::TimePaths::globalPath
fileName globalPath() const
Definition: TimePathsI.H:73
Foam::name
word name(const expressions::valueTypeCode typeCode)
Definition: exprTraits.C:52
Foam::UIndirectList
A List with indirect addressing.
Definition: faMatrix.H:56
Foam::DelaunayMeshTools::allPoints
tmp< pointField > allPoints(const Triangulation &t)
Foam::patchIdentifier::name
const word & name() const noexcept
Definition: patchIdentifier.H:131
timeIndex
label timeIndex
Definition: getTimeIndex.H:24
Foam::plusEqOp
Definition: ops.H:66
Foam::polyMesh::globalData
const globalMeshData & globalData() const
Definition: polyMesh.C:1288
Foam::timeSelector::select0
static instantList select0(Time &runTime, const argList &args)
Definition: timeSelector.C:228
Foam::MeshedSurface< face >
Foam::argList::addOption
static void addOption(const word &optName, const string &param="", const string &usage="", bool advanced=false)
Definition: argList.C:328
args
Foam::argList args(argc, argv)
Foam::fileName::isAbsolute
static bool isAbsolute(const std::string &str)
Definition: fileNameI.H:129
Foam::UPstream::nProcs
static label nProcs(const label communicator=worldComm)
Definition: UPstream.H:441
Foam::argList::found
bool found(const word &optName) const
Definition: argListI.H:171
MeshedSurface.H
Foam::PrimitivePatch
A list of faces which address into the list of points.
Definition: PrimitivePatch.H:75