faBoundaryMesh.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) 2016-2017 Wikki Ltd
9  Copyright (C) 2018-2025 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 "faBoundaryMesh.H"
30 #include "faMesh.H"
31 #include "globalIndex.H"
32 #include "processorFaPatch.H"
33 #include "wordRes.H"
34 #include "PtrListOps.H"
35 
36 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37 
38 namespace Foam
39 {
40  defineTypeNameAndDebug(faBoundaryMesh, 0);
41 }
42 
43 
44 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
45 
46 bool Foam::faBoundaryMesh::hasGroupIDs() const
47 {
48  if (groupIDsPtr_)
49  {
50  // Use existing cache
51  return !groupIDsPtr_->empty();
52  }
53 
54  const faPatchList& patches = *this;
55 
56  for (const faPatch& p : patches)
57  {
58  if (!p.inGroups().empty())
59  {
60  return true;
61  }
62  }
63 
64  return false;
65 }
66 
67 
68 void Foam::faBoundaryMesh::calcGroupIDs() const
69 {
70  if (groupIDsPtr_)
71  {
72  return; // Or FatalError
73  }
74 
75  groupIDsPtr_.emplace(16);
76  auto& groupLookup = *groupIDsPtr_;
77 
78  const faPatchList& patches = *this;
79 
80  forAll(patches, patchi)
81  {
82  for (const word& groupName : patches[patchi].inGroups())
83  {
84  groupLookup(groupName).push_back(patchi);
85  }
86  }
87 
88  // Remove groups that clash with patch names
89  forAll(patches, patchi)
90  {
91  if (groupLookup.empty())
92  {
93  break; // Early termination
94  }
95  else if (groupLookup.erase(patches[patchi].name()))
96  {
98  << "Removed group '" << patches[patchi].name()
99  << "' which clashes with patch " << patchi
100  << " of the same name."
101  << endl;
102  }
103  }
104 }
105 
106 
107 void Foam::faBoundaryMesh::populate(PtrList<entry>&& entries)
108 {
109  clearLocalAddressing();
110 
111  faPatchList& patches = *this;
112 
113  patches.resize_null(entries.size());
114 
115  // Transcribe.
116  // Does not handle nullptr at all (what could possibly be done?)
117  forAll(patches, patchi)
118  {
119  patches.set
120  (
121  patchi,
123  (
124  entries[patchi].keyword(),
125  entries[patchi].dict(),
126  patchi,
127  *this
128  )
129  );
130  }
131 
132  entries.clear();
133 }
134 
135 
136 bool Foam::faBoundaryMesh::readIOcontents(const bool allowOptionalRead)
137 {
138  bool updated = false;
139  PtrList<entry> entries;
140 
141  if
142  (
143  this->isReadRequired()
144  || (allowOptionalRead && this->isReadOptional() && this->headerOk())
145  )
146  {
147  // Warn for MUST_READ_IF_MODIFIED
148  warnNoRereading<faBoundaryMesh>();
149 
150  // Read entries
151  Istream& is = readStream(typeName);
152 
153  is >> entries;
154 
155  is.check(FUNCTION_NAME);
156  close();
157  updated = true;
158  }
159  // Future: support master-only and broadcast?
160 
161  if (updated)
162  {
163  populate(std::move(entries));
164  }
165 
166  return updated;
167 }
168 
169 
170 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
171 
173 (
174  const IOobject& io,
175  const faMesh& mesh
176 )
177 :
178  faPatchList(),
179  regIOobject(io),
180  mesh_(mesh)
181 {
182  readIOcontents(false); // allowOptionalRead = false
183 }
184 
185 
187 (
188  const IOobject& io,
189  const faMesh& pm,
190  Foam::zero
191 )
192 :
194  regIOobject(io),
195  mesh_(pm)
196 {}
197 
198 
200 (
201  const IOobject& io,
202  const faMesh& pm,
203  const label size
204 )
205 :
206  faPatchList(size),
207  regIOobject(io),
208  mesh_(pm)
209 {}
210 
211 
213 (
214  const IOobject& io,
215  const faMesh& fam,
216  const faPatchList& list
217 )
218 :
219  faPatchList(),
220  regIOobject(io),
221  mesh_(fam)
222 {
223  if (!readIOcontents(true)) // allowOptionalRead = true
224  {
225  // Nothing read. Use supplied patches
226  faPatchList& patches = *this;
227  patches.resize(list.size());
228 
229  forAll(patches, patchi)
230  {
231  patches.set(patchi, list[patchi].clone(*this));
232  }
233  }
234 }
235 
236 
238 (
239  const IOobject& io,
240  const faMesh& fam,
241  PtrList<entry>&& entries
242 )
243 :
244  faPatchList(),
245  regIOobject(io),
246  mesh_(fam)
247 {
248  if (!readIOcontents(true)) // allowOptionalRead = true
249  {
250  populate(std::move(entries));
251  }
252  entries.clear();
253 }
254 
255 
256 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
257 
259 {
260  clearLocalAddressing();
262 }
263 
264 
265 void Foam::faBoundaryMesh::clearLocalAddressing()
266 {
267  groupIDsPtr_.reset(nullptr);
268 }
269 
270 
271 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
272 
274 {
275  // processor initGeometry send/recv the following:
276  // - edgeCentres() : faMesh::edgeCentres()
277  // - edgeLengths() : faMesh::Le()
278  // - edgeFaceCentres() : faMesh::areaCentres()
279  //
280  // faMesh::Le() has its own point-to-point communication (OK) but
281  // triggers either/or edgeAreaNormals(), pointAreaNormals()
282  // with their own communication that can block.
283 
284  // This uses parallel comms and hence will not be trigggered
285  // on processors that do not have a processorFaPatch so instead
286  // force construction.
287 
288  (void)mesh_.edgeAreaNormals();
289  (void)mesh_.pointAreaNormals();
290 
291  (void)mesh_.areaCentres();
292  (void)mesh_.faceAreaNormals();
293 
294 
296 
297  if
298  (
299  pBufs.commsType() == Pstream::commsTypes::buffered
300  || pBufs.commsType() == Pstream::commsTypes::nonBlocking
301  )
302  {
303  forAll(*this, patchi)
304  {
305  operator[](patchi).initGeometry(pBufs);
306  }
307 
308  pBufs.finishedSends();
309 
310  forAll(*this, patchi)
311  {
312  operator[](patchi).calcGeometry(pBufs);
313  }
314  }
315  else if (pBufs.commsType() == Pstream::commsTypes::scheduled)
316  {
317  const lduSchedule& patchSchedule = mesh().globalData().patchSchedule();
318 
319  // Dummy.
320  pBufs.finishedSends();
321 
322  for (const auto& patchEval : patchSchedule)
323  {
324  const label patchi = patchEval.patch;
325 
326  if (patchEval.init)
327  {
328  operator[](patchi).initGeometry(pBufs);
329  }
330  else
331  {
332  operator[](patchi).calcGeometry(pBufs);
333  }
334  }
335  }
336 }
337 
338 
341 {
342  const faPatchList& patches = *this;
343 
344  UPtrList<const labelUList> list(patches.size());
345 
346  forAll(list, patchi)
347  {
348  list.set(patchi, &patches[patchi].edgeLabels());
349  }
350 
351  return list;
352 }
353 
354 
357 {
358  const faPatchList& patches = *this;
359 
360  UPtrList<const labelUList> list(patches.size());
361 
362  forAll(list, patchi)
363  {
364  list.set(patchi, &patches[patchi].edgeFaces());
365  }
366 
367  return list;
368 }
369 
370 
372 {
373  const faPatchList& patches = *this;
374 
376 
377  forAll(list, patchi)
378  {
379  const lduInterface* lduPtr = isA<lduInterface>(patches[patchi]);
380 
381  if (lduPtr)
382  {
383  list.set(patchi, lduPtr);
384  }
385  }
386 
387  return list;
388 }
389 
390 
391 Foam::label Foam::faBoundaryMesh::nNonProcessor() const
392 {
393  const faPatchList& patches = *this;
394 
395  label count = 0;
396 
397  for (const faPatch& p : patches)
398  {
399  if (isA<processorFaPatch>(p))
400  {
401  break;
402  }
403 
404  ++count;
405  }
406 
407  return count;
408 }
409 
410 
411 Foam::label Foam::faBoundaryMesh::nProcessorPatches() const
412 {
413  const faPatchList& patches = *this;
414 
415  label count = 0;
416 
417  for (const faPatch& p : patches)
418  {
419  if (isA<processorFaPatch>(p))
420  {
421  ++count;
422  }
423  }
424 
425  return count;
426 }
427 
428 
430 {
431  const faPatchList& patches = *this;
432 
433  label count = 0;
434 
435  for (const faPatch& p : patches)
436  {
437  if (isA<processorFaPatch>(p))
438  {
439  break;
440  }
441 
442  count += p.nEdges();
443  }
444 
445  return count;
446 }
447 
448 
451 {
452  if (!groupIDsPtr_)
453  {
454  calcGroupIDs();
455  }
456 
457  return *groupIDsPtr_;
458 }
459 
460 
462 (
463  const word& groupName,
464  const labelUList& patchIDs
465 )
466 {
467  groupIDsPtr_.reset(nullptr);
468 
469  faPatchList& patches = *this;
470 
471  boolList pending(patches.size(), true);
472 
473  // Add to specified patches
474  for (const label patchi : patchIDs)
475  {
476  if (pending.test(patchi))
477  {
478  pending.unset(patchi);
479  patches[patchi].addGroup(groupName);
480  }
481  }
482 
483  // Remove from other patches
484  forAll(patches, patchi)
485  {
486  if (pending.test(patchi))
487  {
488  patches[patchi].removeGroup(groupName);
489  }
490  }
491 }
492 
495 {
496  return PtrListOps::get<word>(*this, nameOp<faPatch>());
497 }
498 
501 {
502  return PtrListOps::get<word>(*this, typeOp<faPatch>());
503 }
504 
505 
507 {
508  // Manually: faPatch does not have independent start() information
509 
510  const faPatchList& patches = *this;
511 
512  labelList list(patches.size());
513 
514  label beg = mesh_.nInternalEdges();
515  forAll(patches, patchi)
516  {
517  const label len = patches[patchi].nEdges();
518  list[patchi] = beg;
519  beg += len;
520  }
521  return list;
522 }
523 
524 
526 {
527  return
528  PtrListOps::get<label>
529  (
530  *this,
531  [](const faPatch& p) { return p.nEdges(); } // avoid virtual
532  );
533 }
534 
535 
537 {
538  const faPatchList& patches = *this;
539 
540  List<labelRange> list(patches.size());
541 
542  label beg = mesh_.nInternalEdges();
543  forAll(patches, patchi)
544  {
545  const label len = patches[patchi].nEdges();
546  list[patchi].reset(beg, len);
547  beg += len;
548  }
549  return list;
550 }
551 
554 {
555  return this->groupPatchIDs().sortedToc();
556 }
557 
559 Foam::label Foam::faBoundaryMesh::start() const
560 {
561  return mesh_.nInternalEdges();
562 }
563 
565 Foam::label Foam::faBoundaryMesh::nEdges() const
566 {
567  return mesh_.nBoundaryEdges();
568 }
569 
570 
572 {
573  return labelRange(mesh_.nInternalEdges(), mesh_.nBoundaryEdges());
574 }
575 
576 
578 (
579  const wordRe& matcher,
580  const bool useGroups
581 ) const
582 {
583  if (matcher.empty())
584  {
585  return labelList();
586  }
587 
588  // Only check groups if requested and they exist
589  const bool checkGroups = (useGroups && this->hasGroupIDs());
590 
591  labelHashSet ids;
592 
593  if (matcher.isPattern())
594  {
595  if (checkGroups)
596  {
597  ids.reserve(this->size());
598 
599  const auto& groupLookup = groupPatchIDs();
600  forAllConstIters(groupLookup, iter)
601  {
602  if (matcher(iter.key()))
603  {
604  // Add ids associated with the group
605  ids.insert(iter.val());
606  }
607  }
608  }
609 
610  if (ids.empty())
611  {
612  return PtrListOps::findMatching(*this, matcher);
613  }
614  else
615  {
616  ids.insert(PtrListOps::findMatching(*this, matcher));
617  }
618  }
619  else
620  {
621  // Literal string.
622  // Special version of above for reduced memory footprint
623 
624  const label patchId = PtrListOps::firstMatching(*this, matcher);
625 
626  if (patchId >= 0)
627  {
628  return labelList(one{}, patchId);
629  }
630  else if (checkGroups)
631  {
632  const auto iter = groupPatchIDs().cfind(matcher);
633 
634  if (iter.good())
635  {
636  // Add ids associated with the group
637  ids.insert(iter.val());
638  }
639  }
640  }
641 
642  return ids.sortedToc();
643 }
644 
645 
647 (
648  const wordRes& matcher,
649  const bool useGroups
650 ) const
651 {
652  if (matcher.empty())
653  {
654  return labelList();
655  }
656  else if (matcher.size() == 1)
657  {
658  return this->indices(matcher.front(), useGroups);
659  }
660 
661  labelHashSet ids;
662 
663  // Only check groups if requested and they exist
664  if (useGroups && this->hasGroupIDs())
665  {
666  ids.reserve(this->size());
667 
668  const auto& groupLookup = groupPatchIDs();
669  forAllConstIters(groupLookup, iter)
670  {
671  if (matcher(iter.key()))
672  {
673  // Add ids associated with the group
674  ids.insert(iter.val());
675  }
676  }
677  }
678 
679  if (ids.empty())
680  {
681  return PtrListOps::findMatching(*this, matcher);
682  }
683  else
684  {
685  ids.insert(PtrListOps::findMatching(*this, matcher));
686  }
687 
688  return ids.sortedToc();
689 }
690 
691 
693 (
694  const wordRes& allow,
695  const wordRes& deny,
696  const bool useGroups
697 ) const
698 {
699  if (allow.empty() && deny.empty())
700  {
701  // Fast-path: select all
702  return identity(this->size());
703  }
704 
705  const wordRes::filter matcher(allow, deny);
706 
707  labelHashSet ids;
708 
709  // Only check groups if requested and they exist
710  if (useGroups && this->hasGroupIDs())
711  {
712  ids.reserve(this->size());
713 
714  const auto& groupLookup = groupPatchIDs();
715  forAllConstIters(groupLookup, iter)
716  {
717  if (matcher(iter.key()))
718  {
719  // Add ids associated with the group
720  ids.insert(iter.val());
721  }
722  }
723  }
724 
725  if (ids.empty())
726  {
727  return PtrListOps::findMatching(*this, matcher);
728  }
729  else
730  {
731  ids.insert(PtrListOps::findMatching(*this, matcher));
732  }
733 
734  return ids.sortedToc();
735 }
736 
737 
738 Foam::label Foam::faBoundaryMesh::findIndex(const wordRe& key) const
739 {
740  if (key.empty())
741  {
742  return -1;
743  }
744  return PtrListOps::firstMatching(*this, key);
745 }
746 
747 
749 (
750  const word& patchName,
751  bool allowNotFound
752 ) const
753 {
754  if (patchName.empty())
755  {
756  return -1;
757  }
758 
759  const label patchId = PtrListOps::firstMatching(*this, patchName);
760 
761  if (patchId >= 0)
762  {
763  return patchId;
764  }
765 
766  if (!allowNotFound)
767  {
769  << "Patch '" << patchName << "' not found. "
770  << "Available patch names: " << names() << endl
771  << exit(FatalError);
772  }
773 
774  // Patch not found
775  if (debug)
776  {
777  Pout<< "label faBoundaryMesh::findPatchID(const word&) const"
778  << "Patch named " << patchName << " not found. "
779  << "Available patch names: " << names() << endl;
780  }
781 
782  // Not found, return -1
783  return -1;
784 }
785 
786 
787 Foam::label Foam::faBoundaryMesh::whichPatch(const label edgeIndex) const
788 {
789  if (edgeIndex < mesh().nInternalEdges())
790  {
791  // Internal edge
792  return -1;
793  }
794  else if (edgeIndex >= mesh().nEdges())
795  {
796  // Bounds error: abort
798  << "Edge " << edgeIndex
799  << " out of bounds. Number of geometric edges " << mesh().nEdges()
800  << abort(FatalError);
801 
802  return -1;
803  }
804 
805  // Find patch that the edgeIndex belongs to.
806 
807  forAll(*this, patchi)
808  {
809  label start = mesh_.patchStarts()[patchi];
810  label size = operator[](patchi).faPatch::size();
811 
812  if (edgeIndex >= start && edgeIndex < start + size)
813  {
814  return patchi;
815  }
816  }
817 
818  // If not in any of above, it's trouble!
820  << "Error in patch search algorithm"
821  << abort(FatalError);
822 
823  return -1;
824 }
825 
826 
827 bool Foam::faBoundaryMesh::checkParallelSync(const bool report) const
828 {
829  if (!Pstream::parRun())
830  {
831  return false;
832  }
833 
834  const faBoundaryMesh& bm = *this;
835 
836  bool hasError = false;
837 
838  // Collect non-proc patches and check proc patches are last.
839  wordList localNames(bm.size());
840  wordList localTypes(bm.size());
841 
842  label nonProci = 0;
843 
844  forAll(bm, patchi)
845  {
846  if (!isA<processorFaPatch>(bm[patchi]))
847  {
848  if (nonProci != patchi)
849  {
850  // A processor patch in between normal patches!
851  hasError = true;
852 
853  if (debug || report)
854  {
855  Pout<< " ***Problem with boundary patch " << patchi
856  << " name:" << bm[patchi].name()
857  << " type:" << bm[patchi].type()
858  << " - seems to be preceeded by processor patches."
859  << " This is usually a problem." << endl;
860  }
861  }
862  else
863  {
864  localNames[nonProci] = bm[patchi].name();
865  localTypes[nonProci] = bm[patchi].type();
866  ++nonProci;
867  }
868  }
869  }
870  localNames.resize(nonProci);
871  localTypes.resize(nonProci);
872 
873  // Check and report error(s) on master
874  // - don't need indexing on master itself
875 
876  const globalIndex procAddr(globalIndex::gatherNonLocal{}, nonProci);
877 
878  const wordList allNames(procAddr.gather(localNames));
879  const wordList allTypes(procAddr.gather(localTypes));
880 
881  // Automatically restricted to master
882  for (const int proci : procAddr.subProcs())
883  {
884  const auto procNames(allNames.slice(procAddr.range(proci)));
885  const auto procTypes(allTypes.slice(procAddr.range(proci)));
886 
887  if (procNames != localNames || procTypes != localTypes)
888  {
889  hasError = true;
890 
891  if (debug || report)
892  {
893  Info<< " ***Inconsistent patches across processors, "
894  "processor0 has patch names:" << localNames
895  << " patch types:" << localTypes
896  << " processor" << proci
897  << " has patch names:" << procNames
898  << " patch types:" << procTypes
899  << endl;
900  }
901  }
902  }
903 
904  // Reduce (not broadcast) to respect local out-of-order errors (first loop)
905  return returnReduceOr(hasError);
906 }
907 
908 
909 bool Foam::faBoundaryMesh::checkDefinition(const bool report) const
910 {
911  label nextPatchStart = mesh().nInternalEdges();
912  const faBoundaryMesh& bm = *this;
913 
914  bool hasError = false;
915 
916  forAll(bm, patchi)
917  {
918  if (bm[patchi].start() != nextPatchStart && !hasError)
919  {
920  hasError = true;
921 
923  << " ****Problem with boundary patch " << patchi
924  << " named " << bm[patchi].name()
925  << " of type " << bm[patchi].type()
926  << ". The patch should start on face no " << nextPatchStart
927  << " and the patch specifies " << bm[patchi].start()
928  << "." << endl
929  << "Possibly consecutive patches have this same problem."
930  << " Suppressing future warnings." << endl;
931  }
932 
933  // Warn about duplicate boundary patches?
934 
935  nextPatchStart += bm[patchi].faPatch::size();
936  }
937 
938  if (hasError)
939  {
941  << "This mesh is not valid: boundary definition is in error."
942  << endl;
943  }
944  else
945  {
946  if (debug || report)
947  {
948  Info << "Boundary definition OK." << endl;
949  }
950  }
951 
952  return hasError;
953 }
954 
955 
957 {
958  // See comments in calcGeometry()
959 
960  (void)mesh_.edgeAreaNormals();
961  (void)mesh_.pointAreaNormals();
962 
963  (void)mesh_.areaCentres();
964  (void)mesh_.faceAreaNormals();
965 
966 
967  PstreamBuffers pBufs(Pstream::defaultCommsType);
968 
969  if
970  (
971  pBufs.commsType() == Pstream::commsTypes::buffered
972  || pBufs.commsType() == Pstream::commsTypes::nonBlocking
973  )
974  {
975  forAll(*this, patchi)
976  {
977  operator[](patchi).initMovePoints(pBufs, p);
978  }
979 
980  pBufs.finishedSends();
981 
982  forAll(*this, patchi)
983  {
984  operator[](patchi).movePoints(pBufs, p);
985  }
986  }
987  else if (pBufs.commsType() == Pstream::commsTypes::scheduled)
988  {
989  const lduSchedule& patchSchedule = mesh().globalData().patchSchedule();
990 
991  // Dummy.
992  pBufs.finishedSends();
993 
994  for (const auto& schedEval : patchSchedule)
995  {
996  const label patchi = schedEval.patch;
997 
998  if (schedEval.init)
999  {
1000  operator[](patchi).initMovePoints(pBufs, p);
1001  }
1002  else
1003  {
1004  operator[](patchi).movePoints(pBufs, p);
1005  }
1006  }
1007  }
1008 }
1009 
1010 
1012 {
1013  PstreamBuffers pBufs(Pstream::defaultCommsType);
1014 
1015  if
1016  (
1017  pBufs.commsType() == Pstream::commsTypes::buffered
1018  || pBufs.commsType() == Pstream::commsTypes::nonBlocking
1019  )
1020  {
1021  forAll(*this, patchi)
1022  {
1023  operator[](patchi).initUpdateMesh(pBufs);
1024  }
1025 
1026  pBufs.finishedSends();
1027 
1028  forAll(*this, patchi)
1029  {
1030  operator[](patchi).updateMesh(pBufs);
1031  }
1032  }
1033  else if (pBufs.commsType() == Pstream::commsTypes::scheduled)
1034  {
1035  const lduSchedule& patchSchedule = mesh().globalData().patchSchedule();
1036 
1037  // Dummy.
1038  pBufs.finishedSends();
1039 
1040  for (const auto& schedEval : patchSchedule)
1041  {
1042  const label patchi = schedEval.patch;
1043 
1044  if (schedEval.init)
1045  {
1046  operator[](patchi).initUpdateMesh(pBufs);
1047  }
1048  else
1049  {
1050  operator[](patchi).updateMesh(pBufs);
1051  }
1052  }
1053  }
1054 }
1055 
1056 
1057 void Foam::faBoundaryMesh::writeEntry(Ostream& os) const
1058 {
1059  const faPatchList& entries = *this;
1060 
1061  os << entries.size();
1062 
1063  if (entries.empty())
1064  {
1065  // 0-sized : can write with less vertical space
1067  }
1068  else
1069  {
1070  os << nl << token::BEGIN_LIST << incrIndent << nl;
1071 
1072  for (const auto& pp : entries)
1073  {
1074  os.beginBlock(pp.name());
1075  os << pp;
1076  os.endBlock();
1077  }
1079  }
1081 }
1082 
1083 
1085 (
1086  const word& keyword,
1087  Ostream& os
1088 ) const
1089 {
1090  const faPatchList& entries = *this;
1091 
1092  if (!keyword.empty())
1093  {
1094  os.write(keyword);
1095  os << (entries.empty() ? token::SPACE : token::NL);
1096  }
1098  writeEntry(os);
1099 
1100  if (!keyword.empty()) os.endEntry();
1101 }
1102 
1103 
1106  writeEntry(os);
1107  return os.good();
1108 }
1109 
1110 
1112 (
1113  IOstreamOption streamOpt,
1114  const bool writeOnProc
1115 ) const
1116 {
1118  return regIOobject::writeObject(streamOpt, writeOnProc);
1119 }
1120 
1121 
1122 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
1123 
1124 Foam::Ostream& Foam::operator<<(Ostream& os, const faBoundaryMesh& bm)
1125 {
1126  bm.writeData(os);
1127  return os;
1128 }
1129 
1130 
1131 // ************************************************************************* //
wordList groupNames() const
A list of the group names (if any)
label whichPatch(const label edgeIndex) const
Return patch index for a given edge label.
PtrList< faPatch > faPatchList
Store lists of faPatch as a PtrList.
Definition: faPatch.H:59
Finite area mesh (used for 2-D non-Euclidian finite area method) defined using a patch of faces on a ...
Definition: faMesh.H:133
labelRange range(const label proci) const
Return start/size range of proci data.
Definition: globalIndexI.H:282
label patchId(-1)
List< labelRange > patchRanges() const
Return a list of patch ranges.
const labelList patchIDs(pbm.indices(polyPatchNames, true))
static autoPtr< faPatch > New(const word &name, const dictionary &dict, const label index, const faBoundaryMesh &bm)
Return pointer to a new patch created on freestore from dictionary.
Definition: faPatchNew.C:28
dictionary dict
autoPtr< IOobject > clone() const
Clone.
Definition: IOobject.H:629
labelList indices(const wordRe &matcher, const bool useGroups=true) const
The (sorted) patch indices for all matches, optionally matching patch groups.
labelList findMatching(const UPtrList< T > &list, const UnaryMatchPredicate &matcher)
Extract list indices for all items with &#39;name()&#39; that matches.
bool checkDefinition(const bool report=false) const
Check boundary definition.
List< word > names(const UPtrList< T > &list, const UnaryMatchPredicate &matcher)
List of names generated by calling name() for each list item and filtered for matches.
void clear()
Clear the patch list and all demand-driven data.
virtual const fileName & name() const
The name of the stream.
Definition: IOstream.C:33
virtual bool writeData(Ostream &os) const
The writeData member function required by regIOobject.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
virtual Ostream & write(const char c) override
Write character.
Definition: OBJstream.C:69
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:600
virtual bool check(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:45
lduInterfacePtrsList interfaces() const
Return a list of pointers for each patch with only those pointing to interfaces being set...
void calcGeometry()
Calculate the geometry for the patches.
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:195
labelList patchSizes() const
Return a list of patch sizes (number of edges in each patch)
UPtrList< const labelUList > edgeFaces() const
Return a list of edgeFaces for each patch.
A range or interval of labels defined by a start and a size.
Definition: labelRange.H:52
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Type type(bool followLink=true, bool checkGzip=false) const
Return the directory entry type: UNDEFINED, FILE, DIRECTORY (or SYMLINK).
Definition: fileName.C:353
Newline [isspace].
Definition: token.H:130
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:529
void updateMesh()
Correct faBoundaryMesh after topology update.
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1586
Begin list [isseparator].
Definition: token.H:161
List< lduScheduleEntry > lduSchedule
A List of lduSchedule entries.
Definition: lduSchedule.H:46
Functions to operate on Pointer Lists.
A simple container for options an IOstream can normally have.
static void gather(const labelUList &offsets, const label comm, const ProcIDsContainer &procIDs, const UList< Type > &fld, UList< Type > &allFld, const int tag=UPstream::msgType(), UPstream::commsTypes commsType=UPstream::commsTypes::nonBlocking)
Collect data in processor order on master (== procIDs[0]).
virtual bool writeObject(IOstreamOption streamOpt, const bool writeOnProc) const
Write using stream options.
const HashTable< labelList > & groupPatchIDs() const
The patch indices per patch group.
label findIndex(const wordRe &key) const
Return patch index for the first match, return -1 if not found.
virtual const fileName & name() const override
Get the name of the output serial stream. (eg, the name of the Fstream file name) ...
Definition: OSstream.H:134
void writeEntry(Ostream &os) const
Write as a plain list of entries.
UList< label > labelUList
A UList of labels.
Definition: UList.H:76
Extract name (as a word) from an object, typically using its name() method.
Definition: word.H:340
#define SeriousErrorInFunction
Report an error message using Foam::SeriousError.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:286
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition: HashSet.H:85
void resize_null(const label newLen)
Set the addressed list to the given size, deleting all existing entries. Afterwards the list contains...
Definition: PtrListI.H:96
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of &#39;true&#39; entries.
Definition: BitOps.H:73
label findPatchID(const word &patchName, const bool allowNotFound=true) const
Find patch index given a name, return -1 if not found.
label nNonProcessorEdges() const
The number of boundary edges before the first processor patch.
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
void movePoints(const pointField &)
Correct faBoundaryMesh after moving points.
dynamicFvMesh & mesh
"scheduled" (MPI standard) : (MPI_Send, MPI_Recv)
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i), works like std::iota() but returning a...
Definition: labelLists.C:44
wordList names() const
Return a list of patch names.
label size() const noexcept
The number of entries in the list.
Definition: UPtrListI.H:106
virtual Ostream & endBlock()
Write end block group.
Definition: Ostream.C:108
Space [isspace].
Definition: token.H:131
UPtrList< const lduInterface > lduInterfacePtrsList
Store lists of lduInterface as a UPtrList.
const globalMeshData & globalData() const
Return parallel info (demand-driven)
Definition: polyMesh.C:1296
End list [isseparator].
Definition: token.H:162
auto key(const Type &t) -> std::enable_if_t< std::is_enum_v< Type >, std::underlying_type_t< Type > >
Definition: foamGltfBase.H:103
A HashTable similar to std::unordered_map.
Definition: HashTable.H:108
A list of pointers to objects of type <T>, without allocation/deallocation management of the pointers...
Definition: HashTable.H:106
bool returnReduceOr(const bool value, const int communicator=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
errorManip< error > abort(error &err)
Definition: errorManip.H:139
const T * set(const label i) const
Return const pointer to element (can be nullptr), or nullptr for out-of-range access (ie...
Definition: PtrList.H:159
label nEdges() const
Number of mesh edges.
A wordRe is a Foam::word, but can contain a regular expression for matching words or strings...
Definition: wordRe.H:78
label nInternalEdges() const
Internal edges using 0,1 or 2 boundary points.
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
int debug
Static debugging option.
wordList types() const
Return a list of patch types.
OBJstream os(runTime.globalPath()/outputName)
#define FUNCTION_NAME
faBoundaryMesh(const faBoundaryMesh &)=delete
No copy construct.
std::enable_if_t< std::is_same_v< bool, TypeT >, bool > unset(const label i)
Unset the bool entry at specified position, always false for out-of-range access. ...
Definition: UList.H:827
defineTypeNameAndDebug(combustionModel, 0)
Finite area patch class. Used for 2-D non-Euclidian finite area method.
Definition: faPatch.H:72
compressionType compression() const noexcept
Get the stream compression.
Ostream & decrIndent(Ostream &os)
Decrement the indent level.
Definition: Ostream.H:509
Buffers for inter-processor communications streams (UOPstream, UIPstream).
label start() const
The start label of the edges in the faMesh edges list.
UPtrList< const labelUList > edgeLabels() const
Return a list of edgeLabels for each patch.
label nEdges() const
The number of boundary edges for the underlying mesh.
labelRange subProcs() const noexcept
Range of process indices for addressed sub-offsets (processes)
Definition: globalIndexI.H:197
Ostream & operator<<(Ostream &, const boundaryPatch &p)
Write boundaryPatch as dictionary entries (without surrounding braces)
Definition: boundaryPatch.C:77
List< word > wordList
List of word.
Definition: fileName.H:59
static commsTypes defaultCommsType
Default commsType.
Definition: UPstream.H:963
#define WarningInFunction
Report a warning using Foam::Warning.
globalIndex procAddr(aMesh.nFaces())
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
Definition: List.H:54
label nNonProcessor() const
The number of patches before the first processor patch.
bool good() const noexcept
True if next operation might succeed.
Definition: IOstream.H:281
void reserve(label numEntries)
Reserve space for at least the specified number of elements (not the number of buckets) and regenerat...
Definition: HashTable.C:729
const lduSchedule & patchSchedule() const noexcept
Order in which the patches should be initialised/evaluated corresponding to the schedule.
const polyBoundaryMesh & patches
void setGroup(const word &groupName, const labelUList &patchIDs)
Set/add group with patches.
bool checkParallelSync(const bool report=false) const
Check whether all procs have all patches and in same order.
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:68
void clear()
Clear the PtrList. Delete allocated entries and set size to zero.
Definition: PtrListI.H:81
"nonBlocking" (immediate) : (MPI_Isend, MPI_Irecv)
messageStream Info
Information stream (stdout output on master, null elsewhere)
virtual Ostream & beginBlock(const keyType &kw)
Write begin block group with the given name.
Definition: Ostream.C:90
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition: zero.H:57
labelRange range() const
The edge range for all boundary edges.
List< label > labelList
A List of labels.
Definition: List.H:61
volScalarField & p
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
virtual Ostream & endEntry()
Write end entry (&#39;;&#39;) followed by newline.
Definition: Ostream.C:117
"buffered" : (MPI_Bsend, MPI_Recv)
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Definition: Ostream.H:500
virtual bool writeObject(IOstreamOption streamOpt, const bool writeOnProc=true) const
Write using stream options, but always UNCOMPRESSED.
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:180
Calculate the matrix for the second temporal derivative.
labelList patchStarts() const
Return a list of patch start indices.
List< bool > boolList
A List of bools.
Definition: List.H:59
label nProcessorPatches() const
The number of processorFaPatch patches.
bool isPattern() const noexcept
The wordRe is a pattern, not a literal string.
Definition: wordReI.H:104
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Extract type (as a word) from an object, typically using its type() method.
Definition: word.H:361
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
Namespace for OpenFOAM.
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
label firstMatching(const UPtrList< T > &list, const UnaryMatchPredicate &matcher)
Find first list item with &#39;name()&#39; that matches, -1 on failure.
#define InfoInFunction
Report an information message using Foam::Info.