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-2023 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 its neighbour has "
362  << ownerNFaces << endl;
363  }
364  if (pp.nPoints() != ownerNPoints)
365  {
366  SeriousErrorInFunction<< "The patch " << name() << " has "
367  << pp.nPoints() << " points whilst its neighbour has "
368  << ownerNPoints << endl;
369  }
370  if (pp.nEdges() != ownerNEdges)
371  {
372  SeriousErrorInFunction<< "The patch " << name() << " has "
373  << pp.nEdges() << " edges whilst its neighbour has "
374  << ownerNEdges << endl;
375  }
376  if (pp.nInternalEdges() != ownerNInternalEdges)
377  {
378  SeriousErrorInFunction<< "The patch " << name() << " has "
379  << pp.nInternalEdges() << " internal edges whilst its "
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
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:162
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:334
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:106
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:257
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:296
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:41
static const char nl
Definition: Ostream.H:266
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.