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-2022 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 
37 
38 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
39 
40 namespace Foam
41 {
42  defineTypeNameAndDebug(faceZoneSet, 0);
43  addToRunTimeSelectionTable(topoSet, faceZoneSet, word);
46 }
47 
48 
49 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
50 
52 {
53  labelList order(sortedOrder(addressing_));
54  addressing_ = labelUIndList(addressing_, order)();
55  flipMap_ = boolUIndList(flipMap_, order)();
56 
58  faceSet::reserve(addressing_.size());
59  faceSet::set(addressing_);
60 }
61 
62 
63 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
64 
66 (
67  const polyMesh& mesh,
68  const word& name,
71 )
72 :
73  faceSet(mesh, name, 1024), // do not read faceSet
74  mesh_(mesh),
75  addressing_(),
76  flipMap_()
77 {
78  const faceZoneMesh& faceZones = mesh.faceZones();
79  label zoneID = faceZones.findZoneID(name);
80 
81  if
82  (
84  || (IOobjectOption::isReadOptional(rOpt) && zoneID != -1)
85  )
86  {
87  const faceZone& fz = faceZones[zoneID];
88  addressing_ = fz.addressing();
89  flipMap_ = fz.flipMap();
90  }
91 
93 
94  check(mesh.nFaces());
95 }
96 
97 
99 (
100  const polyMesh& mesh,
101  const word& name,
102  const label size,
104 )
105 :
106  faceSet(mesh, name, size, wOpt),
107  mesh_(mesh),
108  addressing_(),
109  flipMap_()
110 {
111  updateSet();
112 }
113 
114 
116 (
117  const polyMesh& mesh,
118  const word& name,
119  const topoSet& set,
121 )
122 :
123  faceSet(mesh, name, set.size(), wOpt),
124  mesh_(mesh),
125  addressing_(refCast<const faceZoneSet>(set).addressing()),
126  flipMap_(refCast<const faceZoneSet>(set).flipMap())
127 {
128  updateSet();
129 }
130 
131 
132 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
133 
134 void Foam::faceZoneSet::invert(const label maxLen)
135 {
136  // Count
137  label n = 0;
138 
139  for (label facei = 0; facei < maxLen; ++facei)
140  {
141  if (!found(facei))
142  {
143  ++n;
144  }
145  }
146 
147  // Fill
148  addressing_.setSize(n);
149  flipMap_.setSize(n);
150  n = 0;
151 
152  for (label facei = 0; facei < maxLen; ++facei)
153  {
154  if (!found(facei))
155  {
156  addressing_[n] = facei;
157  flipMap_[n] = false; //? or true?
158  ++n;
159  }
160  }
161  updateSet();
162 }
163 
164 
165 void Foam::faceZoneSet::subset(const topoSet& set)
166 {
167  label nConflict = 0;
168 
169  DynamicList<label> newAddressing(addressing_.size());
170  DynamicList<bool> newFlipMap(flipMap_.size());
171 
172  Map<label> faceToIndex(addressing_.size());
173  forAll(addressing_, i)
174  {
175  faceToIndex.insert(addressing_[i], i);
176  }
177 
178  const faceZoneSet& zoneSet = refCast<const faceZoneSet>(set);
179 
180  forAll(zoneSet.addressing(), i)
181  {
182  const label facei = zoneSet.addressing()[i];
183 
184  const auto iter = faceToIndex.cfind(facei);
185 
186  if (iter.good())
187  {
188  const label index = iter.val();
189 
190  if (zoneSet.flipMap()[i] != flipMap_[index])
191  {
192  ++nConflict;
193  }
194  newAddressing.append(facei);
195  newFlipMap.append(flipMap_[index]);
196  }
197  }
198 
199  if (nConflict > 0)
200  {
202  << "subset : there are " << nConflict
203  << " faces with different orientation in faceZonesSets "
204  << name() << " and " << set.name() << endl;
205  }
207  addressing_.transfer(newAddressing);
208  flipMap_.transfer(newFlipMap);
209  updateSet();
210 }
211 
212 
213 void Foam::faceZoneSet::addSet(const topoSet& set)
214 {
215  label nConflict = 0;
216 
217  DynamicList<label> newAddressing(addressing_);
218  DynamicList<bool> newFlipMap(flipMap_);
219 
220  Map<label> faceToIndex(addressing_.size());
221  forAll(addressing_, i)
222  {
223  faceToIndex.insert(addressing_[i], i);
224  }
225 
226  const faceZoneSet& zoneSet = refCast<const faceZoneSet>(set);
227 
228  forAll(zoneSet.addressing(), i)
229  {
230  label facei = zoneSet.addressing()[i];
231 
232  const auto iter = faceToIndex.cfind(facei);
233 
234  if (iter.good())
235  {
236  const label index = iter.val();
237 
238  if (zoneSet.flipMap()[i] != flipMap_[index])
239  {
240  ++nConflict;
241  }
242  }
243  else
244  {
245  newAddressing.append(facei);
246  newFlipMap.append(zoneSet.flipMap()[i]);
247  }
248  }
249 
250  if (nConflict > 0)
251  {
253  << "addSet : there are " << nConflict
254  << " faces with different orientation in faceZonesSets "
255  << name() << " and " << set.name() << endl;
256  }
258  addressing_.transfer(newAddressing);
259  flipMap_.transfer(newFlipMap);
260  updateSet();
261 }
262 
263 
265 {
266  label nConflict = 0;
267 
268  DynamicList<label> newAddressing(addressing_.size());
269  DynamicList<bool> newFlipMap(flipMap_.size());
270 
271  const faceZoneSet& zoneSet = refCast<const faceZoneSet>(set);
272 
273  Map<label> faceToIndex(zoneSet.addressing().size());
274  forAll(zoneSet.addressing(), i)
275  {
276  faceToIndex.insert(zoneSet.addressing()[i], i);
277  }
278 
279  forAll(addressing_, i)
280  {
281  const label facei = addressing_[i];
282 
283  const auto iter = faceToIndex.cfind(facei);
284 
285  if (iter.good())
286  {
287  const label index = iter.val();
288 
289  if (zoneSet.flipMap()[index] != flipMap_[i])
290  {
291  ++nConflict;
292  }
293  }
294  else
295  {
296  // Not found in zoneSet so add
297  newAddressing.append(facei);
298  newFlipMap.append(zoneSet.flipMap()[i]);
299  }
300  }
301 
302  if (nConflict > 0)
303  {
305  << "subtractSet : there are " << nConflict
306  << " faces with different orientation in faceZonesSets "
307  << name() << " and " << set.name() << endl;
308  }
310  addressing_.transfer(newAddressing);
311  flipMap_.transfer(newFlipMap);
312  updateSet();
313 }
314 
315 
317 {
318  // Make sure that the faceZone is consistent with the faceSet
319  {
320  const labelHashSet zoneSet(addressing_);
321 
322  // Elements that are in zone but not faceSet, and
323  // elements that are in faceSet but not in zone
324  labelHashSet badSet(*this ^ zoneSet);
325 
326  const label nBad = returnReduce(badSet.size(), sumOp<label>());
327 
328  if (nBad)
329  {
330  WarningInFunction << "Detected " << nBad
331  << " faces that are in the faceZone but not"
332  << " in the faceSet or vice versa."
333  << " The faceZoneSet should only be manipulated"
334  << " using " << setsToFaceZone::typeName
335  << " or " << setToFaceZone::typeName << endl;
336  }
337  }
338 
339 
340  // Make sure that on coupled faces orientation is opposite. Pushes
341  // master orientation to slave in case of conflict.
342 
343 
344  // 0 : not in faceZone
345  // 1 : in faceZone and unflipped
346  //-1 : in faceZone and flipped
347  const label UNFLIPPED = 1;
348  const label FLIPPED = -1;
349  labelList myZoneFace(mesh.nBoundaryFaces(), Zero);
350 
351  forAll(addressing_, i)
352  {
353  const label bFacei = addressing_[i]-mesh.nInternalFaces();
354 
355  if (bFacei >= 0)
356  {
357  if (flipMap_[i])
358  {
359  myZoneFace[bFacei] = FLIPPED;
360  }
361  else
362  {
363  myZoneFace[bFacei] = UNFLIPPED;
364  }
365  }
366  }
367 
368  labelList neiZoneFace(myZoneFace);
370 
371 
372  const bitSet isMasterFace(syncTools::getMasterFaces(mesh));
373 
374 
375  // Rebuild faceZone addressing and flipMap
376  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
377 
378  DynamicList<label> newAddressing(addressing_.size());
379  DynamicList<bool> newFlipMap(flipMap_.size());
380 
381  forAll(addressing_, i)
382  {
383  const label facei = addressing_[i];
384  if (facei < mesh.nInternalFaces())
385  {
386  newAddressing.append(facei);
387  newFlipMap.append(flipMap_[i]);
388  }
389  }
390 
391  for (label facei = mesh.nInternalFaces(); facei < mesh.nFaces(); facei++)
392  {
393  label myStat = myZoneFace[facei-mesh.nInternalFaces()];
394  label neiStat = neiZoneFace[facei-mesh.nInternalFaces()];
395 
396  if (myStat == 0)
397  {
398  if (neiStat == UNFLIPPED)
399  {
400  // Neighbour is unflipped so I am flipped
401  newAddressing.append(facei);
402  newFlipMap.append(true);
403  }
404  else if (neiStat == FLIPPED)
405  {
406  newAddressing.append(facei);
407  newFlipMap.append(false);
408  }
409  }
410  else
411  {
412  if (myStat == neiStat)
413  {
414  // Conflict. masterFace wins
415  newAddressing.append(facei);
416  if (isMasterFace[facei])
417  {
418  newFlipMap.append(myStat == FLIPPED);
419  }
420  else
421  {
422  newFlipMap.append(neiStat == UNFLIPPED);
423  }
424  }
425  else
426  {
427  newAddressing.append(facei);
428  newFlipMap.append(myStat == FLIPPED);
429  }
430  }
431  }
432 
433  addressing_.transfer(newAddressing);
434  flipMap_.transfer(newFlipMap);
435  updateSet();
436 }
437 
438 
439 Foam::label Foam::faceZoneSet::maxSize(const polyMesh& mesh) const
440 {
441  return mesh.nFaces();
442 }
443 
444 
446 (
447  IOstreamOption streamOpt,
448  const bool writeOnProc
449 ) const
450 {
451  // Write shadow faceSet
452  word oldTypeName = typeName;
453  const_cast<word&>(type()) = faceSet::typeName;
454  bool ok = faceSet::writeObject(streamOpt, writeOnProc);
455  const_cast<word&>(type()) = oldTypeName;
456 
457  // Modify faceZone
458  faceZoneMesh& faceZones = const_cast<polyMesh&>(mesh_).faceZones();
459  label zoneID = faceZones.findZoneID(name());
460 
461  if (zoneID == -1)
462  {
463  zoneID = faceZones.size();
464 
465  faceZones.emplace_back
466  (
467  name(),
468  addressing_,
469  flipMap_,
470  zoneID,
471  faceZones
472  );
473  }
474  else
475  {
476  faceZones[zoneID].resetAddressing(addressing_, flipMap_);
477  }
478  faceZones.clearAddressing();
480  return ok && faceZones.write(writeOnProc);
481 }
482 
483 
484 void Foam::faceZoneSet::updateMesh(const mapPolyMesh& morphMap)
485 {
486  // faceZone
487  labelList newAddressing(addressing_.size());
488  boolList newFlipMap(flipMap_.size(), false);
489 
490  label n = 0;
491  forAll(addressing_, i)
492  {
493  label facei = addressing_[i];
494  label newFacei = morphMap.reverseFaceMap()[facei];
495  if (newFacei >= 0)
496  {
497  newAddressing[n] = newFacei;
498  newFlipMap[n] = flipMap_[i];
499  n++;
500  }
501  }
502  newAddressing.setSize(n);
503  newFlipMap.setSize(n);
504 
505  addressing_.transfer(newAddressing);
506  flipMap_.transfer(newFlipMap);
507 
508  updateSet();
509 }
510 
511 
513 (
514  Ostream& os,
515  const primitiveMesh& mesh,
516  const label maxLen
517 ) const
518 {
519  faceSet::writeDebug(os, mesh, maxLen);
520 }
521 
522 
523 // ************************************************************************* //
writeOption
Enumeration defining write preferences.
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
void clearAddressing()
Clear addressing.
Definition: ZoneMesh.C:815
A list of face labels.
Definition: faceSet.H:47
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
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:127
Type & refCast(U &obj)
A dynamic_cast (for references). Generates a FatalError on failed casts and uses the virtual type() m...
Definition: typeInfo.H:159
UIndirectList< label > labelUIndList
UIndirectList of labels.
Definition: IndirectList.H:65
virtual bool set(const label id)
Set an index.
Definition: topoSet.C:497
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
A simple container for options an IOstream can normally have.
void set(List< bool > &bools, const labelUList &locations)
Set the listed locations (assign &#39;true&#39;).
Definition: BitOps.C:30
virtual bool writeObject(IOstreamOption streamOpt, const bool writeOnProc) const
Write using stream options.
label nFaces() const noexcept
Number of mesh faces.
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
virtual void updateMesh(const mapPolyMesh &morphMap)
Update any stored data for new labels.
Definition: faceZoneSet.C:479
bool isReadOptional() const noexcept
True if (LAZY_READ) bits are set [same as READ_IF_PRESENT].
T & emplace_back(Args &&... args)
Construct and append an element to the end of the list, return reference to the new list element...
Definition: PtrListI.H:105
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Definition: mapPolyMesh.H:157
Macros for easy insertion into run-time selection tables.
virtual void writeDebug(Ostream &os, const primitiveMesh &, const label maxLen) const
Write maxLen items with label and coordinates.
Definition: faceSet.C:208
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
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:508
dynamicFvMesh & mesh
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
label findZoneID(const word &zoneName) const
Find zone index by name, return -1 if not found.
Definition: ZoneMesh.C:629
A class for handling words, derived from Foam::string.
Definition: word.H:63
label size() const noexcept
The number of entries in the list.
Definition: UPtrListI.H:106
virtual bool write(const bool writeOnProc=true) const
Write using setting from DB.
label nInternalFaces() const noexcept
Number of internal faces.
const labelList & addressing() const noexcept
The addressing (face IDs) used for the zone.
Definition: faceZone.H:359
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
virtual void subtractSet(const topoSet &set)
Subtract elements present in set.
Definition: faceZoneSet.C:257
virtual void subset(const topoSet &set)
Subset contents. Only elements present in both sets remain.
Definition: faceZoneSet.C:158
OBJstream os(runTime.globalPath()/outputName)
defineTypeNameAndDebug(combustionModel, 0)
virtual void sync(const polyMesh &mesh)
Sync faceZoneSet across coupled patches.
Definition: faceZoneSet.C:309
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:59
void updateSet()
Sort addressing and make faceSet part consistent with addressing.
Definition: faceZoneSet.C:44
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
#define WarningInFunction
Report a warning using Foam::Warning.
virtual void addSet(const topoSet &set)
Add elements present in set.
Definition: faceZoneSet.C:206
void reserve(label numEntries)
Reserve space for at least the specified number of elements (not the number of buckets) and regenerat...
Definition: HashTable.C:712
const boolList & flipMap() const noexcept
Return face flip map.
Definition: faceZone.H:367
label n
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:60
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:196
label nBoundaryFaces() const noexcept
Number of boundary faces (== nFaces - nInternalFaces)
bool found
virtual label maxSize(const polyMesh &mesh) const
Return max index+1.
Definition: faceZoneSet.C:434
virtual bool writeObject(IOstreamOption streamOpt, const bool writeOnProc) const
Write faceZone using stream options.
Definition: faceZoneSet.C:441
UIndirectList< bool > boolUIndList
UIndirectList of bools.
Definition: IndirectList.H:61
const labelList & reverseFaceMap() const
Reverse face map.
Definition: mapPolyMesh.H:617
Namespace for OpenFOAM.
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &faceValues)
Swap coupled boundary face values. Uses eqOp.
Definition: syncTools.H:485
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)
void clearStorage()
Remove all entries from table and the table itself.
Definition: HashTable.C:750
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127
readOption
Enumeration defining read preferences.