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 {
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 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,
331  labelList& faceMap,
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 
585 (
586  const coupledPolyPatch& pp,
587  const polyBoundaryMesh& bm,
588  const label index,
589  const labelUList& mapAddressing,
590  const label newStart
591 )
592 :
593  polyPatch(pp, bm, index, mapAddressing, newStart),
594  matchTolerance_(pp.matchTolerance_),
595  ownToOwnOrderDataPtr_(nullptr)
596 {}
597 
598 
599 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
600 
602 {}
603 
604 
605 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
606 
608 (
609  const UList<face>& faces,
610  const pointField& points,
611  const pointField& faceCentres
612 )
613 {
614  // Calculate typical distance per face
615  scalarField tols(faces.size());
616 
617  forAll(faces, facei)
618  {
619  const point& cc = faceCentres[facei];
620 
621  const face& f = faces[facei];
622 
623  // 1. calculate a typical size of the face. Use maximum distance
624  // to face centre
625  scalar maxLenSqr = -great;
626  // 2. as measure of truncation error when comparing two coordinates
627  // use small * maximum component
628  scalar maxCmpt = -great;
629 
630  forAll(f, fp)
631  {
632  const point& pt = points[f[fp]];
633  maxLenSqr = max(maxLenSqr, magSqr(pt - cc));
634  maxCmpt = max(maxCmpt, cmptMax(cmptMag(pt)));
635  }
636 
637  tols[facei] = max
638  (
639  small,
640  max(small*maxCmpt, Foam::sqrt(maxLenSqr))
641  );
642  }
643  return tols;
644 }
645 
646 
648 {
649  polyPatch::write(os);
650  writeEntry(os, "matchTolerance", matchTolerance_);
651 }
652 
653 
654 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
655 
656 Foam::Istream& Foam::operator>>
657 (
658  Istream& is,
660 )
661 {
662  is >> ownToNbr.seedFacePoints;
663  return is;
664 }
665 
666 
667 Foam::Ostream& Foam::operator<<
668 (
669  Ostream& os,
671 )
672 {
673  os << ownToNbr.seedFacePoints;
674  return os;
675 }
676 
677 
678 Foam::Istream& Foam::operator>>
679 (
680  Istream& is,
682 )
683 {
684  is >> ownToNbrDebug.nFaces
685  >> ownToNbrDebug.nPoints
686  >> ownToNbrDebug.nEdges
687  >> ownToNbrDebug.nInternalEdges;
688  return is;
689 }
690 
691 
692 Foam::Ostream& Foam::operator<<
693 (
694  Ostream& os,
695  const coupledPolyPatch::ownToNbrDebugOrderData& ownToNbrDebug
696 )
697 {
698  os << ownToNbrDebug.nFaces
699  << ownToNbrDebug.nPoints
700  << ownToNbrDebug.nEdges
701  << ownToNbrDebug.nInternalEdges;
702  return os;
703 }
704 
705 
706 // ************************************************************************* //
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
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
FvWallInfoData< WallInfo, label > label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
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:156
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
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.
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
const dimensionedScalar c
Speed of light in a vacuum.
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:382
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.
dimensionSet cmptMag(const dimensionSet &)
Definition: dimensionSet.C:275
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:64
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.
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:311
static void writeOBJ(const fileName &, const primitivePatch &)
Write a patch in OBJ format.
Namespace for OpenFOAM.