faceZoneSet.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-2017 OpenFOAM Foundation
9  Copyright (C) 2018-2024 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 \*---------------------------------------------------------------------------*/
28 
29 #include "faceZoneSet.H"
30 #include "mapPolyMesh.H"
31 #include "polyMesh.H"
32 #include "setToFaceZone.H"
33 #include "setsToFaceZone.H"
34 #include "syncTools.H"
35 #include "ListOps.H"
36 
38 
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 
41 namespace Foam
42 {
43  defineTypeName(faceZoneSet);
44  addToRunTimeSelectionTable(topoSet, faceZoneSet, word);
47 }
48 
49 
50 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
51 
53 {
54  if (flipMap_.size() == addressing_.size())
55  {
56  labelList order(Foam::sortedOrder(addressing_));
57  addressing_ = labelUIndList(addressing_, order)();
58  flipMap_ = boolUIndList(flipMap_, order)();
59  }
60  else
61  {
62  Foam::sort(addressing_);
63  flipMap_.resize_nocopy(addressing_.size());
64  flipMap_ = false;
65  }
66 
68  faceSet::reserve(addressing_.size());
69  faceSet::set(addressing_);
70 }
71 
72 
73 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
74 
76 (
77  const polyMesh& mesh,
78  const word& name,
79  const label initialCapacity,
81 )
82 :
83  faceSet(mesh, name, initialCapacity, wOpt), // Construct no-read
84  mesh_(mesh)
85 {}
86 
87 
89 (
90  const polyMesh& mesh,
91  const word& name,
94 )
95 :
96  faceZoneSet(mesh, name, label(0), wOpt) // Construct no-read
97 {
98  const auto& zones = mesh.faceZones();
99  const auto* zonePtr = zones.cfindZone(name);
100 
101  if (!zonePtr)
102  {
104  {
106  << "Zone named " << name << " not found. "
107  << "List of available zone names: " << zones.names() << nl
108  << exit(FatalError);
109  }
110  }
111  else if (IOobjectOption::isAnyRead(rOpt))
112  {
113  const auto& zn = *zonePtr;
114  addressing_ = zn.addressing();
115  flipMap_ = zn.flipMap();
116  }
118  updateSet();
119  check(mesh.nFaces());
120 }
121 
122 
124 (
125  const polyMesh& mesh,
126  const word& name,
127  const topoSet& set,
129 )
130 :
131  faceZoneSet(mesh, name, label(0), wOpt) // Construct no-read
132 {
133  const auto* zonePtr = isA<faceZoneSet>(set);
134 
135  if (zonePtr)
136  {
137  addressing_ = zonePtr->addressing();
138  flipMap_ = zonePtr->flipMap();
139  }
140  else
141  {
142  // No flipMap for faceSet - handled in updateSet()
143  addressing_ = set.sortedToc();
144  }
146  updateSet();
147 }
148 
149 
150 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
151 
152 void Foam::faceZoneSet::invert(const label maxLen)
153 {
154  // Count
155  label n = 0;
156 
157  for (label id = 0; id < maxLen; ++id)
158  {
159  if (!topoSet::contains(id))
160  {
161  ++n;
162  }
163  }
164 
165  // Fill
166  addressing_.resize_nocopy(n);
167  flipMap_.resize_nocopy(n);
168  n = 0;
169 
170  for (label id = 0; id < maxLen; ++id)
171  {
172  if (!topoSet::contains(id))
173  {
174  addressing_[n] = id;
175  flipMap_[n] = false; //? or true?
176  ++n;
177  }
178  }
179  updateSet();
180 }
181 
182 
183 void Foam::faceZoneSet::subset
184 (
185  const word& setName,
186  const labelUList& setAddressing,
187  const UList<bool>& setFlipMap
188 )
189 {
190  label nConflict = 0;
191 
192  DynamicList<label> newAddressing(addressing_.size());
193  DynamicList<bool> newFlipMap(flipMap_.size());
194 
195  Map<label> faceToIndex(invertToMap(addressing_));
196 
197  forAll(setAddressing, i)
198  {
199  const label facei = setAddressing[i];
200 
201  const auto iter = faceToIndex.cfind(facei);
202 
203  if (iter.good())
204  {
205  const label index = iter.val();
206 
207  if (setFlipMap.size() && (setFlipMap[i] != flipMap_[index]))
208  {
209  ++nConflict;
210  }
211  newAddressing.append(facei);
212  newFlipMap.append(flipMap_[index]);
213  }
214  }
215 
216  if (nConflict)
217  {
219  << "subset : there are " << nConflict
220  << " faces with different orientation in faceZoneSets "
221  << name() << " and " << setName << endl;
222  }
224  addressing_.transfer(newAddressing);
225  flipMap_.transfer(newFlipMap);
226  updateSet();
227 }
228 
229 
230 void Foam::faceZoneSet::subset(const topoSet& set)
231 {
232  const auto* zonePtr = isA<faceZoneSet>(set);
233 
234  if (zonePtr)
235  {
236  subset(zonePtr->name(), zonePtr->addressing(), zonePtr->flipMap());
237  }
238  else
239  {
240  // Assume a faceSet. Ignore flipMap
241  subset
242  (
243  set.name(),
244  refCast<const faceSet>(set).sortedToc(),
246  );
247  }
248 }
249 
250 
251 void Foam::faceZoneSet::subset(const labelUList& elems)
252 {
253  subset(word::null, elems, boolList::null());
254 }
255 
256 
257 void Foam::faceZoneSet::addSet
258 (
259  const word& setName,
260  const labelUList& setAddressing,
261  const UList<bool>& setFlipMap
262 )
263 {
264  label nConflict = 0;
265 
266  DynamicList<label> newAddressing(addressing_);
267  DynamicList<bool> newFlipMap(flipMap_);
268 
269  Map<label> faceToIndex(invertToMap(addressing_));
270 
271  forAll(setAddressing, i)
272  {
273  const label facei = setAddressing[i];
274  const auto iter = faceToIndex.cfind(facei);
275 
276  if (iter.good())
277  {
278  const label index = iter.val();
279 
280  if (setFlipMap.size() && (setFlipMap[i] != flipMap_[index]))
281  {
282  ++nConflict;
283  }
284  }
285  else
286  {
287  newAddressing.append(facei);
288  newFlipMap.append(setFlipMap.size() ? setFlipMap[i] : false);
289  }
290  }
291 
292  if (nConflict > 0)
293  {
295  << "addSet : there are " << nConflict
296  << " faces with different orientation in faceZonesSets "
297  << name() << " and " << setName << endl;
298  }
300  addressing_.transfer(newAddressing);
301  flipMap_.transfer(newFlipMap);
302  updateSet();
303 }
304 
305 
306 void Foam::faceZoneSet::addSet(const topoSet& set)
307 {
308  const auto* zonePtr = isA<faceZoneSet>(set);
309 
310  if (zonePtr)
311  {
312  addSet(zonePtr->name(), zonePtr->addressing(), zonePtr->flipMap());
313  }
314  else
315  {
316  // Assume a faceSet. Ignore flipMap
317  addSet
318  (
319  set.name(),
320  refCast<const faceSet>(set).sortedToc(),
322  );
323  }
324 }
325 
326 
327 void Foam::faceZoneSet::addSet(const labelUList& elems)
328 {
329  addSet(word::null, elems, boolList::null());
330 }
331 
332 
333 void Foam::faceZoneSet::subtractSet
334 (
335  const word& setName,
336  const labelUList& setAddressing,
337  const UList<bool>& setFlipMap
338 )
339 {
340  label nConflict = 0;
341 
342  DynamicList<label> newAddressing(addressing_.size());
343  DynamicList<bool> newFlipMap(flipMap_.size());
344 
345  Map<label> faceToIndex(invertToMap(setAddressing));
346 
347  forAll(addressing_, i)
348  {
349  const label facei = addressing_[i];
350 
351  const auto iter = faceToIndex.cfind(facei);
352 
353  if (iter.good())
354  {
355  const label index = iter.val();
356 
357  if (setFlipMap.size() && (setFlipMap[index] != flipMap_[i]))
358  {
359  ++nConflict;
360  }
361  }
362  else
363  {
364  // Not found in zoneSet so add
365  newAddressing.append(facei);
366  newFlipMap.append(setFlipMap.size() ? setFlipMap[i] : false);
367  }
368  }
369 
370  if (nConflict > 0)
371  {
373  << "subtractSet : there are " << nConflict
374  << " faces with different orientation in faceZonesSets "
375  << name() << " and " << setName << endl;
376  }
378  addressing_.transfer(newAddressing);
379  flipMap_.transfer(newFlipMap);
380  updateSet();
381 }
382 
383 
384 void Foam::faceZoneSet::subtractSet(const topoSet& set)
385 {
386  const auto* zonePtr = isA<faceZoneSet>(set);
387 
388  if (zonePtr)
389  {
390  subtractSet(zonePtr->name(), zonePtr->addressing(), zonePtr->flipMap());
391  }
392  else
393  {
394  // Assume a faceSet. Ignore flipMap
395  subtractSet
396  (
397  set.name(),
398  refCast<const faceSet>(set).sortedToc(),
400  );
401  }
402 }
403 
405 void Foam::faceZoneSet::subtractSet(const labelUList& elems)
406 {
407  subtractSet(word::null, elems, boolList::null());
408 }
409 
410 
412 {
413  // This routine serves two purposes
414  // 1. make sure that any previous faceZoneSet manipulation is
415  // consistent across coupled boundaries
416  // 2. push faceZone contents to faceSet (looses flip bit)
417 
418 
419  // Collect all current zone info
420  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
421 
422  // 0 : not in faceZone
423  // 1 : in faceZone and unflipped
424  //-1 : in faceZone and flipped
425  const label UNFLIPPED = 1;
426  const label FLIPPED = -1;
427  labelList myZoneFace(mesh.nFaces(), Zero);
428 
429  forAll(addressing_, i)
430  {
431  const label facei = addressing_[i];
432  myZoneFace[facei] =
433  (
434  flipMap_[i]
435  ? FLIPPED
436  : UNFLIPPED
437  );
438  }
439 
440  labelList neiZoneFace
441  (
442  SubList<label>
443  (
444  myZoneFace,
447  )
448  );
450 
451 
452  const bitSet isMasterFace(syncTools::getMasterFaces(mesh));
453 
454 
455  // Rebuild faceZone addressing and flipMap
456  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
457 
458  const labelHashSet& set = *this;
459 
460  DynamicList<label> newAddressing(set.size());
461  DynamicList<bool> newFlipMap(set.size());
462 
463  for (const label facei : set)
464  {
465  // See if any info from original. If so maintain flipMap.
466  if (facei < mesh.nInternalFaces())
467  {
468  newAddressing.append(facei);
469  newFlipMap.append(myZoneFace[facei] == FLIPPED);
470  }
471  else
472  {
473  const label myStat = myZoneFace[facei];
474  const label neiStat = neiZoneFace[facei-mesh.nInternalFaces()];
475 
476  if (myStat == 0)
477  {
478  // My face was not in zone. Check neighbour
479 
480  if (neiStat == UNFLIPPED)
481  {
482  // Neighbour is unflipped so I am flipped
483  newAddressing.append(facei);
484  newFlipMap.append(true);
485  }
486  else if (neiStat == FLIPPED)
487  {
488  newAddressing.append(facei);
489  newFlipMap.append(false);
490  }
491  else //if (neiStat == 0)
492  {
493  // neighbour face not in zone either. Masterface decides.
494  newAddressing.append(facei);
495  newFlipMap.append(!isMasterFace[facei]);
496  }
497  }
498  else
499  {
500  if (myStat == neiStat)
501  {
502  // Conflict. masterFace wins
503  newAddressing.append(facei);
504  if (isMasterFace[facei])
505  {
506  newFlipMap.append(myStat == FLIPPED);
507  }
508  else
509  {
510  newFlipMap.append(neiStat == UNFLIPPED);
511  }
512  }
513  else
514  {
515  newAddressing.append(facei);
516  newFlipMap.append(myStat == FLIPPED);
517  }
518  }
519  }
520  }
521 
522  addressing_.transfer(newAddressing);
523  flipMap_.transfer(newFlipMap);
524  updateSet();
525 }
526 
527 
528 Foam::label Foam::faceZoneSet::maxSize(const polyMesh& mesh) const
529 {
530  return mesh.nFaces();
531 }
532 
533 
535 (
536  IOstreamOption streamOpt,
537  const bool writeOnProc
538 ) const
539 {
540  // Write shadow faceSet
541  const word oldTypeName = typeName;
542  const_cast<word&>(type()) = faceSet::typeName;
543  bool ok = faceSet::writeObject(streamOpt, writeOnProc);
544  const_cast<word&>(type()) = oldTypeName;
545 
546  // Modify faceZone
547  auto& zones = const_cast<polyMesh&>(mesh_).faceZones();
548  auto* zonePtr = zones.findZone(name());
549 
550  if (zonePtr)
551  {
552  zonePtr->resetAddressing(addressing_, flipMap_);
553  }
554  else
555  {
556  zones.emplace_back
557  (
558  name(),
559  addressing_,
560  flipMap_,
561  zones.size(), // zoneID
562  zones
563  );
564  }
565  zones.clearAddressing();
567  return ok && zones.write(writeOnProc);
568 }
569 
570 
571 void Foam::faceZoneSet::updateMesh(const mapPolyMesh& morphMap)
572 {
573  DynamicList<label> newAddressing(addressing_.size());
574  DynamicList<bool> newFlipMap(flipMap_.size());
575 
576  forAll(addressing_, i)
577  {
578  label facei = addressing_[i];
579  label newFacei = morphMap.reverseFaceMap()[facei];
580  if (newFacei >= 0)
581  {
582  newAddressing.push_back(newFacei);
583  newFlipMap.push_back(flipMap_[i]);
584  }
585  }
586 
587  addressing_.transfer(newAddressing);
588  flipMap_.transfer(newFlipMap);
589 
590  updateSet();
591 }
592 
593 
595 (
596  Ostream& os,
597  const primitiveMesh& mesh,
598  const label maxLen
599 ) const
600 {
601  faceSet::writeDebug(os, mesh, maxLen);
602 }
603 
604 
605 // ************************************************************************* //
writeOption
Enumeration defining write preferences.
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
A list of face labels.
Definition: faceSet.H:47
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
void clearAddressing(const bool isMeshUpdate=false)
Clear addressing.
static bitSet getMasterFaces(const polyMesh &mesh)
Get per face whether it is uncoupled or a master of a coupled set of faces.
Definition: syncTools.C:119
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:608
labelList sortedOrder(const UList< T > &input)
Return the (stable) sort order for the list.
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:195
Cell-face mesh analysis engine.
Definition: primitiveMesh.H:75
virtual void invert(const label maxLen)
Invert contents.
Definition: faceZoneSet.C:145
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
UIndirectList< label > labelUIndList
UIndirectList of labels.
Definition: IndirectList.H:65
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &faceValues, const bool parRun=UPstream::parRun())
Swap coupled boundary face values. Uses eqOp.
Definition: syncTools.H:524
virtual bool set(const label id)
Set an index.
Definition: topoSet.C:545
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
void resize_nocopy(const label len)
Adjust allocated size of list without necessarily.
Definition: ListI.H:168
A simple container for options an IOstream can normally have.
bool isAnyRead() const noexcept
True if any reading may be required (ie, != NO_READ)
virtual bool writeObject(IOstreamOption streamOpt, const bool writeOnProc) const
Write using stream options.
label nFaces() const noexcept
Number of mesh faces.
void push_back(const T &val)
Append an element at the end of the list.
Definition: ListI.H:220
virtual void updateMesh(const mapPolyMesh &morphMap)
Update any stored data for new labels.
Definition: faceZoneSet.C:566
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Definition: mapPolyMesh.H:158
Macros for easy insertion into run-time selection tables.
UList< label > labelUList
A UList of labels.
Definition: UList.H:78
virtual void writeDebug(Ostream &os, const primitiveMesh &, const label maxLen) const
Write maxLen items with label and coordinates.
Definition: faceSet.C:237
virtual bool contains(const label id) const
Has the given index?
Definition: topoSet.C:533
Various functions to operate on Lists.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
const labelList & reverseFaceMap() const noexcept
Reverse face map.
Definition: mapPolyMesh.H:620
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition: HashSet.H:85
defineTypeName(manifoldCellsMeshObject)
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:799
virtual void writeDebug(Ostream &os, const primitiveMesh &, const label maxLen) const
Write maxLen items with label and coordinates.
Definition: faceZoneSet.C:590
dynamicFvMesh & mesh
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
A class for handling words, derived from Foam::string.
Definition: word.H:63
void sort(UList< T > &list)
Sort the list.
Definition: UList.C:296
static const word null
An empty word.
Definition: word.H:84
label nInternalFaces() const noexcept
Number of internal faces.
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
OBJstream os(runTime.globalPath()/outputName)
virtual void sync(const polyMesh &mesh)
Sync faceZoneSet across coupled patches.
Definition: faceZoneSet.C:404
bool isReadRequired() const noexcept
True if (MUST_READ | READ_MODIFIED) bits are set.
faceZoneSet(const polyMesh &mesh, const word &name, IOobjectOption::readOption rOpt=IOobjectOption::MUST_READ, IOobjectOption::writeOption wOpt=IOobjectOption::NO_WRITE)
Construct from objectRegistry and name.
Definition: faceZoneSet.C:82
void updateSet()
Sort addressing and make faceSet part consistent with addressing.
Definition: faceZoneSet.C:45
Like faceSet but -reads data from faceZone -updates faceZone when writing.
Definition: faceZoneSet.H:47
General set of labels of mesh quantity (points, cells, faces).
Definition: topoSet.H:59
List< T > subset(const BoolListType &select, const UList< T > &input, const bool invert=false)
Extract elements of the input list when select is true.
#define WarningInFunction
Report a warning using Foam::Warning.
void reserve(label numEntries)
Reserve space for at least the specified number of elements (not the number of buckets) and regenerat...
Definition: HashTable.C:736
List< label > sortedToc(const UList< bool > &bools)
Return the (sorted) values corresponding to &#39;true&#39; entries.
Definition: BitOps.C:195
label n
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:75
List< label > labelList
A List of labels.
Definition: List.H:62
virtual void check(const label maxSize)
Check limits on addressable range.
Definition: topoSet.C:252
label nBoundaryFaces() const noexcept
Number of boundary faces (== nFaces - nInternalFaces)
Map< label > invertToMap(const labelUList &values)
Create inverse mapping, which is a lookup table into the given list.
Definition: ListOps.C:107
static const List< bool > & null() noexcept
Return a null List (reference to a nullObject). Behaves like an empty List.
Definition: List.H:153
virtual label maxSize(const polyMesh &mesh) const
Return max index+1.
Definition: faceZoneSet.C:523
virtual bool writeObject(IOstreamOption streamOpt, const bool writeOnProc) const
Write faceZone using stream options.
Definition: faceZoneSet.C:530
UIndirectList< bool > boolUIndList
UIndirectList of bools.
Definition: IndirectList.H:61
Namespace for OpenFOAM.
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)
void clearStorage()
Remove all entries from table and the table itself.
Definition: HashTable.C:774
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127
readOption
Enumeration defining read preferences.