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