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-2020 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);
44  addToRunTimeSelectionTable(topoSet, faceZoneSet, size);
45  addToRunTimeSelectionTable(topoSet, faceZoneSet, set);
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 
57  faceSet::clearStorage();
58  faceSet::resize(2*addressing_.size());
59  faceSet::set(addressing_);
60 }
61 
62 
63 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
64 
66 (
67  const polyMesh& mesh,
68  const word& name,
69  readOption r,
70  writeOption w
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  (
83  (r == IOobject::MUST_READ)
85  || (r == IOobject::READ_IF_PRESENT && zoneID != -1)
86  )
87  {
88  const faceZone& fz = faceZones[zoneID];
89  addressing_ = fz.addressing();
90  flipMap_ = fz.flipMap();
91  }
92 
93  updateSet();
94 
95  check(mesh.nFaces());
96 }
97 
98 
100 (
101  const polyMesh& mesh,
102  const word& name,
103  const label size,
104  writeOption w
105 )
106 :
107  faceSet(mesh, name, size, w),
108  mesh_(mesh),
109  addressing_(),
110  flipMap_()
111 {
112  updateSet();
113 }
114 
115 
117 (
118  const polyMesh& mesh,
119  const word& name,
120  const topoSet& set,
121  writeOption w
122 )
123 :
124  faceSet(mesh, name, set.size(), w),
125  mesh_(mesh),
126  addressing_(refCast<const faceZoneSet>(set).addressing()),
127  flipMap_(refCast<const faceZoneSet>(set).flipMap())
128 {
129  updateSet();
130 }
131 
132 
133 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
134 
135 void Foam::faceZoneSet::invert(const label maxLen)
136 {
137  // Count
138  label n = 0;
139 
140  for (label facei = 0; facei < maxLen; ++facei)
141  {
142  if (!found(facei))
143  {
144  ++n;
145  }
146  }
147 
148  // Fill
149  addressing_.setSize(n);
150  flipMap_.setSize(n);
151  n = 0;
152 
153  for (label facei = 0; facei < maxLen; ++facei)
154  {
155  if (!found(facei))
156  {
157  addressing_[n] = facei;
158  flipMap_[n] = false; //? or true?
159  ++n;
160  }
161  }
162  updateSet();
163 }
164 
165 
167 {
168  label nConflict = 0;
169 
170  DynamicList<label> newAddressing(addressing_.size());
171  DynamicList<bool> newFlipMap(flipMap_.size());
172 
173  Map<label> faceToIndex(addressing_.size());
174  forAll(addressing_, i)
175  {
176  faceToIndex.insert(addressing_[i], i);
177  }
178 
179  const faceZoneSet& zoneSet = refCast<const faceZoneSet>(set);
180 
181  forAll(zoneSet.addressing(), i)
182  {
183  const label facei = zoneSet.addressing()[i];
184 
185  const auto iter = faceToIndex.cfind(facei);
186 
187  if (iter.found())
188  {
189  const label index = *iter;
190 
191  if (zoneSet.flipMap()[i] != flipMap_[index])
192  {
193  ++nConflict;
194  }
195  newAddressing.append(facei);
196  newFlipMap.append(flipMap_[index]);
197  }
198  }
199 
200  if (nConflict > 0)
201  {
203  << "subset : there are " << nConflict
204  << " faces with different orientation in faceZonesSets "
205  << name() << " and " << set.name() << endl;
206  }
207 
208  addressing_.transfer(newAddressing);
209  flipMap_.transfer(newFlipMap);
210  updateSet();
211 }
212 
213 
215 {
216  label nConflict = 0;
217 
218  DynamicList<label> newAddressing(addressing_);
219  DynamicList<bool> newFlipMap(flipMap_);
220 
221  Map<label> faceToIndex(addressing_.size());
222  forAll(addressing_, i)
223  {
224  faceToIndex.insert(addressing_[i], i);
225  }
226 
227  const faceZoneSet& zoneSet = refCast<const faceZoneSet>(set);
228 
229  forAll(zoneSet.addressing(), i)
230  {
231  label facei = zoneSet.addressing()[i];
232 
233  const auto iter = faceToIndex.cfind(facei);
234 
235  if (iter.found())
236  {
237  const label index = *iter;
238 
239  if (zoneSet.flipMap()[i] != flipMap_[index])
240  {
241  ++nConflict;
242  }
243  }
244  else
245  {
246  newAddressing.append(facei);
247  newFlipMap.append(zoneSet.flipMap()[i]);
248  }
249  }
250 
251  if (nConflict > 0)
252  {
254  << "addSet : there are " << nConflict
255  << " faces with different orientation in faceZonesSets "
256  << name() << " and " << set.name() << endl;
257  }
258 
259  addressing_.transfer(newAddressing);
260  flipMap_.transfer(newFlipMap);
261  updateSet();
262 }
263 
264 
266 {
267  label nConflict = 0;
268 
269  DynamicList<label> newAddressing(addressing_.size());
270  DynamicList<bool> newFlipMap(flipMap_.size());
271 
272  const faceZoneSet& zoneSet = refCast<const faceZoneSet>(set);
273 
274  Map<label> faceToIndex(zoneSet.addressing().size());
275  forAll(zoneSet.addressing(), i)
276  {
277  faceToIndex.insert(zoneSet.addressing()[i], i);
278  }
279 
280  forAll(addressing_, i)
281  {
282  const label facei = addressing_[i];
283 
284  const auto iter = faceToIndex.cfind(facei);
285 
286  if (iter.found())
287  {
288  const label index = *iter;
289 
290  if (zoneSet.flipMap()[index] != flipMap_[i])
291  {
292  ++nConflict;
293  }
294  }
295  else
296  {
297  // Not found in zoneSet so add
298  newAddressing.append(facei);
299  newFlipMap.append(zoneSet.flipMap()[i]);
300  }
301  }
302 
303  if (nConflict > 0)
304  {
306  << "subtractSet : there are " << nConflict
307  << " faces with different orientation in faceZonesSets "
308  << name() << " and " << set.name() << endl;
309  }
310 
311  addressing_.transfer(newAddressing);
312  flipMap_.transfer(newFlipMap);
313  updateSet();
314 }
315 
316 
318 {
319  // Make sure that the faceZone is consistent with the faceSet
320  {
321  const labelHashSet zoneSet(addressing_);
322 
323  // Elements that are in zone but not faceSet, and
324  // elements that are in faceSet but not in zone
325  labelHashSet badSet(*this ^ zoneSet);
326 
327  const label nBad = returnReduce(badSet.size(), sumOp<label>());
328 
329  if (nBad)
330  {
331  WarningInFunction << "Detected " << nBad
332  << " faces that are in the faceZone but not"
333  << " in the faceSet or vice versa."
334  << " The faceZoneSet should only be manipulated"
335  << " using " << setsToFaceZone::typeName
336  << " or " << setToFaceZone::typeName << endl;
337  }
338  }
339 
340 
341  // Make sure that on coupled faces orientation is opposite. Pushes
342  // master orientation to slave in case of conflict.
343 
344 
345  // 0 : not in faceZone
346  // 1 : in faceZone and unflipped
347  //-1 : in faceZone and flipped
348  const label UNFLIPPED = 1;
349  const label FLIPPED = -1;
350  labelList myZoneFace(mesh.nBoundaryFaces(), Zero);
351 
352  forAll(addressing_, i)
353  {
354  const label bFacei = addressing_[i]-mesh.nInternalFaces();
355 
356  if (bFacei >= 0)
357  {
358  if (flipMap_[i])
359  {
360  myZoneFace[bFacei] = FLIPPED;
361  }
362  else
363  {
364  myZoneFace[bFacei] = UNFLIPPED;
365  }
366  }
367  }
368 
369  labelList neiZoneFace(myZoneFace);
371 
372 
373  const bitSet isMasterFace(syncTools::getMasterFaces(mesh));
374 
375 
376  // Rebuild faceZone addressing and flipMap
377  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
378 
379  DynamicList<label> newAddressing(addressing_.size());
380  DynamicList<bool> newFlipMap(flipMap_.size());
381 
382  forAll(addressing_, i)
383  {
384  const label facei = addressing_[i];
385  if (facei < mesh.nInternalFaces())
386  {
387  newAddressing.append(facei);
388  newFlipMap.append(flipMap_[i]);
389  }
390  }
391 
392  for (label facei = mesh.nInternalFaces(); facei < mesh.nFaces(); facei++)
393  {
394  label myStat = myZoneFace[facei-mesh.nInternalFaces()];
395  label neiStat = neiZoneFace[facei-mesh.nInternalFaces()];
396 
397  if (myStat == 0)
398  {
399  if (neiStat == UNFLIPPED)
400  {
401  // Neighbour is unflipped so I am flipped
402  newAddressing.append(facei);
403  newFlipMap.append(true);
404  }
405  else if (neiStat == FLIPPED)
406  {
407  newAddressing.append(facei);
408  newFlipMap.append(false);
409  }
410  }
411  else
412  {
413  if (myStat == neiStat)
414  {
415  // Conflict. masterFace wins
416  newAddressing.append(facei);
417  if (isMasterFace[facei])
418  {
419  newFlipMap.append(myStat == FLIPPED);
420  }
421  else
422  {
423  newFlipMap.append(neiStat == UNFLIPPED);
424  }
425  }
426  else
427  {
428  newAddressing.append(facei);
429  newFlipMap.append(myStat == FLIPPED);
430  }
431  }
432  }
433 
434  addressing_.transfer(newAddressing);
435  flipMap_.transfer(newFlipMap);
436  updateSet();
437 }
438 
439 
440 Foam::label Foam::faceZoneSet::maxSize(const polyMesh& mesh) const
441 {
442  return mesh.nFaces();
443 }
444 
445 
447 (
448  IOstreamOption streamOpt,
449  const bool valid
450 ) const
451 {
452  // Write shadow faceSet
453  word oldTypeName = typeName;
454  const_cast<word&>(type()) = faceSet::typeName;
455  bool ok = faceSet::writeObject(streamOpt, valid);
456  const_cast<word&>(type()) = oldTypeName;
457 
458  // Modify faceZone
459  faceZoneMesh& faceZones = const_cast<polyMesh&>(mesh_).faceZones();
460  label zoneID = faceZones.findZoneID(name());
461 
462  if (zoneID == -1)
463  {
464  zoneID = faceZones.size();
465 
466  faceZones.setSize(zoneID+1);
467  faceZones.set
468  (
469  zoneID,
470  new faceZone
471  (
472  name(),
473  addressing_,
474  flipMap_,
475  zoneID,
476  faceZones
477  )
478  );
479  }
480  else
481  {
482  faceZones[zoneID].resetAddressing(addressing_, flipMap_);
483  }
484  faceZones.clearAddressing();
485 
486  return ok && faceZones.write(valid);
487 }
488 
489 
491 {
492  // faceZone
493  labelList newAddressing(addressing_.size());
494  boolList newFlipMap(flipMap_.size(), false);
495 
496  label n = 0;
497  forAll(addressing_, i)
498  {
499  label facei = addressing_[i];
500  label newFacei = morphMap.reverseFaceMap()[facei];
501  if (newFacei >= 0)
502  {
503  newAddressing[n] = newFacei;
504  newFlipMap[n] = flipMap_[i];
505  n++;
506  }
507  }
508  newAddressing.setSize(n);
509  newFlipMap.setSize(n);
510 
511  addressing_.transfer(newAddressing);
512  flipMap_.transfer(newFlipMap);
513 
514  updateSet();
515 }
516 
517 
519 (
520  Ostream& os,
521  const primitiveMesh& mesh,
522  const label maxLen
523 ) const
524 {
525  faceSet::writeDebug(os, mesh, maxLen);
526 }
527 
528 
529 // ************************************************************************* //
Foam::addToRunTimeSelectionTable
addToRunTimeSelectionTable(decompositionMethod, kahipDecomp, dictionary)
Foam::faceZoneSet::addressing
const labelList & addressing() const
Definition: faceZoneSet.H:106
Foam::BitOps::set
void set(List< bool > &bools, const labelRange &range)
Set the specified range 'on' in a boolList.
Definition: BitOps.C:37
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::faceZone::flipMap
const boolList & flipMap() const noexcept
Return face flip map.
Definition: faceZone.H:272
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:94
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:63
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::DynamicList< label >
faceZoneSet.H
Foam::faceZoneSet::updateSet
void updateSet()
Sort addressing and make faceSet part consistent with addressing.
Definition: faceZoneSet.C:51
mapPolyMesh.H
Foam::faceZoneSet::maxSize
virtual label maxSize(const polyMesh &mesh) const
Return max index+1.
Definition: faceZoneSet.C:440
Foam::Map< label >
Foam::faceZoneSet::updateMesh
virtual void updateMesh(const mapPolyMesh &morphMap)
Update any stored data for new labels.
Definition: faceZoneSet.C:490
Foam::syncTools::swapBoundaryFaceList
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &faceValues)
Swap coupled boundary face values. Uses eqOp.
Definition: syncTools.H:445
Foam::faceSet
A list of face labels.
Definition: faceSet.H:51
Foam::List::append
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:175
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::syncTools::getMasterFaces
static bitSet getMasterFaces(const polyMesh &mesh)
Definition: syncTools.C:126
polyMesh.H
Foam::HashSet< label, Hash< label > >
syncTools.H
Foam::faceZoneSet::flipMap
const boolList & flipMap() const
Definition: faceZoneSet.H:117
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
Foam::sumOp
Definition: ops.H:213
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::IOobject::writeOption
writeOption
Enumeration defining the write options.
Definition: IOobject.H:192
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::check
static void check(const int retVal, const char *what)
Definition: ptscotchDecomp.C:80
Foam::faceSet::writeDebug
virtual void writeDebug(Ostream &os, const primitiveMesh &, const label maxLen) const
Write maxLen items with label and coordinates.
Definition: faceSet.C:215
Foam::boolUIndList
UIndirectList< bool > boolUIndList
UIndirectList of bools.
Definition: UIndirectList.H:54
resize
patchWriters resize(patchIds.size())
Foam::faceZone
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:64
Foam::faceZoneSet::invert
virtual void invert(const label maxLen)
Invert contents.
Definition: faceZoneSet.C:135
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Append an element to the end of this list.
Definition: DynamicListI.H:511
Foam::topoSet::set
virtual bool set(const label id)
Set an index.
Definition: topoSet.C:514
Foam::IOobject::READ_IF_PRESENT
Definition: IOobject.H:187
Foam::IOstreamOption
The IOstreamOption is a simple container for options an IOstream can normally have.
Definition: IOstreamOption.H:63
Foam::primitiveMesh::nBoundaryFaces
label nBoundaryFaces() const noexcept
Number of boundary faces (== nFaces - nInternalFaces)
Definition: primitiveMeshI.H:84
Foam::ZoneMesh< faceZone, polyMesh >
Foam::faceZoneSet
Like faceSet but -reads data from faceZone -updates faceZone when writing.
Definition: faceZoneSet.H:51
Foam::polyMesh::faceZones
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition: polyMesh.H:486
Foam::faceZoneSet::writeDebug
virtual void writeDebug(Ostream &os, const primitiveMesh &, const label maxLen) const
Write maxLen items with label and coordinates.
Definition: faceZoneSet.C:519
Foam::topoSet
General set of labels of mesh quantity (points, cells, faces).
Definition: topoSet.H:63
Foam::faceZoneSet::faceZoneSet
faceZoneSet(const polyMesh &mesh, const word &name, readOption r=MUST_READ, writeOption w=NO_WRITE)
Construct from objectRegistry and name.
Definition: faceZoneSet.C:66
Foam::faceZoneSet::subtractSet
virtual void subtractSet(const topoSet &set)
Subtract elements present in set.
Definition: faceZoneSet.C:265
Foam::faceZoneSet::sync
virtual void sync(const polyMesh &mesh)
Sync faceZoneSet across coupled patches.
Definition: faceZoneSet.C:317
Foam::faceZoneSet::writeObject
virtual bool writeObject(IOstreamOption streamOpt, const bool valid) const
Write faceZone using stream options.
Definition: faceZoneSet.C:447
os
OBJstream os(runTime.globalPath()/outputName)
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
zoneID
const labelIOList & zoneID
Definition: interpolatedFaces.H:22
Foam::regIOobject::writeObject
virtual bool writeObject(IOstreamOption streamOpt, const bool valid) const
Write using stream options.
Definition: regIOobjectWrite.C:36
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::ZoneMesh::findZoneID
label findZoneID(const word &zoneName) const
Find zone index by name, return -1 if not found.
Definition: ZoneMesh.C:519
Foam::mapPolyMesh::reverseFaceMap
const labelList & reverseFaceMap() const
Reverse face map.
Definition: mapPolyMesh.H:501
found
bool found
Definition: TABSMDCalcMethod2.H:32
Foam::faceZoneSet::addSet
virtual void addSet(const topoSet &set)
Add elements present in set.
Definition: faceZoneSet.C:214
setToFaceZone.H
Foam::faceZoneSet::subset
virtual void subset(const topoSet &set)
Subset contents. Only elements present in both sets remain.
Definition: faceZoneSet.C:166
Foam::primitiveMesh::nInternalFaces
label nInternalFaces() const noexcept
Number of internal faces.
Definition: primitiveMeshI.H:78
Foam::List< label >
Foam::type
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: MSwindows.C:590
Foam::IOobject::MUST_READ_IF_MODIFIED
Definition: IOobject.H:186
setsToFaceZone.H
Foam::mapPolyMesh
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Definition: mapPolyMesh.H:161
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
Foam::primitiveMesh::nFaces
label nFaces() const noexcept
Number of mesh faces.
Definition: primitiveMeshI.H:90
Foam::sortedOrder
labelList sortedOrder(const UList< T > &input)
Return the (stable) sort order for the list.
Foam::IOobject::readOption
readOption
Enumeration defining the read options.
Definition: IOobject.H:183
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::ZoneMesh::clearAddressing
void clearAddressing()
Clear addressing.
Definition: ZoneMesh.C:709
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328
Foam::zone::addressing
const labelList & addressing() const noexcept
The addressing used by the zone.
Definition: zone.H:147
Foam::IOobject::MUST_READ
Definition: IOobject.H:185
Foam::labelUIndList
UIndirectList< label > labelUIndList
UIndirectList of labels.
Definition: UIndirectList.H:58
Foam::primitiveMesh
Cell-face mesh analysis engine.
Definition: primitiveMesh.H:78