Loading...
Searching...
No Matches
conformalVoronoiMeshZones.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) 2013-2016 OpenFOAM Foundation
9 Copyright (C) 2021 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
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
30#include "polyModifyFace.H"
31#include "polyModifyCell.H"
32#include "syncTools.H"
33#include "regionSplit.H"
34#include "surfaceZonesInfo.H"
35
36// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
37
38void Foam::conformalVoronoiMesh::calcNeighbourCellCentres
39(
40 const polyMesh& mesh,
41 const pointField& cellCentres,
42 pointField& neiCc
43) const
44{
45 const label nBoundaryFaces = mesh.nBoundaryFaces();
46
47 if (neiCc.size() != nBoundaryFaces)
48 {
50 << "nBoundaries:" << nBoundaryFaces
51 << " neiCc:" << neiCc.size()
52 << abort(FatalError);
53 }
54
55 const polyBoundaryMesh& patches = mesh.boundaryMesh();
56
57 forAll(patches, patchi)
58 {
59 const polyPatch& pp = patches[patchi];
60
61 const labelUList& faceCells = pp.faceCells();
62
63 label bFacei = pp.start() - mesh.nInternalFaces();
64
65 if (pp.coupled())
66 {
67 forAll(faceCells, i)
68 {
69 neiCc[bFacei] = cellCentres[faceCells[i]];
70 bFacei++;
71 }
72 }
73 }
74
75 // Swap coupled boundaries. Apply separation to cc since is coordinate.
77}
78
79
80void Foam::conformalVoronoiMesh::selectSeparatedCoupledFaces
81(
82 const polyMesh& mesh,
83 boolList& selected
84) const
85{
86 for (const polyPatch& pp : mesh.boundaryMesh())
87 {
88 // Check all coupled. Avoid using .coupled() so we also pick up AMI.
89
90 const auto* cpp = isA<coupledPolyPatch>(pp);
91
92 if (cpp && (cpp->separated() || !cpp->parallel()))
93 {
94 SubList<bool>(selected, pp.size(), pp.start()) = true;
95 }
96 }
97}
98
99
100void Foam::conformalVoronoiMesh::findCellZoneInsideWalk
101(
102 const polyMesh& mesh,
103 const labelList& locationSurfaces, // indices of surfaces with inside point
104 const labelList& faceToSurface, // per face index of named surface
105 labelList& cellToSurface
106) const
107{
108 // Analyse regions. Reuse regionsplit
109 boolList blockedFace(mesh.nFaces());
110 selectSeparatedCoupledFaces(mesh, blockedFace);
111
112 forAll(faceToSurface, facei)
113 {
114 if (faceToSurface[facei] == -1)
115 {
116 blockedFace[facei] = false;
117 }
118 else
119 {
120 blockedFace[facei] = true;
121 }
122 }
123 // No need to sync since namedSurfaceIndex already is synced
124
125 // Set region per cell based on walking
126 regionSplit cellRegion(mesh, blockedFace);
127 blockedFace.clear();
128
129
130 // Force calculation of face decomposition (used in findCell)
131 (void)mesh.tetBasePtIs();
132
133 const PtrList<surfaceZonesInfo>& surfZones =
134 geometryToConformTo().surfZones();
135
136 // For all locationSurface find the cell
137 forAll(locationSurfaces, i)
138 {
139 label surfI = locationSurfaces[i];
140
141 const Foam::point& insidePoint = surfZones[surfI].zoneInsidePoint();
142
143 const word& surfName = geometryToConformTo().geometry().names()[surfI];
144
145 Info<< " For surface " << surfName
146 << " finding inside point " << insidePoint
147 << endl;
148
149 // Find the region containing the insidePoint
150 label keepRegionI = -1;
151
152 label celli = mesh.findCell(insidePoint);
153
154 if (celli != -1)
155 {
156 keepRegionI = cellRegion[celli];
157 }
158 reduce(keepRegionI, maxOp<label>());
159
160 Info<< " For surface " << surfName
161 << " found point " << insidePoint << " in cell " << celli
162 << " in global region " << keepRegionI
163 << " out of " << cellRegion.nRegions() << " regions." << endl;
164
165 if (keepRegionI == -1)
166 {
168 << "Point " << insidePoint
169 << " is not inside the mesh." << nl
170 << "Bounding box of the mesh:" << mesh.bounds()
171 << exit(FatalError);
172 }
173
174 // Set all cells with this region
175 forAll(cellRegion, celli)
176 {
177 if (cellRegion[celli] == keepRegionI)
178 {
179 if (cellToSurface[celli] == -2)
180 {
181 cellToSurface[celli] = surfI;
182 }
183 else if (cellToSurface[celli] != surfI)
184 {
186 << "Cell " << celli
187 << " at " << mesh.cellCentres()[celli]
188 << " is inside surface " << surfName
189 << " but already marked as being in zone "
190 << cellToSurface[celli] << endl
191 << "This can happen if your surfaces are not"
192 << " (sufficiently) closed."
193 << endl;
194 }
195 }
196 }
197 }
198}
199
200
201Foam::labelList Foam::conformalVoronoiMesh::calcCellZones
202(
203 const pointField& cellCentres
204) const
205{
206 labelList cellToSurface(cellCentres.size(), label(-1));
207
208 const PtrList<surfaceZonesInfo>& surfZones =
209 geometryToConformTo().surfZones();
210
211 // Get list of closed surfaces
212 labelList closedNamedSurfaces
213 (
215 (
216 surfZones,
217 geometryToConformTo().geometry(),
218 geometryToConformTo().surfaces()
219 )
220 );
221
222 forAll(closedNamedSurfaces, i)
223 {
224 label surfI = closedNamedSurfaces[i];
225
227 allGeometry()[geometryToConformTo().surfaces()[surfI]];
228
229 const surfaceZonesInfo::areaSelectionAlgo selectionMethod =
230 surfZones[surfI].zoneInside();
231
232 if
233 (
234 selectionMethod != surfaceZonesInfo::INSIDE
235 && selectionMethod != surfaceZonesInfo::OUTSIDE
236 && selectionMethod != surfaceZonesInfo::INSIDEPOINT
237 )
238 {
240 << "Trying to use surface "
241 << surface.name()
242 << " which has non-geometric inside selection method "
244 << exit(FatalError);
245 }
246
247 if (surface.hasVolumeType())
248 {
249 List<volumeType> volType;
250 surface.getVolumeType(cellCentres, volType);
251
252 bool selectInside = true;
253 if (selectionMethod == surfaceZonesInfo::INSIDEPOINT)
254 {
255 List<volumeType> volTypeInsidePoint;
256 surface.getVolumeType
257 (
258 pointField(1, surfZones[surfI].zoneInsidePoint()),
259 volTypeInsidePoint
260 );
261
262 if (volTypeInsidePoint[0] == volumeType::OUTSIDE)
263 {
264 selectInside = false;
265 }
266 }
267 else if (selectionMethod == surfaceZonesInfo::OUTSIDE)
268 {
269 selectInside = false;
270 }
271
272 forAll(volType, pointi)
273 {
274 if (cellToSurface[pointi] == -1)
275 {
276 if
277 (
278 (
279 volType[pointi] == volumeType::INSIDE
280 && selectInside
281 )
282 || (
283 volType[pointi] == volumeType::OUTSIDE
284 && !selectInside
285 )
286 )
287 {
288 cellToSurface[pointi] = surfI;
289 }
290 }
291 }
292 }
293 }
294
295 return cellToSurface;
296}
297
298
299void Foam::conformalVoronoiMesh::calcFaceZones
300(
301 const polyMesh& mesh,
302 const pointField& cellCentres,
303 const labelList& cellToSurface,
304 labelList& faceToSurface,
305 boolList& flipMap
306) const
307{
308 faceToSurface.setSize(mesh.nFaces(), -1);
309 flipMap.setSize(mesh.nFaces(), false);
310
311 const faceList& faces = mesh.faces();
312 const labelList& faceOwner = mesh.faceOwner();
313 const labelList& faceNeighbour = mesh.faceNeighbour();
314
315 labelList neiFaceOwner(mesh.nBoundaryFaces(), label(-1));
316
318
319 forAll(patches, patchi)
320 {
321 const polyPatch& pp = patches[patchi];
322
323 const labelUList& faceCells = pp.faceCells();
324
325 label bFacei = pp.start() - mesh.nInternalFaces();
326
327 if (pp.coupled())
328 {
329 forAll(faceCells, i)
330 {
331 neiFaceOwner[bFacei] = cellToSurface[faceCells[i]];
332 bFacei++;
333 }
334 }
335 }
336
338
339 forAll(faces, facei)
340 {
341 const label ownerSurfacei = cellToSurface[faceOwner[facei]];
342
343 if (faceToSurface[facei] >= 0)
344 {
345 continue;
346 }
347
348 if (mesh.isInternalFace(facei))
349 {
350 const label neiSurfacei = cellToSurface[faceNeighbour[facei]];
351
352 if
353 (
354 (ownerSurfacei >= 0 || neiSurfacei >= 0)
355 && ownerSurfacei != neiSurfacei
356 )
357 {
358 flipMap[facei] =
359 (
360 ownerSurfacei == max(ownerSurfacei, neiSurfacei)
361 ? false
362 : true
363 );
364
365 faceToSurface[facei] = max(ownerSurfacei, neiSurfacei);
366 }
367 }
368 else
369 {
370 label patchID = mesh.boundaryMesh().whichPatch(facei);
371
372 if (mesh.boundaryMesh()[patchID].coupled())
373 {
374 const label neiSurfacei =
375 neiFaceOwner[facei - mesh.nInternalFaces()];
376
377 if
378 (
379 (ownerSurfacei >= 0 || neiSurfacei >= 0)
380 && ownerSurfacei != neiSurfacei
381 )
382 {
383 flipMap[facei] =
384 (
385 ownerSurfacei == max(ownerSurfacei, neiSurfacei)
386 ? false
387 : true
388 );
389
390 faceToSurface[facei] = max(ownerSurfacei, neiSurfacei);
391 }
392 }
393 else
394 {
395 if (ownerSurfacei >= 0)
396 {
397 faceToSurface[facei] = ownerSurfacei;
398 }
399 }
400 }
401 }
402
403
404 const PtrList<surfaceZonesInfo>& surfZones =
405 geometryToConformTo().surfZones();
406
407 labelList unclosedSurfaces
408 (
410 (
411 surfZones,
412 geometryToConformTo().geometry(),
413 geometryToConformTo().surfaces()
414 )
415 );
416
418 calcNeighbourCellCentres
419 (
420 mesh,
421 cellCentres,
422 neiCc
423 );
424
425 // Use intersection of cellCentre connections
426 forAll(faces, facei)
427 {
428 if (faceToSurface[facei] >= 0)
429 {
430 continue;
431 }
432
433 label patchID = mesh.boundaryMesh().whichPatch(facei);
434
435 const label own = faceOwner[facei];
436
437 List<pointIndexHit> surfHit;
438 labelList hitSurface;
439
440 if (mesh.isInternalFace(facei))
441 {
442 const label nei = faceNeighbour[facei];
443
444 geometryToConformTo().findSurfaceAllIntersections
445 (
446 cellCentres[own],
447 cellCentres[nei],
448 surfHit,
449 hitSurface
450 );
451 }
452 else if (patchID != -1 && mesh.boundaryMesh()[patchID].coupled())
453 {
454 geometryToConformTo().findSurfaceAllIntersections
455 (
456 cellCentres[own],
457 neiCc[facei - mesh.nInternalFaces()],
458 surfHit,
459 hitSurface
460 );
461 }
462
463 // If there are multiple intersections then do not add to
464 // a faceZone
465 if (surfHit.size() == 1 && surfHit[0].hit())
466 {
467 if (unclosedSurfaces.found(hitSurface[0]))
468 {
469 vectorField norm;
470 geometryToConformTo().getNormal
471 (
472 hitSurface[0],
473 List<pointIndexHit>(1, surfHit[0]),
474 norm
475 );
476
477 const vector areaNorm = faces[facei].areaNormal(mesh.points());
478
479 if ((norm[0] & areaNorm) < 0)
480 {
481 flipMap[facei] = true;
482 }
483 else
484 {
485 flipMap[facei] = false;
486 }
487
488 faceToSurface[facei] = hitSurface[0];
489 }
490 }
491 }
492
493
494// labelList neiCellSurface(mesh.nBoundaryFaces());
495//
496// forAll(patches, patchi)
497// {
498// const polyPatch& pp = patches[patchi];
499//
500// if (pp.coupled())
501// {
502// forAll(pp, i)
503// {
504// label facei = pp.start()+i;
505// label ownSurface = cellToSurface[faceOwner[facei]];
506// neiCellSurface[facei - mesh.nInternalFaces()] = ownSurface;
507// }
508// }
509// }
510// syncTools::swapBoundaryFaceList(mesh, neiCellSurface);
511//
512// forAll(patches, patchi)
513// {
514// const polyPatch& pp = patches[patchi];
515//
516// if (pp.coupled())
517// {
518// forAll(pp, i)
519// {
520// label facei = pp.start()+i;
521// label ownSurface = cellToSurface[faceOwner[facei]];
522// label neiSurface =
523// neiCellSurface[facei-mesh.nInternalFaces()];
524//
525// if (faceToSurface[facei] == -1 && (ownSurface != neiSurface))
526// {
527// // Give face the max cell zone
528// faceToSurface[facei] = max(ownSurface, neiSurface);
529// }
530// }
531// }
532// }
533
534 // Sync
536}
537
538
539void Foam::conformalVoronoiMesh::addZones
540(
541 polyMesh& mesh,
542 const pointField& cellCentres
543) const
544{
545 Info<< " Adding zones to mesh" << endl;
546
547 const PtrList<surfaceZonesInfo>& surfZones =
548 geometryToConformTo().surfZones();
549
550 labelList cellToSurface(calcCellZones(cellCentres));
551
552 labelList faceToSurface;
553 boolList flipMap;
554
555 calcFaceZones
556 (
557 mesh,
558 cellCentres,
559 cellToSurface,
560 faceToSurface,
561 flipMap
562 );
563
564 labelList insidePointNamedSurfaces
565 (
567 );
568
569 findCellZoneInsideWalk
570 (
571 mesh,
572 insidePointNamedSurfaces,
573 faceToSurface,
574 cellToSurface
575 );
576
577 labelList namedSurfaces(surfaceZonesInfo::getNamedSurfaces(surfZones));
578
579 // Tbd. No support yet for multi-faceZones on outside of cellZone
580
581 forAll(namedSurfaces, i)
582 {
583 label surfI = namedSurfaces[i];
584 const wordList& fzNames = surfZones[surfI].faceZoneNames();
585
586 Info<< incrIndent << indent << "Surface : "
587 << geometryToConformTo().geometry().names()[surfI] << nl
588 << indent << " faceZone : "
589 << (fzNames.size() ? fzNames[0] : "") << nl
590 << indent << " cellZone : "
591 << surfZones[surfI].cellZoneName()
592 << decrIndent << endl;
593 }
594
595 // Add zones to mesh
596 labelList surfaceToFaceZone(surfZones.size(), -1);
597 {
598 const labelListList surfaceToFaceZones
599 (
601 (
602 surfZones,
603 namedSurfaces,
604 mesh
605 )
606 );
607 forAll(surfaceToFaceZones, surfi)
608 {
609 if (surfaceToFaceZones[surfi].size())
610 {
611 surfaceToFaceZone[surfi] = surfaceToFaceZones[surfi][0];
612 }
613 }
614 }
615
616 const labelList surfaceToCellZone
617 (
619 (
620 surfZones,
621 namedSurfaces,
622 mesh
623 )
624 );
625
626 // Topochange container
627 polyTopoChange meshMod(mesh);
628
629 forAll(cellToSurface, celli)
630 {
631 label surfacei = cellToSurface[celli];
632
633 if (surfacei >= 0)
634 {
635 label zoneI = surfaceToCellZone[surfacei];
636
637 if (zoneI >= 0)
638 {
639 meshMod.setAction
640 (
642 (
643 celli,
644 false, // removeFromZone
645 zoneI
646 )
647 );
648 }
649 }
650 }
651
652 const labelList& faceOwner = mesh.faceOwner();
653 const labelList& faceNeighbour = mesh.faceNeighbour();
654
655 forAll(faceToSurface, facei)
656 {
657 label surfacei = faceToSurface[facei];
658
659 if (surfacei < 0)
660 {
661 continue;
662 }
663
664 label patchID = mesh.boundaryMesh().whichPatch(facei);
665
666 if (mesh.isInternalFace(facei))
667 {
668 label own = faceOwner[facei];
669 label nei = faceNeighbour[facei];
670
671 meshMod.setAction
672 (
674 (
675 mesh.faces()[facei], // modified face
676 facei, // label of face
677 own, // owner
678 nei, // neighbour
679 false, // face flip
680 -1, // patch for face
681 false, // remove from zone
682 surfaceToFaceZone[surfacei], // zone for face
683 flipMap[facei] // face flip in zone
684 )
685 );
686 }
687 else if (patchID != -1 && mesh.boundaryMesh()[patchID].coupled())
688 {
689 label own = faceOwner[facei];
690
691 meshMod.setAction
692 (
694 (
695 mesh.faces()[facei], // modified face
696 facei, // label of face
697 own, // owner
698 -1, // neighbour
699 false, // face flip
700 patchID, // patch for face
701 false, // remove from zone
702 surfaceToFaceZone[surfacei], // zone for face
703 flipMap[facei] // face flip in zone
704 )
705 );
706 }
707 }
708
709 // Change the mesh (no inflation, parallel sync)
710 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false, true);
711}
712
713
714// ************************************************************************* //
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
label size() const noexcept
The number of elements in the list.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition PtrList.H:67
A non-owning sub-view of a List (allocated or unallocated storage).
Definition SubList.H:61
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition autoPtr.H:65
Smooth ATC in cells next to a set of patches supplied by type.
Definition faceCells.H:55
A polyBoundaryMesh is a polyPatch list with registered IO, a reference to the associated polyMesh,...
label whichPatch(const label meshFacei) const
Return patch index for a given mesh face index. Uses binary search.
Mesh consisting of general polyhedral cells.
Definition polyMesh.H:79
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition polyMesh.H:609
virtual const faceList & faces() const
Return raw faces.
Definition polyMesh.C:1088
label findCell(const point &p, const cellDecomposition=CELL_TETS) const
Find cell enclosing this location and return index.
Definition polyMesh.C:1496
virtual const labelList & faceOwner() const
Return face owner.
Definition polyMesh.C:1101
const labelIOList & tetBasePtIs() const
Return the tetBasePtIs.
Definition polyMesh.C:884
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition polyMesh.C:1107
const boundBox & bounds() const noexcept
Return mesh bounding box.
Definition polyMesh.H:617
virtual const pointField & points() const
Return raw points.
Definition polyMesh.C:1063
Class describing modification of a cell.
Class describing modification of a face.
A patch is a list of labels that address the faces in the global face list.
Definition polyPatch.H:73
Direct mesh changes based on v1.3 polyTopoChange syntax.
bool isInternalFace(const label faceIndex) const noexcept
Return true if given face label is internal to the mesh.
label nBoundaryFaces() const noexcept
Number of boundary faces (== nFaces - nInternalFaces).
label nInternalFaces() const noexcept
Number of internal faces.
const vectorField & cellCentres() const
label nFaces() const noexcept
Number of mesh faces.
This class separates the mesh into distinct unconnected regions, each of which is then given a label ...
Base class of (analytical or triangulated) surface. Encapsulates all the search routines....
static labelList getInsidePointNamedSurfaces(const PtrList< surfaceZonesInfo > &surfList)
Get indices of surfaces with a cellZone that have 'insidePoint'.
areaSelectionAlgo
Types of selection of area.
static labelList getNamedSurfaces(const PtrList< surfaceZonesInfo > &surfList)
Get indices of named surfaces (surfaces with faceZoneName).
static labelList getAllClosedNamedSurfaces(const PtrList< surfaceZonesInfo > &surfList, const searchableSurfaces &allGeometry, const labelList &surfaces)
Get indices of surfaces with a cellZone that are closed.
static labelList addCellZonesToMesh(const PtrList< surfaceZonesInfo > &surfList, const labelList &namedSurfaces, polyMesh &mesh)
static labelList getUnclosedNamedSurfaces(const PtrList< surfaceZonesInfo > &surfList, const searchableSurfaces &allGeometry, const labelList &surfaces)
Get indices of surfaces with a cellZone that are unclosed.
static labelListList addFaceZonesToMesh(const PtrList< surfaceZonesInfo > &surfList, const labelList &namedSurfaces, polyMesh &mesh)
static const Enum< areaSelectionAlgo > areaSelectionAlgoNames
static void swapBoundaryFacePositions(const polyMesh &mesh, UList< point > &positions, const bool parRun=UPstream::parRun())
Swap coupled positions. Uses eqOp.
Definition syncTools.H:545
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
static void syncFaceList(const polyMesh &mesh, UList< T > &faceValues, const CombineOp &cop, const bool parRun=UPstream::parRun())
Synchronize values on all mesh faces.
Definition syncTools.H:465
@ OUTSIDE
A location outside the volume.
Definition volumeType.H:66
@ INSIDE
A location inside the volume.
Definition volumeType.H:65
A class for handling words, derived from Foam::string.
Definition word.H:66
const polyBoundaryMesh & patches
dynamicFvMesh & mesh
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
#define WarningInFunction
Report a warning using Foam::Warning.
const wordList surface
Standard surface field types (scalar, vector, tensor, etc).
List< word > wordList
List of word.
Definition fileName.H:60
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:40
List< labelList > labelListList
List of labelList.
Definition labelList.H:38
List< label > labelList
A List of labels.
Definition List.H:62
messageStream Info
Information stream (stdout output on master, null elsewhere).
List< face > faceList
List of faces.
Definition faceListFwd.H:41
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Definition Ostream.H:490
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
Ostream & indent(Ostream &os)
Indent stream.
Definition Ostream.H:481
const Type * isA(const U &obj)
Attempt dynamic_cast to Type.
Definition typeInfo.H:87
void reduce(T &value, BinaryOp bop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce).
errorManip< error > abort(error &err)
Definition errorManip.H:139
Field< vector > vectorField
Specialisation of Field<T> for vector.
vector point
Point is a vector.
Definition point.H:37
List< bool > boolList
A List of bools.
Definition List.H:60
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
vectorField pointField
pointField is a vectorField.
Vector< scalar > vector
Definition vector.H:57
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
UList< label > labelUList
A UList of labels.
Definition UList.H:75
Ostream & decrIndent(Ostream &os)
Decrement the indent level.
Definition Ostream.H:499
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299