FreeFOAM The Cross-Platform CFD Toolkit
faceZone.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 | Copyright (C) 1991-2010 OpenCFD Ltd.
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 Description
25  A subset of mesh faces.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "faceZone.H"
31 #include <OpenFOAM/faceZoneMesh.H>
32 #include <OpenFOAM/polyMesh.H>
33 #include <OpenFOAM/primitiveMesh.H>
35 #include <OpenFOAM/mapPolyMesh.H>
36 #include <OpenFOAM/syncTools.H>
37 
38 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
39 
40 namespace Foam
41 {
42  defineTypeNameAndDebug(faceZone, 0);
43  defineRunTimeSelectionTable(faceZone, dictionary);
44  addToRunTimeSelectionTable(faceZone, faceZone, dictionary);
45 }
46 
47 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
48 
49 void Foam::faceZone::calcFaceZonePatch() const
50 {
51  if (debug)
52  {
53  Info<< "void faceZone::calcFaceZonePatch() const : "
54  << "Calculating primitive patch"
55  << endl;
56  }
57 
58  if (patchPtr_)
59  {
61  (
62  "void faceZone::calcFaceZonePatch() const"
63  ) << "primitive face zone patch already calculated"
64  << abort(FatalError);
65  }
66 
67  patchPtr_ =
69  (
70  faceList(size()),
71  zoneMesh().mesh().points()
72  );
73 
74  primitiveFacePatch& patch = *patchPtr_;
75 
76  const faceList& f = zoneMesh().mesh().faces();
77 
78  const labelList& addr = *this;
79  const boolList& flip = flipMap();
80 
81  forAll (addr, faceI)
82  {
83  if (flip[faceI])
84  {
85  patch[faceI] = f[addr[faceI]].reverseFace();
86  }
87  else
88  {
89  patch[faceI] = f[addr[faceI]];
90  }
91  }
92 
93  if (debug)
94  {
95  Info<< "void faceZone::calcFaceZonePatch() const : "
96  << "Finished calculating primitive patch"
97  << endl;
98  }
99 }
100 
101 
102 const Foam::Map<Foam::label>& Foam::faceZone::faceLookupMap() const
103 {
104  if (!faceLookupMapPtr_)
105  {
106  calcFaceLookupMap();
107  }
108 
109  return *faceLookupMapPtr_;
110 }
111 
112 
113 void Foam::faceZone::calcFaceLookupMap() const
114 {
115  if (debug)
116  {
117  Info<< "void faceZone::calcFaceLookupMap() const : "
118  << "Calculating face lookup map"
119  << endl;
120  }
121 
122  if (faceLookupMapPtr_)
123  {
125  (
126  "void faceZone::calcFaceLookupMap() const"
127  ) << "face lookup map already calculated"
128  << abort(FatalError);
129  }
130 
131  const labelList& addr = *this;
132 
133  faceLookupMapPtr_ = new Map<label>(2*addr.size());
134  Map<label>& flm = *faceLookupMapPtr_;
135 
136  forAll (addr, faceI)
137  {
138  flm.insert(addr[faceI], faceI);
139  }
140 
141  if (debug)
142  {
143  Info<< "void faceZone::calcFaceLookupMap() const : "
144  << "Finished calculating face lookup map"
145  << endl;
146  }
147 }
148 
149 
150 void Foam::faceZone::calcCellLayers() const
151 {
152  if (debug)
153  {
154  Info<< "void Foam::faceZone::calcCellLayers() const : "
155  << "calculating master cells"
156  << endl;
157  }
158 
159  // It is an error to attempt to recalculate edgeCells
160  // if the pointer is already set
161  if (masterCellsPtr_ || slaveCellsPtr_)
162  {
163  FatalErrorIn("void faceZone::calcCellLayers() const")
164  << "cell layers already calculated"
165  << abort(FatalError);
166  }
167  else
168  {
169  // Go through all the faces in the master zone. Choose the
170  // master or slave cell based on the face flip
171 
172  const labelList& own = zoneMesh().mesh().faceOwner();
173  const labelList& nei = zoneMesh().mesh().faceNeighbour();
174 
175  const labelList& mf = *this;
176 
177  const boolList& faceFlip = flipMap();
178 
179  masterCellsPtr_ = new labelList(mf.size());
180  labelList& mc = *masterCellsPtr_;
181 
182  slaveCellsPtr_ = new labelList(mf.size());
183  labelList& sc = *slaveCellsPtr_;
184 
185  forAll (mf, faceI)
186  {
187  label ownCellI = own[mf[faceI]];
188  label neiCellI =
189  (
190  zoneMesh().mesh().isInternalFace(mf[faceI])
191  ? nei[mf[faceI]]
192  : -1
193  );
194 
195  if (!faceFlip[faceI])
196  {
197  // Face is oriented correctly, no flip needed
198  mc[faceI] = neiCellI;
199  sc[faceI] = ownCellI;
200  }
201  else
202  {
203  mc[faceI] = ownCellI;
204  sc[faceI] = neiCellI;
205  }
206  }
207  //Info << "masterCells: " << mc << endl;
208  //Info << "slaveCells: " << sc << endl;
209  }
210 }
211 
212 
213 void Foam::faceZone::checkAddressing() const
214 {
215  if (size() != flipMap_.size())
216  {
217  FatalErrorIn("void Foam::faceZone::checkAddressing() const")
218  << "Different sizes of the addressing and flipMap arrays. "
219  << "Size of addressing: " << size()
220  << " size of flip map: " << flipMap_.size()
221  << abort(FatalError);
222  }
223 }
224 
225 
226 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
227 
228 // Construct from components
229 Foam::faceZone::faceZone
230 (
231  const word& name,
232  const labelList& addr,
233  const boolList& fm,
234  const label index,
235  const faceZoneMesh& zm
236 )
237 :
238  labelList(addr),
239  name_(name),
240  flipMap_(fm),
241  index_(index),
242  zoneMesh_(zm),
243  patchPtr_(NULL),
244  masterCellsPtr_(NULL),
245  slaveCellsPtr_(NULL),
246  mePtr_(NULL),
247  faceLookupMapPtr_(NULL)
248 {
249  checkAddressing();
250 }
251 
252 
253 Foam::faceZone::faceZone
254 (
255  const word& name,
256  const Xfer<labelList>& addr,
257  const Xfer<boolList>& fm,
258  const label index,
259  const faceZoneMesh& zm
260 )
261 :
262  labelList(addr),
263  name_(name),
264  flipMap_(fm),
265  index_(index),
266  zoneMesh_(zm),
267  patchPtr_(NULL),
268  masterCellsPtr_(NULL),
269  slaveCellsPtr_(NULL),
270  mePtr_(NULL),
271  faceLookupMapPtr_(NULL)
272 {
273  checkAddressing();
274 }
275 
276 
277 // Construct from dictionary
278 Foam::faceZone::faceZone
279 (
280  const word& name,
281  const dictionary& dict,
282  const label index,
283  const faceZoneMesh& zm
284 )
285 :
286  labelList(dict.lookup("faceLabels")),
287  name_(name),
288  flipMap_(dict.lookup("flipMap")),
289  index_(index),
290  zoneMesh_(zm),
291  patchPtr_(NULL),
292  masterCellsPtr_(NULL),
293  slaveCellsPtr_(NULL),
294  mePtr_(NULL),
295  faceLookupMapPtr_(NULL)
296 {
297  checkAddressing();
298 }
299 
300 
301 // Construct given the original zone and resetting the
302 // face list and zone mesh information
303 Foam::faceZone::faceZone
304 (
305  const faceZone& fz,
306  const labelList& addr,
307  const boolList& fm,
308  const label index,
309  const faceZoneMesh& zm
310 )
311 :
312  labelList(addr),
313  name_(fz.name()),
314  flipMap_(fm),
315  index_(index),
316  zoneMesh_(zm),
317  patchPtr_(NULL),
318  masterCellsPtr_(NULL),
319  slaveCellsPtr_(NULL),
320  mePtr_(NULL),
321  faceLookupMapPtr_(NULL)
322 {
323  checkAddressing();
324 }
325 
326 
327 Foam::faceZone::faceZone
328 (
329  const faceZone& fz,
330  const Xfer<labelList>& addr,
331  const Xfer<boolList>& fm,
332  const label index,
333  const faceZoneMesh& zm
334 )
335 :
336  labelList(addr),
337  name_(fz.name()),
338  flipMap_(fm),
339  index_(index),
340  zoneMesh_(zm),
341  patchPtr_(NULL),
342  masterCellsPtr_(NULL),
343  slaveCellsPtr_(NULL),
344  mePtr_(NULL),
345  faceLookupMapPtr_(NULL)
346 {
347  checkAddressing();
348 }
349 
350 
351 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
352 
354 {
355  clearAddressing();
356 }
357 
358 
359 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
360 
361 Foam::label Foam::faceZone::whichFace(const label globalFaceID) const
362 {
363  const Map<label>& flm = faceLookupMap();
364 
365  Map<label>::const_iterator flmIter = flm.find(globalFaceID);
366 
367  if (flmIter == flm.end())
368  {
369  return -1;
370  }
371  else
372  {
373  return flmIter();
374  }
375 }
376 
377 
379 {
380  return zoneMesh_;
381 }
382 
383 
385 {
386  if (!patchPtr_)
387  {
388  calcFaceZonePatch();
389  }
390 
391  return *patchPtr_;
392 }
393 
394 
396 {
397  if (!masterCellsPtr_)
398  {
399  calcCellLayers();
400  }
401 
402  return *masterCellsPtr_;
403 }
404 
405 
407 {
408  if (!slaveCellsPtr_)
409  {
410  calcCellLayers();
411  }
412 
413  return *slaveCellsPtr_;
414 }
415 
416 
418 {
419  if (!mePtr_)
420  {
421  //labelList faceCells(size());
422  //
423  //const labelList& own = zoneMesh().mesh().faceOwner();
424  //
425  //const labelList& faceLabels = *this;
426  //
427  //forAll (faceCells, faceI)
428  //{
429  // faceCells[faceI] = own[faceLabels[faceI]];
430  //}
431  //
432  //mePtr_ =
433  // new labelList
434  // (
435  // operator()().meshEdges
436  // (
437  // zoneMesh().mesh().edges(),
438  // zoneMesh().mesh().cellEdges(),
439  // faceCells
440  // )
441  // );
442 
443  mePtr_ =
444  new labelList
445  (
446  operator()().meshEdges
447  (
448  zoneMesh().mesh().edges(),
449  zoneMesh().mesh().pointEdges()
450  )
451  );
452  }
453 
454  return *mePtr_;
455 }
456 
457 
459 {
460  deleteDemandDrivenData(patchPtr_);
461 
462  deleteDemandDrivenData(masterCellsPtr_);
463  deleteDemandDrivenData(slaveCellsPtr_);
464 
465  deleteDemandDrivenData(mePtr_);
466  deleteDemandDrivenData(faceLookupMapPtr_);
467 }
468 
469 
471 (
472  const labelList& addr,
473  const boolList& flipMap
474 )
475 {
476  clearAddressing();
477  labelList::operator=(addr);
478  flipMap_ = flipMap;
479 }
480 
481 
483 {
484  clearAddressing();
485 
486  labelList newAddressing(size());
487  boolList newFlipMap(flipMap_.size());
488  label nFaces = 0;
489 
490  const labelList& faceMap = mpm.reverseFaceMap();
491 
492  forAll(*this, i)
493  {
494  label faceI = operator[](i);
495 
496  if (faceMap[faceI] >= 0)
497  {
498  newAddressing[nFaces] = faceMap[faceI];
499  newFlipMap[nFaces] = flipMap_[i]; // Keep flip map.
500  nFaces++;
501  }
502  }
503 
504  newAddressing.setSize(nFaces);
505  newFlipMap.setSize(nFaces);
506 
507  transfer(newAddressing);
508  flipMap_.transfer(newFlipMap);
509 }
510 
511 
512 bool Foam::faceZone::checkDefinition(const bool report) const
513 {
514  const labelList& addr = *this;
515 
516  bool boundaryError = false;
517 
518  forAll(addr, i)
519  {
520  if (addr[i] < 0 || addr[i] >= zoneMesh().mesh().faces().size())
521  {
522  boundaryError = true;
523 
524  if (report)
525  {
527  (
528  "bool faceZone::checkDefinition("
529  "const bool report) const"
530  ) << "Zone " << name()
531  << " contains invalid face label " << addr[i] << nl
532  << "Valid face labels are 0.."
533  << zoneMesh().mesh().faces().size()-1 << endl;
534  }
535  }
536  }
537  return boundaryError;
538 }
539 
540 
541 bool Foam::faceZone::checkParallelSync(const bool report) const
542 {
543  const polyMesh& mesh = zoneMesh().mesh();
544  const polyBoundaryMesh& bm = mesh.boundaryMesh();
545 
546  bool boundaryError = false;
547 
548 
549  // Check that zone faces are synced
550  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
551 
552  {
553  boolList neiZoneFace(mesh.nFaces()-mesh.nInternalFaces(), false);
554  boolList neiZoneFlip(mesh.nFaces()-mesh.nInternalFaces(), false);
555  forAll(*this, i)
556  {
557  label faceI = operator[](i);
558 
559  if (!mesh.isInternalFace(faceI))
560  {
561  neiZoneFace[faceI-mesh.nInternalFaces()] = true;
562  neiZoneFlip[faceI-mesh.nInternalFaces()] = flipMap()[i];
563  }
564  }
565  boolList myZoneFace(neiZoneFace);
566  syncTools::swapBoundaryFaceList(mesh, neiZoneFace, false);
567  boolList myZoneFlip(neiZoneFlip);
568  syncTools::swapBoundaryFaceList(mesh, neiZoneFlip, false);
569 
570  forAll(*this, i)
571  {
572  label faceI = operator[](i);
573 
574  label patchI = bm.whichPatch(faceI);
575 
576  if (patchI != -1 && bm[patchI].coupled())
577  {
578  label bFaceI = faceI-mesh.nInternalFaces();
579 
580  // Check face in zone on both sides
581  if (myZoneFace[bFaceI] != neiZoneFace[bFaceI])
582  {
583  boundaryError = true;
584 
585  if (report)
586  {
587  Pout<< " ***Problem with faceZone " << index()
588  << " named " << name()
589  << ". Face " << faceI
590  << " on coupled patch "
591  << bm[patchI].name()
592  << " is not consistent with its coupled neighbour."
593  << endl;
594  }
595  }
596  else if (myZoneFlip[bFaceI] == neiZoneFlip[bFaceI])
597  {
598  // Flip state should be opposite.
599  boundaryError = true;
600 
601  if (report)
602  {
603  Pout<< " ***Problem with faceZone " << index()
604  << " named " << name()
605  << ". Face " << faceI
606  << " on coupled patch "
607  << bm[patchI].name()
608  << " does not have consistent flipMap"
609  << " across coupled faces."
610  << endl;
611  }
612  }
613  }
614  }
615  }
616 
617  return returnReduce(boundaryError, orOp<bool>());
618 }
619 
620 
622 {
623  if (patchPtr_)
624  {
625  patchPtr_->movePoints(p);
626  }
627 }
628 
630 {
631  os << nl << name()
632  << nl << static_cast<const labelList&>(*this)
633  << nl << flipMap();
634 }
635 
636 
638 {
639  os << nl << name() << nl << token::BEGIN_BLOCK << nl
640  << " type " << type() << token::END_STATEMENT << nl;
641 
642  writeEntry("faceLabels", os);
643  flipMap().writeEntry("flipMap", os);
644 
645  os << token::END_BLOCK << endl;
646 }
647 
648 
649 // * * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * //
650 
652 {
653  p.write(os);
654  os.check("Ostream& operator<<(Ostream& f, const faceZone& p");
655  return os;
656 }
657 
658 
659 // ************************ vim: set sw=4 sts=4 et: ************************ //