coupledPolyPatch.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
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 \*---------------------------------------------------------------------------*/
25 
26 #include "coupledPolyPatch.H"
27 #include "ListOps.H"
28 #include "transform.H"
29 #include "OFstream.H"
30 
31 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
32 
33 namespace Foam
34 {
36 
37  const scalar coupledPolyPatch::defaultMatchTol_ = 1e-4;
38 }
39 
40 
41 // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
42 
43 bool Foam::coupledPolyPatch::walk
44 (
45  const primitivePatch& pp,
46  const bool direction,
47  const label seedFacei,
48  const label seedFacePointi,
50  labelList& facePointMap,
51  label& mapFacei,
52  autoPtr<labelListList>& walks
53 ) const
54 {
55  // Initialisation
56  label facei = seedFacei, facePointi = seedFacePointi;
57  faceMap[facei] = mapFacei;
58  facePointMap[facei] = facePointi;
59  bool changed = facei != mapFacei || facePointi != 0;
60  ++ mapFacei;
61  if (walks.valid())
62  {
63  walks->append(labelList(1, facei));
64  }
65 
66  // Walk the patch until we get back to the seed face and point
67  do
68  {
69  // Get the next point around the face
70  const label facePointi1 =
71  direction
72  ? pp[facei].fcIndex(facePointi)
73  : pp[facei].rcIndex(facePointi);
74 
75  // Get the current edge within the face
76  const label faceEdgei =
77  direction ? facePointi : pp[facei].rcIndex(facePointi);
78  const label edgei = pp.faceEdges()[facei][faceEdgei];
79 
80  // If the number of faces connected to this edge is not 2, then this
81  // edge is non-manifold and is considered a boundary to the walk. So,
82  // the walk moves on to the next point around the current face.
83  if (pp.edgeFaces()[edgei].size() != 2)
84  {
85  facePointi = facePointi1;
86  continue;
87  }
88 
89  // Get the connected face and the corresponding point index within
90  const label facej =
91  pp.edgeFaces()[edgei][pp.edgeFaces()[edgei][0] == facei];
92  const label facePointj = pp[facej].which(pp[facei][facePointi]);
93 
94  // Get the corresponding next point within the connected face
95  const label facePointj1 =
96  direction
97  ? pp[facej].rcIndex(facePointj)
98  : pp[facej].fcIndex(facePointj);
99 
100  // If the next points are not the same then that indicates that the
101  // faces are numbered in opposite directions. This means that the faces
102  // are not actually connected. There should really be two edges, each
103  // connected to just one of the faces. This edge should therefore be
104  // considered a boundary to the walk.
105  if (pp[facei][facePointi1] != pp[facej][facePointj1])
106  {
107  facePointi = facePointi1;
108  continue;
109  }
110 
111  // It has been determined that the current edge *can* be crossed. Now
112  // test whether of not the walk *should* cross this edge...
113  if (faceMap[facej] == -1)
114  {
115  // The connected face has not been visited, so walk into it and
116  // set its ordering in the map, its point and visited status
117  facei = facej;
118  facePointi = facePointj;
119  faceMap[facei] = mapFacei;
120  facePointMap[facei] = facePointi;
121  changed = changed || facei != mapFacei || facePointi != 0;
122  ++ mapFacei;
123  }
124  else if (facePointMap[facei] != facePointi1 || facei == seedFacei)
125  {
126  // The connected face has been visited, but there are more
127  // edges to consider on the current face, so move to the next
128  // face point
129  facePointi = facePointi1;
130  }
131  else
132  {
133  // The connected face has been visited, and there are no more
134  // edges to consider on the current face, so backtrack to the
135  // previous face in the walk
136  facei = facej;
137  facePointi = facePointj;
138  }
139 
140  // Add to the walk, if that information is being stored
141  if (walks.valid() && walks->last().last() != facei)
142  {
143  walks->last().append(facei);
144  }
145  }
146  while (facei != seedFacei || facePointi != seedFacePointi);
147 
148  return changed;
149 }
150 
151 
152 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
153 
155 (
156  const fileName& name,
157  const primitivePatch& pp
158 )
159 {
160  OFstream os(name);
161 
162  forAll(pp.localPoints(), pointi)
163  {
164  const point& p = pp.localPoints()[pointi];
165  os << "v " << p.x() << ' ' << p.y() << ' ' << p.z() << endl;
166  }
167 
168  forAll(pp.localFaces(), facei)
169  {
170  const face& f = pp.localFaces()[facei];
171  os << 'f';
172  forAll(f, fi)
173  {
174  os << ' ' << f[fi] + 1;
175  }
176  os << endl;
177  }
178 }
179 
181 (
182  const fileName& name,
183  const pointField& points0,
184  const pointField& points1
185 )
186 {
187  OFstream os(name);
188 
189  forAll(points0, pointi)
190  {
191  const point& p0 = points0[pointi];
192  const point& p1 = points1[pointi];
193  os << "v " << p0.x() << ' ' << p0.y() << ' ' << p0.z() << endl
194  << "v " << p1.x() << ' ' << p1.y() << ' ' << p1.z() << endl
195  << "l " << 2*pointi << ' ' << 2*pointi + 1 << endl;
196  }
197 }
198 
199 
201 (
202  const fileName& name,
203  const pointField& points,
204  const labelListList& paths
205 )
206 {
207  OFstream os(name);
208 
209  forAll(points, pointi)
210  {
211  const point& c = points[pointi];
212  os << "v " << c.x() << ' '<< c.y() << ' ' << c.z() << endl;
213  }
214 
215  forAll(paths, pathi)
216  {
217  for (label pathj = 0; pathj < paths[pathi].size() - 1; ++ pathj)
218  {
219  os << "l " << paths[pathi][pathj] + 1 << ' '
220  << paths[pathi][pathj + 1] + 1 << endl;
221  }
222  }
223 }
224 
225 
227 (
228  ownToNbrOrderData& ownToNbr,
229  autoPtr<ownToNbrDebugOrderData>& ownToNbrDebugPtr,
230  const primitivePatch& pp
231 ) const
232 {
233  if (owner())
234  {
235  // Generate the connected regions
236  label nRegions = 0;
237  labelList faceRegionis(pp.size(), -1);
238 
239  label seedFacei = 0;
240 
241  labelList faceMap(pp.size(), -1);
242  labelList facePointMap(pp.size(), -1);
243  label mapFacei = 0;
244  autoPtr<labelListList> walks(nullptr);
245 
246  while (mapFacei < pp.size())
247  {
248  walk
249  (
250  pp,
251  owner(),
252  seedFacei,
253  0,
254  faceMap,
255  facePointMap,
256  mapFacei,
257  walks
258  );
259 
260  forAll(pp, facei)
261  {
262  if (faceRegionis[facei] == -1 && faceMap[facei] != -1)
263  {
264  faceRegionis[facei] = nRegions;
265  }
266  }
267 
268  ++ nRegions;
269 
270  forAll(pp, facei)
271  {
272  if (faceMap[facei] == -1)
273  {
274  seedFacei = facei;
275  break;
276  }
277  }
278  }
279 
280  // Generate the face tolerances
281  //
282  // !!! It is possible that a different metric would be more appropriate
283  // for this method than the tolerance that was developed when all faces
284  // were being geometrically compared
285  //
286  const scalarField tols(calcFaceTol(pp, pp.points(), pp.faceCentres()));
287 
288  // Get the face with the largest tolerance in each region as the seed
289  // and store its index in the (self) ordering data
290  ownToOwnOrderDataPtr_ = new ownToOwnOrderData();
291  ownToOwnOrderDataPtr_->seedFaceis = labelList(nRegions, -1);
292  scalarList maxTols(nRegions, -vGreat);
293  forAll(pp, facei)
294  {
295  const label regioni = faceRegionis[facei];
296 
297  if (tols[facei] > maxTols[regioni])
298  {
299  ownToOwnOrderDataPtr_->seedFaceis[regioni] = facei;
300  maxTols[regioni] = tols[facei];
301  }
302  }
303 
304  // Get the points of each seed face and store them in the neighbour
305  // ordering data
306  ownToNbr.seedFacePoints = List<pointField>(nRegions, pointField());
307  forAll(ownToOwnOrderDataPtr_->seedFaceis, regioni)
308  {
309  const face& f = pp[ownToOwnOrderDataPtr_->seedFaceis[regioni]];
310  ownToNbr.seedFacePoints[regioni] = f.points(pp.points());
311  }
312 
313  // Get debug data
314  if (ownToNbrDebugPtr.valid())
315  {
316  ownToNbrDebugPtr = new ownToNbrDebugOrderData();
317  ownToNbrDebugPtr->nFaces = pp.size();
318  ownToNbrDebugPtr->nPoints = pp.nPoints();
319  ownToNbrDebugPtr->nEdges = pp.nEdges();
320  ownToNbrDebugPtr->nInternalEdges = pp.nInternalEdges();
321  }
322  }
323 }
324 
325 
327 (
328  const ownToNbrOrderData& ownToNbr,
329  const autoPtr<ownToNbrDebugOrderData>& ownToNbrDebugPtr,
330  const primitivePatch& pp,
332  labelList& rotation
333 ) const
334 {
335  // Determine the seed faces and face points
336  labelList seedFaceis, seedFacePointis;
337  if (owner())
338  {
339  seedFaceis = ownToOwnOrderDataPtr_->seedFaceis;
340  ownToOwnOrderDataPtr_.clear();
341 
342  seedFacePointis.resize(seedFaceis.size(), 0);
343  }
344  else
345  {
346  const List<pointField> ownerSeedFacePoints(ownToNbr.seedFacePoints);
347 
348  seedFaceis.resize(ownerSeedFacePoints.size());
349  seedFacePointis.resize(ownerSeedFacePoints.size());
350 
351  // Check the element counts
352  if (ownToNbrDebugPtr.valid())
353  {
354  const label ownerNFaces = ownToNbrDebugPtr->nFaces;
355  const label ownerNPoints = ownToNbrDebugPtr->nPoints;
356  const label ownerNEdges = ownToNbrDebugPtr->nEdges;
357  const label ownerNInternalEdges = ownToNbrDebugPtr->nInternalEdges;
358  if (pp.size() != ownerNFaces)
359  {
360  SeriousErrorInFunction<< "The patch " << name() << " has "
361  << pp.size() << " faces whilst it's neighbour has "
362  << ownerNFaces << endl;
363  }
364  if (pp.nPoints() != ownerNPoints)
365  {
366  SeriousErrorInFunction<< "The patch " << name() << " has "
367  << pp.nPoints() << " points whilst it's neighbour has "
368  << ownerNPoints << endl;
369  }
370  if (pp.nEdges() != ownerNEdges)
371  {
372  SeriousErrorInFunction<< "The patch " << name() << " has "
373  << pp.nEdges() << " edges whilst it's neighbour has "
374  << ownerNEdges << endl;
375  }
376  if (pp.nInternalEdges() != ownerNInternalEdges)
377  {
378  SeriousErrorInFunction<< "The patch " << name() << " has "
379  << pp.nInternalEdges() << " internal edges whilst it's "
380  << "neighbour has " << ownerNInternalEdges << endl;
381  }
382  }
383 
384  // Do geometric testing to determine the faces that match those sent
385  // over from the opposite patch
386  forAll(ownerSeedFacePoints, regioni)
387  {
388  const pointField& ownerFacePts = ownerSeedFacePoints[regioni];
389 
390  // The seed face and face-point are the ones which give the smallest
391  // total displacement between all corresponding points. Note that
392  // owner and neighbour point order is reversed.
393  scalar minSumSqrDisplacement = vGreat;
394  forAll(pp, facei)
395  {
396  const pointField facePts = pp[facei].points(pp.points());
397 
398  if (facePts.size() != ownerFacePts.size()) continue;
399 
400  forAll(facePts, facePointi)
401  {
402  const scalar sumSqrDisplacement =
403  sum
404  (
405  magSqr
406  (
407  rotateList(reverseList(facePts), facePointi + 1)
408  - ownerFacePts
409  )
410  );
411  if (sumSqrDisplacement < minSumSqrDisplacement)
412  {
413  seedFaceis[regioni] = facei;
414  seedFacePointis[regioni] = facePointi;
415  minSumSqrDisplacement = sumSqrDisplacement;
416  }
417  }
418  }
419 
420  // Check and report if the min displacement is large
421  const scalar seedFaceTol =
422  calcFaceTol
423  (
424  faceList(1, pp[seedFaceis[regioni]]),
425  pp.points(),
426  pointField(1, pp.faceCentres()[seedFaceis[regioni]])
427  ).first();
428  if (minSumSqrDisplacement > seedFaceTol)
429  {
431  << "The root-sum-square displacement between the points of "
432  << "the seed face and the best matching face (#"
433  << seedFaceis[regioni] << ") on patch " << name()
434  << " is " << sqrt(minSumSqrDisplacement) << "."
435  << nl
436  << "This is greater than the match tolerance of "
437  << seedFaceTol << " for this face."
438  << nl
439  << "Check that the patches are conformal and that any "
440  << "transformations defined between them are correct"
441  << nl
442  << "It might be possible to fix this problem by increasing "
443  << "the \"matchTolerance\" setting for this patch in the "
444  << "boundary file."
445  << nl
446  << "Re-run with the \"coupled\" debug flag set for more "
447  << "information."
448  << exit(FatalError);
449  }
450  }
451  }
452 
453  // Walk the patch from the seeds
454  bool changed = false;
455  faceMap = -1;
456  labelList facePointMap(pp.size(), -1);
457  label mapFacei = 0;
458  autoPtr<labelListList> walks(debug ? new labelListList() : nullptr);
459  forAll(seedFaceis, regioni)
460  {
461  changed =
462  walk
463  (
464  pp,
465  owner(),
466  seedFaceis[regioni],
467  seedFacePointis[regioni],
468  faceMap,
469  facePointMap,
470  mapFacei,
471  walks
472  )
473  || changed;
474  }
475 
476  // Write out the patch
477  if (debug)
478  {
479  Pout<< "Writing patch " << name() << " to " << name() + ".obj" << endl;
480  writeOBJ(name() + ".obj", pp);
481  }
482 
483  // Write out the walk
484  if (debug)
485  {
486  Pout<< "Writing patch " << name() << " walks to "
487  << name() + "Walk.obj" << endl;
488  writeOBJ(name() + "Walk.obj", pp.faceCentres(), walks());
489  }
490 
491  // Check that all faces have been visited exactly once
492  bool badWalk = mapFacei != pp.size();
493  forAll(pp, facei)
494  {
495  badWalk = badWalk || facePointMap[facei] == -1;
496  }
497  if (badWalk)
498  {
500  << "The ordering walk did not hit every face exactly once"
501  << exit(FatalError);
502  }
503 
504  // Construct the rotations from the face point map
505  forAll(pp, facei)
506  {
507  rotation[facei] =
508  (pp[facei].size() - facePointMap[facei]) % pp[facei].size();
509  }
510 
511  // Map the rotations
512  //
513  // !!! The rotation list appears to be indexed by the new face label,
514  // rather than the old one. For sanity's sake the ordering code above
515  // indexes everything consistently with the old face label. This means the
516  // rotations need mapping to the new indices.
517  //
518  UIndirectList<label>(rotation, faceMap) = labelList(rotation);
519 
520  return changed;
521 }
522 
523 
524 // * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * * * * //
525 
527 (
528  const word& name,
529  const label size,
530  const label start,
531  const label index,
532  const polyBoundaryMesh& bm,
533  const word& patchType
534 )
535 :
536  polyPatch(name, size, start, index, bm, patchType),
537  matchTolerance_(defaultMatchTol_),
538  ownToOwnOrderDataPtr_(nullptr)
539 {}
540 
541 
543 (
544  const word& name,
545  const dictionary& dict,
546  const label index,
547  const polyBoundaryMesh& bm,
548  const word& patchType
549 )
550 :
551  polyPatch(name, dict, index, bm, patchType),
552  matchTolerance_(dict.lookupOrDefault("matchTolerance", defaultMatchTol_)),
553  ownToOwnOrderDataPtr_(nullptr)
554 {}
555 
556 
558 (
559  const coupledPolyPatch& pp,
560  const polyBoundaryMesh& bm
561 )
562 :
563  polyPatch(pp, bm),
564  matchTolerance_(pp.matchTolerance_),
565  ownToOwnOrderDataPtr_(nullptr)
566 {}
567 
568 
570 (
571  const coupledPolyPatch& pp,
572  const polyBoundaryMesh& bm,
573  const label index,
574  const label newSize,
575  const label newStart
576 )
577 :
578  polyPatch(pp, bm, index, newSize, newStart),
579  matchTolerance_(pp.matchTolerance_),
580  ownToOwnOrderDataPtr_(nullptr)
581 {}
582 
583 
584 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
585 
587 {}
588 
589 
590 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
591 
593 (
594  const UList<face>& faces,
595  const pointField& points,
596  const pointField& faceCentres
597 )
598 {
599  // Calculate typical distance per face
600  scalarField tols(faces.size());
601 
602  forAll(faces, facei)
603  {
604  const point& cc = faceCentres[facei];
605 
606  const face& f = faces[facei];
607 
608  // 1. calculate a typical size of the face. Use maximum distance
609  // to face centre
610  scalar maxLenSqr = -great;
611  // 2. as measure of truncation error when comparing two coordinates
612  // use small * maximum component
613  scalar maxCmpt = -great;
614 
615  forAll(f, fp)
616  {
617  const point& pt = points[f[fp]];
618  maxLenSqr = max(maxLenSqr, magSqr(pt - cc));
619  maxCmpt = max(maxCmpt, cmptMax(cmptMag(pt)));
620  }
621 
622  tols[facei] = max
623  (
624  small,
625  max(small*maxCmpt, Foam::sqrt(maxLenSqr))
626  );
627  }
628  return tols;
629 }
630 
631 
633 {
634  polyPatch::write(os);
635  writeEntry(os, "matchTolerance", matchTolerance_);
636 }
637 
638 
639 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
640 
641 Foam::Istream& Foam::operator>>
642 (
643  Istream& is,
645 )
646 {
647  is >> ownToNbr.seedFacePoints;
648  return is;
649 }
650 
651 
652 Foam::Ostream& Foam::operator<<
653 (
654  Ostream& os,
656 )
657 {
658  os << ownToNbr.seedFacePoints;
659  return os;
660 }
661 
662 
663 Foam::Istream& Foam::operator>>
664 (
665  Istream& is,
667 )
668 {
669  is >> ownToNbrDebug.nFaces
670  >> ownToNbrDebug.nPoints
671  >> ownToNbrDebug.nEdges
672  >> ownToNbrDebug.nInternalEdges;
673  return is;
674 }
675 
676 
677 Foam::Ostream& Foam::operator<<
678 (
679  Ostream& os,
680  const coupledPolyPatch::ownToNbrDebugOrderData& ownToNbrDebug
681 )
682 {
683  os << ownToNbrDebug.nFaces
684  << ownToNbrDebug.nPoints
685  << ownToNbrDebug.nEdges
686  << ownToNbrDebug.nInternalEdges;
687  return os;
688 }
689 
690 
691 // ************************************************************************* //
Various functions to operate on Lists.
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:60
void resize(const label)
Alias for setSize(const label)
Definition: ListI.H:138
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:125
Output to file stream.
Definition: OFstream.H:86
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
A list of faces which address into the list of points.
label nEdges() const
Return number of edges in patch.
label nPoints() const
Return number of points supporting patch faces.
label nInternalEdges() const
Number of internal edges.
const Field< PointType > & points() const
Return reference to global points.
const List< FaceType > & localFaces() const
Return patch faces addressing into local point list.
const Field< PointType > & localPoints() const
Return pointField of points in patch.
const Field< PointType > & faceCentres() const
Return face centres for patch.
A List with indirect addressing.
Definition: UIndirectList.H:60
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: UList.H:74
T & first()
Return the first element of the list.
Definition: UListI.H:114
label size() const
Return the number of elements in the UList.
Definition: UListI.H:311
const Cmpt & z() const
Definition: VectorI.H:87
const Cmpt & y() const
Definition: VectorI.H:81
const Cmpt & x() const
Definition: VectorI.H:75
bool valid() const
Return true if the autoPtr valid (ie, the pointer is set)
Definition: autoPtrI.H:83
The coupledPolyPatch is an abstract base class for patches that couple regions of the computational d...
virtual void write(Ostream &) const
Write the polyPatch data as a dictionary.
static const scalar defaultMatchTol_
Default matching tolerance.
coupledPolyPatch(const word &name, const label size, const label start, const label index, const polyBoundaryMesh &bm, const word &patchType)
Construct from components.
virtual bool order(const ownToNbrOrderData &ownToNbr, const autoPtr< ownToNbrDebugOrderData > &ownToNbrDebugPtr, const primitivePatch &, labelList &faceMap, labelList &rotation) const
Return new ordering for the given primitivePatch.
static void writeOBJ(const fileName &, const primitivePatch &)
Write a patch in OBJ format.
static scalarField calcFaceTol(const UList< face > &faces, const pointField &points, const pointField &faceCentres)
Calculate typical tolerance per face. Is currently max distance.
virtual void initOrder(ownToNbrOrderData &ownToNbr, autoPtr< ownToNbrDebugOrderData > &ownToNbrDebugPtr, const primitivePatch &) const
Initialise ordering for the given primitivePatch. Fills the.
virtual ~coupledPolyPatch()
Destructor.
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:160
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:76
A class for handling file names.
Definition: fileName.H:82
Foam::polyBoundaryMesh.
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:70
virtual void write(Ostream &) const
Write the polyPatch data as a dictionary.
Definition: polyPatch.C:355
A class for handling words, derived from string.
Definition: word.H:62
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
const pointField & points
#define SeriousErrorInFunction
Report an error message using Foam::SeriousError.
const dimensionedScalar c
Speed of light in a vacuum.
void writeOBJ(Ostream &os, const point &pt)
Write obj representation of point.
Definition: meshTools.C:203
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
const doubleScalar e
Definition: doubleScalar.H:105
List< label > labelList
A List of labels.
Definition: labelList.H:56
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
word name(const bool)
Return a word representation of a bool.
Definition: boolIO.C:39
ListType reverseList(const ListType &list)
Reverse a list. First element becomes last element etc.
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
ListType rotateList(const ListType &list, const label n)
Rotate a list by n places. If n is positive rotate clockwise/right/down.
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
Addressing for a faceList slice.
void writeEntry(Ostream &os, const HashTable< T, Key, Hash > &ht)
Definition: HashTableIO.C:96
dimensionedScalar sqrt(const dimensionedScalar &ds)
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:57
defineTypeNameAndDebug(combustionModel, 0)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
dimensionSet cmptMag(const dimensionSet &)
Definition: dimensionSet.C:275
void cmptMax(FieldField< Field, typename FieldField< Field, Type >::cmptType > &cf, const FieldField< Field, Type > &f)
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
error FatalError
List< face > faceList
Definition: faceListFwd.H:43
static const char nl
Definition: Ostream.H:260
dimensioned< scalar > magSqr(const dimensioned< Type > &)
uint8_t direction
Definition: direction.H:45
labelList f(nPoints)
dictionary dict
volScalarField & p
Data to pass from owner.initOrder to nbr.order if debugging.
Data to pass from owner.initOrder to nbr.order.
Data to pass from owner.initOrder to owner.order.
3D tensor transformation operations.