cyclicPolyPatch.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2015-2020 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "cyclicPolyPatch.H"
31 #include "polyBoundaryMesh.H"
32 #include "polyMesh.H"
33 #include "demandDrivenData.H"
34 #include "OFstream.H"
35 #include "matchPoints.H"
36 #include "edgeHashes.H"
37 #include "Time.H"
38 #include "transformField.H"
39 #include "SubField.H"
40 #include "unitConversion.H"
41 
42 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
43 
44 namespace Foam
45 {
46  defineTypeNameAndDebug(cyclicPolyPatch, 0);
47 
48  addToRunTimeSelectionTable(polyPatch, cyclicPolyPatch, word);
49  addToRunTimeSelectionTable(polyPatch, cyclicPolyPatch, dictionary);
50 }
51 
52 
53 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
54 
55 Foam::label Foam::cyclicPolyPatch::findMaxArea
56 (
57  const pointField& points,
58  const faceList& faces
59 )
60 {
61  label maxI = -1;
62  scalar maxAreaSqr = -GREAT;
63 
64  forAll(faces, facei)
65  {
66  scalar areaSqr = magSqr(faces[facei].areaNormal(points));
67 
68  if (maxAreaSqr < areaSqr)
69  {
70  maxAreaSqr = areaSqr;
71  maxI = facei;
72  }
73  }
74  return maxI;
75 }
76 
77 
79 {
80  if (size())
81  {
82  // Half0
83  const cyclicPolyPatch& half0 = *this;
84  vectorField half0Areas(half0.size());
85  forAll(half0, facei)
86  {
87  half0Areas[facei] = half0[facei].areaNormal(half0.points());
88  }
89 
90  // Half1
91  const cyclicPolyPatch& half1 = neighbPatch();
92  vectorField half1Areas(half1.size());
93  forAll(half1, facei)
94  {
95  half1Areas[facei] = half1[facei].areaNormal(half1.points());
96  }
97 
98  calcTransforms
99  (
100  half0,
101  half0.faceCentres(),
102  half0Areas,
103  half1.faceCentres(),
104  half1Areas
105  );
106  }
107 }
108 
109 
111 (
112  const primitivePatch& half0,
113  const pointField& half0Ctrs,
114  const vectorField& half0Areas,
115  const pointField& half1Ctrs,
116  const vectorField& half1Areas
117 )
118 {
119  if (debug && owner())
120  {
121  fileName casePath(boundaryMesh().mesh().time().path());
122  {
123  fileName nm0(casePath/name()+"_faces.obj");
124  Pout<< "cyclicPolyPatch::calcTransforms : Writing " << name()
125  << " faces to OBJ file " << nm0 << endl;
126  writeOBJ(nm0, half0, half0.points());
127  }
128  const cyclicPolyPatch& half1 = neighbPatch();
129  {
130  fileName nm1(casePath/half1.name()+"_faces.obj");
131  Pout<< "cyclicPolyPatch::calcTransforms : Writing " << half1.name()
132  << " faces to OBJ file " << nm1 << endl;
133  writeOBJ(nm1, half1, half1.points());
134  }
135  {
136  OFstream str(casePath/name()+"_to_" + half1.name() + ".obj");
137  label vertI = 0;
138  Pout<< "cyclicPolyPatch::calcTransforms :"
139  << " Writing coupled face centres as lines to " << str.name()
140  << endl;
141  forAll(half0Ctrs, i)
142  {
143  const point& p0 = half0Ctrs[i];
144  str << "v " << p0.x() << ' ' << p0.y() << ' ' << p0.z() << nl;
145  vertI++;
146  const point& p1 = half1Ctrs[i];
147  str << "v " << p1.x() << ' ' << p1.y() << ' ' << p1.z() << nl;
148  vertI++;
149  str << "l " << vertI-1 << ' ' << vertI << nl;
150  }
151  }
152  }
153 
154 
155  // Some sanity checks
156 
157  if (half0Ctrs.size() != half1Ctrs.size())
158  {
160  << "For patch " << name()
161  << " there are " << half0Ctrs.size()
162  << " face centres, for the neighbour patch " << neighbPatch().name()
163  << " there are " << half1Ctrs.size()
164  << exit(FatalError);
165  }
166 
167  if (transform() != neighbPatch().transform())
168  {
170  << "Patch " << name()
171  << " has transform type " << transformTypeNames[transform()]
172  << ", neighbour patch " << neighbPatchName()
173  << " has transform type "
174  << neighbPatch().transformTypeNames[neighbPatch().transform()]
175  << exit(FatalError);
176  }
177 
178 
179  // Calculate transformation tensors
180 
181  if (half0Ctrs.size() > 0)
182  {
183  vectorField half0Normals(half0Areas.size());
184  vectorField half1Normals(half1Areas.size());
185 
186  scalar maxAreaDiff = -GREAT;
187  label maxAreaFacei = -1;
188 
189  forAll(half0, facei)
190  {
191  scalar magSf = mag(half0Areas[facei]);
192  scalar nbrMagSf = mag(half1Areas[facei]);
193  scalar avSf = (magSf + nbrMagSf)/2.0;
194 
195  if (magSf < ROOTVSMALL && nbrMagSf < ROOTVSMALL)
196  {
197  // Undetermined normal. Use dummy normal to force separation
198  // check. (note use of sqrt(VSMALL) since that is how mag
199  // scales)
200  half0Normals[facei] = point(1, 0, 0);
201  half1Normals[facei] = half0Normals[facei];
202  }
203  else
204  {
205  scalar areaDiff = mag(magSf - nbrMagSf)/avSf;
206 
207  if (areaDiff > maxAreaDiff)
208  {
209  maxAreaDiff = areaDiff;
210  maxAreaFacei = facei;
211  }
212 
213  if (areaDiff > matchTolerance())
214  {
216  << "face " << facei
217  << " area does not match neighbour by "
218  << 100*areaDiff
219  << "% -- possible face ordering problem." << endl
220  << "patch:" << name()
221  << " my area:" << magSf
222  << " neighbour area:" << nbrMagSf
223  << " matching tolerance:" << matchTolerance()
224  << endl
225  << "Mesh face:" << start()+facei
226  << " fc:" << half0Ctrs[facei]
227  << endl
228  << "Neighbour fc:" << half1Ctrs[facei]
229  << endl
230  << "If you are certain your matching is correct"
231  << " you can increase the 'matchTolerance' setting"
232  << " in the patch dictionary in the boundary file."
233  << endl
234  << "Rerun with cyclic debug flag set"
235  << " for more information." << exit(FatalError);
236  }
237  else
238  {
239  half0Normals[facei] = half0Areas[facei] / magSf;
240  half1Normals[facei] = half1Areas[facei] / nbrMagSf;
241  }
242  }
243  }
244 
245 
246  // Print area match
247  if (debug)
248  {
249  Pout<< "cyclicPolyPatch::calcTransforms :"
250  << " patch:" << name()
251  << " Max area error:" << 100*maxAreaDiff << "% at face:"
252  << maxAreaFacei << " at:" << half0Ctrs[maxAreaFacei]
253  << " coupled face at:" << half1Ctrs[maxAreaFacei]
254  << endl;
255  }
256 
257 
258  // Calculate transformation tensors
259 
260  if (transform() == ROTATIONAL)
261  {
262  // Calculate using the given rotation axis and centre. Do not
263  // use calculated normals.
264  vector n0 = findFaceMaxRadius(half0Ctrs);
265  vector n1 = -findFaceMaxRadius(half1Ctrs);
266  n0.normalise();
267  n1.normalise();
268 
269  if (debug)
270  {
271  Pout<< "cyclicPolyPatch::calcTransforms :"
272  << " patch:" << name()
273  << " Specified rotation :"
274  << " n0:" << n0 << " n1:" << n1
275  << " swept angle: " << radToDeg(acos(n0 & n1))
276  << " [deg]" << endl;
277  }
278 
279  // Extended tensor from two local coordinate systems calculated
280  // using normal and rotation axis
281  const tensor E0
282  (
283  rotationAxis_,
284  (n0 ^ rotationAxis_),
285  n0
286  );
287  const tensor E1
288  (
289  rotationAxis_,
290  (-n1 ^ rotationAxis_),
291  -n1
292  );
293  const tensor revT(E1.T() & E0);
294 
295  const_cast<tensorField&>(forwardT()) = tensorField(1, revT.T());
296  const_cast<tensorField&>(reverseT()) = tensorField(1, revT);
297  const_cast<vectorField&>(separation()).setSize(0);
298  const_cast<boolList&>(collocated()) = boolList(1, false);
299  }
300  else
301  {
302  scalarField half0Tols
303  (
304  matchTolerance()
305  *calcFaceTol
306  (
307  half0,
308  half0.points(),
309  static_cast<const pointField&>(half0Ctrs)
310  )
311  );
312 
313  calcTransformTensors
314  (
315  static_cast<const pointField&>(half0Ctrs),
316  static_cast<const pointField&>(half1Ctrs),
317  half0Normals,
318  half1Normals,
319  half0Tols,
320  matchTolerance(),
321  transform()
322  );
323 
324 
325  if (transform() == TRANSLATIONAL)
326  {
327  if (debug)
328  {
329  Pout<< "cyclicPolyPatch::calcTransforms :"
330  << " patch:" << name()
331  << " Specified separation vector : "
332  << separationVector_ << endl;
333  }
334 
335  // Check that separation vectors are same.
336  const scalar avgTol = average(half0Tols);
337  if
338  (
339  mag(separationVector_ + neighbPatch().separationVector_)
340  > avgTol
341  )
342  {
344  << "Specified separation vector " << separationVector_
345  << " differs by that of neighbouring patch "
346  << neighbPatch().separationVector_
347  << " by more than tolerance " << avgTol << endl
348  << "patch:" << name()
349  << " neighbour:" << neighbPatchName()
350  << endl;
351  }
352 
353 
354  // Override computed transform with specified.
355  if
356  (
357  separation().size() != 1
358  || mag(separation()[0] - separationVector_) > avgTol
359  )
360  {
362  << "Specified separationVector " << separationVector_
363  << " differs from computed separation vector "
364  << separation() << endl
365  << "This probably means your geometry is not consistent"
366  << " with the specified separation and might lead"
367  << " to problems." << endl
368  << "Continuing with specified separation vector "
369  << separationVector_ << endl
370  << "patch:" << name()
371  << " neighbour:" << neighbPatchName()
372  << endl;
373  }
374 
375  // Set tensors
376  const_cast<tensorField&>(forwardT()).clear();
377  const_cast<tensorField&>(reverseT()).clear();
378  const_cast<vectorField&>(separation()) = vectorField
379  (
380  1,
381  separationVector_
382  );
383  const_cast<boolList&>(collocated()) = boolList(1, false);
384  }
385  }
386  }
387 }
388 
389 
390 void Foam::cyclicPolyPatch::getCentresAndAnchors
391 (
392  const primitivePatch& pp0,
393  const primitivePatch& pp1,
394 
395  pointField& half0Ctrs,
396  pointField& half1Ctrs,
397  pointField& anchors0,
398  scalarField& tols
399 ) const
400 {
401  // Get geometric data on both halves.
402  half0Ctrs = pp0.faceCentres();
403  anchors0 = getAnchorPoints(pp0, pp0.points(), transform());
404  half1Ctrs = pp1.faceCentres();
405 
406  if (debug)
407  {
408  Pout<< "cyclicPolyPatch::getCentresAndAnchors :"
409  << " patch:" << name() << nl
410  << "half0 untransformed faceCentres (avg) : "
411  << gAverage(half0Ctrs) << nl
412  << "half1 untransformed faceCentres (avg) : "
413  << gAverage(half1Ctrs) << endl;
414  }
415 
416  if (half0Ctrs.size())
417  {
418  switch (transform())
419  {
420  case ROTATIONAL:
421  {
422  vector n0 = findFaceMaxRadius(half0Ctrs);
423  vector n1 = -findFaceMaxRadius(half1Ctrs);
424  n0.normalise();
425  n1.normalise();
426 
427  if (debug)
428  {
429  Pout<< "cyclicPolyPatch::getCentresAndAnchors :"
430  << " patch:" << name()
431  << " Specified rotation :"
432  << " n0:" << n0 << " n1:" << n1
433  << " swept angle: "
434  << radToDeg(acos(n0 & n1)) << " [deg]"
435  << endl;
436  }
437 
438  // Extended tensor from two local coordinate systems calculated
439  // using normal and rotation axis
440  const tensor E0
441  (
442  rotationAxis_,
443  (n0 ^ rotationAxis_),
444  n0
445  );
446  const tensor E1
447  (
448  rotationAxis_,
449  (-n1 ^ rotationAxis_),
450  -n1
451  );
452  const tensor revT(E1.T() & E0);
453 
454  // Rotation
455  forAll(half0Ctrs, facei)
456  {
457  half0Ctrs[facei] =
459  (
460  revT,
461  half0Ctrs[facei] - rotationCentre_
462  )
463  + rotationCentre_;
464  anchors0[facei] =
466  (
467  revT,
468  anchors0[facei] - rotationCentre_
469  )
470  + rotationCentre_;
471  }
472 
473  break;
474  }
475  case TRANSLATIONAL:
476  {
477  // Transform 0 points.
478 
479  if (debug)
480  {
481  Pout<< "cyclicPolyPatch::getCentresAndAnchors :"
482  << " patch:" << name()
483  << "Specified translation : " << separationVector_
484  << endl;
485  }
486 
487  // Note: getCentresAndAnchors gets called on the slave side
488  // so separationVector is owner-slave points.
489 
490  half0Ctrs -= separationVector_;
491  anchors0 -= separationVector_;
492  break;
493  }
494  default:
495  {
496  // Assumes that cyclic is rotational. This is also the initial
497  // condition for patches without faces.
498 
499  // Determine the face with max area on both halves. These
500  // two faces are used to determine the transformation tensors
501  label max0I = findMaxArea(pp0.points(), pp0);
502  const vector n0 = pp0[max0I].unitNormal(pp0.points());
503 
504  label max1I = findMaxArea(pp1.points(), pp1);
505  const vector n1 = pp1[max1I].unitNormal(pp1.points());
506 
507  if (mag(n0 & n1) < 1-matchTolerance())
508  {
509  if (debug)
510  {
511  Pout<< "cyclicPolyPatch::getCentresAndAnchors :"
512  << " patch:" << name()
513  << " Detected rotation :"
514  << " n0:" << n0 << " n1:" << n1 << endl;
515  }
516 
517  // Rotation (around origin)
518  const tensor revT(rotationTensor(n0, -n1));
519 
520  // Rotation
521  forAll(half0Ctrs, facei)
522  {
523  half0Ctrs[facei] = Foam::transform
524  (
525  revT,
526  half0Ctrs[facei]
527  );
528  anchors0[facei] = Foam::transform
529  (
530  revT,
531  anchors0[facei]
532  );
533  }
534  }
535  else
536  {
537  // Parallel translation. Get average of all used points.
538 
539  const point ctr0(sum(pp0.localPoints())/pp0.nPoints());
540  const point ctr1(sum(pp1.localPoints())/pp1.nPoints());
541 
542  if (debug)
543  {
544  Pout<< "cyclicPolyPatch::getCentresAndAnchors :"
545  << " patch:" << name()
546  << " Detected translation :"
547  << " n0:" << n0 << " n1:" << n1
548  << " ctr0:" << ctr0 << " ctr1:" << ctr1 << endl;
549  }
550 
551  half0Ctrs += ctr1 - ctr0;
552  anchors0 += ctr1 - ctr0;
553  }
554  break;
555  }
556  }
557  }
558 
559  // Calculate typical distance per face
560  tols = matchTolerance()*calcFaceTol(pp1, pp1.points(), half1Ctrs);
561 }
562 
563 
564 Foam::vector Foam::cyclicPolyPatch::findFaceMaxRadius
565 (
566  const pointField& faceCentres
567 ) const
568 {
569  // Determine a face furthest away from the axis
570 
571  const vectorField n((faceCentres - rotationCentre_) ^ rotationAxis_);
572 
573  const scalarField magRadSqr(magSqr(n));
574 
575  label facei = findMax(magRadSqr);
576 
577  if (debug)
578  {
579  Info<< "findFaceMaxRadius(const pointField&) : patch: " << name() << nl
580  << " rotFace = " << facei << nl
581  << " point = " << faceCentres[facei] << nl
582  << " distance = " << Foam::sqrt(magRadSqr[facei])
583  << endl;
584  }
585 
586  return n[facei];
587 }
588 
589 
590 // * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * * * * //
591 
593 (
594  const word& name,
595  const label size,
596  const label start,
597  const label index,
598  const polyBoundaryMesh& bm,
599  const word& patchType,
601 )
602 :
603  coupledPolyPatch(name, size, start, index, bm, patchType, transform),
604  neighbPatchName_(word::null),
605  neighbPatchID_(-1),
606  rotationAxis_(Zero),
607  rotationCentre_(Zero),
608  separationVector_(Zero),
609  coupledPointsPtr_(nullptr),
610  coupledEdgesPtr_(nullptr)
611 {
612  // Neighbour patch might not be valid yet so no transformation
613  // calculation possible.
614 }
615 
616 
618 (
619  const word& name,
620  const label size,
621  const label start,
622  const label index,
623  const polyBoundaryMesh& bm,
624  const word& neighbPatchName,
625  const transformType transform,
626  const vector& rotationAxis,
627  const point& rotationCentre,
628  const vector& separationVector
629 )
630 :
631  coupledPolyPatch(name, size, start, index, bm, typeName, transform),
632  neighbPatchName_(neighbPatchName),
633  neighbPatchID_(-1),
634  rotationAxis_(rotationAxis),
635  rotationCentre_(rotationCentre),
636  separationVector_(separationVector),
637  coupledPointsPtr_(nullptr),
638  coupledEdgesPtr_(nullptr)
639 {
640  // Neighbour patch might not be valid yet so no transformation
641  // calculation possible.
642 }
643 
644 
646 (
647  const word& name,
648  const dictionary& dict,
649  const label index,
650  const polyBoundaryMesh& bm,
651  const word& patchType
652 )
653 :
654  coupledPolyPatch(name, dict, index, bm, patchType),
655  neighbPatchName_(dict.getOrDefault("neighbourPatch", word::null)),
656  coupleGroup_(dict),
657  neighbPatchID_(-1),
658  rotationAxis_(Zero),
659  rotationCentre_(Zero),
660  separationVector_(Zero),
661  coupledPointsPtr_(nullptr),
662  coupledEdgesPtr_(nullptr)
663 {
664  if (neighbPatchName_ == word::null && !coupleGroup_.valid())
665  {
667  << "No \"neighbourPatch\" provided." << endl
668  << "Is your mesh uptodate with split cyclics?" << endl
669  << "Run foamUpgradeCyclics to convert mesh and fields"
670  << " to split cyclics." << exit(FatalIOError);
671  }
672 
673  if (neighbPatchName_ == name)
674  {
676  << "Neighbour patch name " << neighbPatchName_
677  << " cannot be the same as this patch " << name
678  << exit(FatalIOError);
679  }
680 
681  switch (transform())
682  {
683  case ROTATIONAL:
684  {
685  dict.readEntry("rotationAxis", rotationAxis_);
686  dict.readEntry("rotationCentre", rotationCentre_);
687 
688  scalar magRot = mag(rotationAxis_);
689  if (magRot < SMALL)
690  {
692  << "Illegal rotationAxis " << rotationAxis_ << endl
693  << "Please supply a non-zero vector."
694  << exit(FatalIOError);
695  }
696  rotationAxis_ /= magRot;
697 
698  break;
699  }
700  case TRANSLATIONAL:
701  {
702  dict.readEntry("separationVector", separationVector_);
703  break;
704  }
705  default:
706  {
707  // no additional info required
708  }
709  }
710 
711  // Neighbour patch might not be valid yet so no transformation
712  // calculation possible.
713 }
714 
715 
717 (
718  const cyclicPolyPatch& pp,
719  const polyBoundaryMesh& bm
720 )
721 :
722  coupledPolyPatch(pp, bm),
723  neighbPatchName_(pp.neighbPatchName_),
724  coupleGroup_(pp.coupleGroup_),
725  neighbPatchID_(-1),
726  rotationAxis_(pp.rotationAxis_),
727  rotationCentre_(pp.rotationCentre_),
728  separationVector_(pp.separationVector_),
729  coupledPointsPtr_(nullptr),
730  coupledEdgesPtr_(nullptr)
731 {
732  // Neighbour patch might not be valid yet so no transformation
733  // calculation possible.
734 }
735 
736 
738 (
739  const cyclicPolyPatch& pp,
740  const label nrbPatchID,
741  const labelList& faceCells
742 )
743 :
745  neighbPatchName_(pp.neighbPatchName_),
746  coupleGroup_(pp.coupleGroup_),
747  neighbPatchID_(nrbPatchID),
748  rotationAxis_(pp.rotationAxis_),
749  rotationCentre_(pp.rotationCentre_),
750  separationVector_(pp.separationVector_),
751  coupledPointsPtr_(nullptr),
752  coupledEdgesPtr_(nullptr)
753 {
754  // Neighbour patch might not be valid yet so no transformation
755  // calculation possible.
756 }
757 
758 
760 (
761  const cyclicPolyPatch& pp,
762  const polyBoundaryMesh& bm,
763  const label index,
764  const label newSize,
765  const label newStart,
766  const word& neighbName
767 )
768 :
769  coupledPolyPatch(pp, bm, index, newSize, newStart),
770  neighbPatchName_(neighbName),
771  coupleGroup_(pp.coupleGroup_),
772  neighbPatchID_(-1),
773  rotationAxis_(pp.rotationAxis_),
774  rotationCentre_(pp.rotationCentre_),
775  separationVector_(pp.separationVector_),
776  coupledPointsPtr_(nullptr),
777  coupledEdgesPtr_(nullptr)
778 {
779  if (neighbName == name())
780  {
782  << "Neighbour patch name " << neighbName
783  << " cannot be the same as this patch " << name()
784  << exit(FatalError);
785  }
786 
787  // Neighbour patch might not be valid yet so no transformation
788  // calculation possible.
789 }
790 
791 
793 (
794  const cyclicPolyPatch& pp,
795  const polyBoundaryMesh& bm,
796  const label index,
797  const labelUList& mapAddressing,
798  const label newStart
799 )
800 :
801  coupledPolyPatch(pp, bm, index, mapAddressing, newStart),
802  neighbPatchName_(pp.neighbPatchName_),
803  coupleGroup_(pp.coupleGroup_),
804  neighbPatchID_(-1),
805  rotationAxis_(pp.rotationAxis_),
806  rotationCentre_(pp.rotationCentre_),
807  separationVector_(pp.separationVector_),
808  coupledPointsPtr_(nullptr),
809  coupledEdgesPtr_(nullptr)
810 {}
811 
812 
813 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
814 
816 {
817  deleteDemandDrivenData(coupledPointsPtr_);
818  deleteDemandDrivenData(coupledEdgesPtr_);
819 }
820 
821 
822 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
823 
825 {
826  if (neighbPatchName_.empty())
827  {
828  // Try and use patchGroup to find samplePatch and sampleRegion
829  label patchID = coupleGroup_.findOtherPatchID(*this);
830 
831  neighbPatchName_ = boundaryMesh()[patchID].name();
832  }
833  return neighbPatchName_;
834 }
835 
836 
838 {
839  if (neighbPatchID_ == -1)
840  {
841  neighbPatchID_ = this->boundaryMesh().findPatchID(neighbPatchName());
842 
843  if (neighbPatchID_ == -1)
844  {
846  << "Illegal neighbourPatch name " << neighbPatchName()
847  << endl << "Valid patch names are "
848  << this->boundaryMesh().names()
849  << exit(FatalError);
850  }
851 
852  // Check that it is a cyclic
853  const cyclicPolyPatch& nbrPatch = refCast<const cyclicPolyPatch>
854  (
855  this->boundaryMesh()[neighbPatchID_]
856  );
857 
858  if (nbrPatch.neighbPatchName() != name())
859  {
861  << "Patch " << name()
862  << " specifies neighbour patch " << neighbPatchName()
863  << endl << " but that in return specifies "
864  << nbrPatch.neighbPatchName()
865  << endl;
866  }
867  }
868  return neighbPatchID_;
869 }
870 
871 
873 {
874  if (!parallel())
875  {
876  if (transform() == ROTATIONAL)
877  {
878  l =
879  Foam::transform(forwardT(), l-rotationCentre_)
880  + rotationCentre_;
881  }
882  else
883  {
884  l = Foam::transform(forwardT(), l);
885  }
886  }
887  else if (separated())
888  {
889  // transformPosition gets called on the receiving side,
890  // separation gets calculated on the sending side so subtract.
891 
892  const vectorField& s = separation();
893  if (s.size() == 1)
894  {
895  forAll(l, i)
896  {
897  l[i] -= s[0];
898  }
899  }
900  else
901  {
902  l -= s;
903  }
904  }
905 }
906 
907 
908 void Foam::cyclicPolyPatch::transformPosition(point& l, const label facei) const
909 {
910  if (!parallel())
911  {
912  const tensor& T =
913  (
914  forwardT().size() == 1
915  ? forwardT()[0]
916  : forwardT()[facei]
917  );
918 
919  if (transform() == ROTATIONAL)
920  {
921  l = Foam::transform(T, l-rotationCentre_) + rotationCentre_;
922  }
923  else
924  {
925  l = Foam::transform(T, l);
926  }
927  }
928  else if (separated())
929  {
930  const vector& s =
931  (
932  separation().size() == 1
933  ? separation()[0]
934  : separation()[facei]
935  );
936 
937  l -= s;
938  }
939 }
940 
941 
943 {
945 }
946 
947 
949 (
950  const primitivePatch& referPatch,
951  pointField& nbrCtrs,
952  vectorField& nbrAreas,
953  pointField& nbrCc
954 )
955 {}
956 
957 
959 (
960  const primitivePatch& referPatch,
961  const pointField& thisCtrs,
962  const vectorField& thisAreas,
963  const pointField& thisCc,
964  const pointField& nbrCtrs,
965  const vectorField& nbrAreas,
966  const pointField& nbrCc
967 )
968 {
969  calcTransforms
970  (
971  referPatch,
972  thisCtrs,
973  thisAreas,
974  nbrCtrs,
975  nbrAreas
976  );
977 }
978 
979 
981 {
982  calcGeometry
983  (
984  *this,
985  faceCentres(),
986  faceAreas(),
987  faceCellCentres(),
988  neighbPatch().faceCentres(),
989  neighbPatch().faceAreas(),
990  neighbPatch().faceCellCentres()
991  );
992 }
993 
994 
996 (
997  PstreamBuffers& pBufs,
998  const pointField& p
999 )
1000 {
1001  polyPatch::initMovePoints(pBufs, p);
1002 }
1003 
1004 
1007  PstreamBuffers& pBufs,
1008  const pointField& p
1009 )
1010 {
1011  polyPatch::movePoints(pBufs, p);
1012  calcTransforms();
1013 }
1014 
1015 
1017 {
1019 }
1020 
1021 
1023 {
1024  polyPatch::updateMesh(pBufs);
1025  deleteDemandDrivenData(coupledPointsPtr_);
1026  deleteDemandDrivenData(coupledEdgesPtr_);
1027 }
1028 
1029 
1031 {
1032  if (!coupledPointsPtr_)
1033  {
1034  const faceList& nbrLocalFaces = neighbPatch().localFaces();
1035  const labelList& nbrMeshPoints = neighbPatch().meshPoints();
1036 
1037  // Now all we know is that relative face index in *this is same
1038  // as coupled face in nbrPatch and also that the 0th vertex
1039  // corresponds.
1040 
1041  // From local point to nbrPatch or -1.
1042  labelList coupledPoint(nPoints(), -1);
1043 
1044  forAll(*this, patchFacei)
1045  {
1046  const face& fA = localFaces()[patchFacei];
1047  const face& fB = nbrLocalFaces[patchFacei];
1048 
1049  forAll(fA, indexA)
1050  {
1051  label patchPointA = fA[indexA];
1052 
1053  if (coupledPoint[patchPointA] == -1)
1054  {
1055  label indexB = (fB.size() - indexA) % fB.size();
1056 
1057  // Filter out points on wedge axis
1058  if (meshPoints()[patchPointA] != nbrMeshPoints[fB[indexB]])
1059  {
1060  coupledPoint[patchPointA] = fB[indexB];
1061  }
1062  }
1063  }
1064  }
1065 
1066  coupledPointsPtr_ = new edgeList(nPoints());
1067  edgeList& connected = *coupledPointsPtr_;
1068 
1069  // Extract coupled points.
1070  label connectedI = 0;
1071 
1072  forAll(coupledPoint, i)
1073  {
1074  if (coupledPoint[i] != -1)
1075  {
1076  connected[connectedI++] = edge(i, coupledPoint[i]);
1077  }
1078  }
1079 
1080  connected.setSize(connectedI);
1081 
1082  if (debug)
1083  {
1084  OFstream str
1085  (
1086  boundaryMesh().mesh().time().path()
1087  /name() + "_coupledPoints.obj"
1088  );
1089  label vertI = 0;
1090 
1091  Pout<< "Writing file " << str.name() << " with coordinates of "
1092  << "coupled points" << endl;
1093 
1094  forAll(connected, i)
1095  {
1096  const point& a = points()[meshPoints()[connected[i][0]]];
1097  const point& b = points()[nbrMeshPoints[connected[i][1]]];
1098 
1099  str<< "v " << a.x() << ' ' << a.y() << ' ' << a.z() << nl;
1100  str<< "v " << b.x() << ' ' << b.y() << ' ' << b.z() << nl;
1101  vertI += 2;
1102 
1103  str<< "l " << vertI-1 << ' ' << vertI << nl;
1104  }
1105  }
1106  }
1107  return *coupledPointsPtr_;
1108 }
1109 
1110 
1112 {
1113  if (!coupledEdgesPtr_)
1114  {
1115  const edgeList& pointCouples = coupledPoints();
1116 
1117  // Build map from points on *this (A) to points on neighbourpatch (B)
1118  Map<label> aToB(2*pointCouples.size());
1119 
1120  for (const edge& e : pointCouples)
1121  {
1122  aToB.insert(e[0], e[1]);
1123  }
1124 
1125  // Map from edge on A to points (in B indices)
1126  EdgeMap<label> edgeMap(nEdges());
1127 
1128  forAll(*this, patchFacei)
1129  {
1130  const labelList& fEdges = faceEdges()[patchFacei];
1131 
1132  for (const label edgeI : fEdges)
1133  {
1134  const edge& e = edges()[edgeI];
1135 
1136  // Convert edge end points to corresponding points on B side.
1137  const auto fnd0 = aToB.cfind(e[0]);
1138  if (fnd0.found())
1139  {
1140  const auto fnd1 = aToB.cfind(e[1]);
1141  if (fnd1.found())
1142  {
1143  edgeMap.insert(edge(fnd0(), fnd1()), edgeI);
1144  }
1145  }
1146  }
1147  }
1148 
1149  // Use the edgeMap to get the edges on the B side.
1150 
1151  const cyclicPolyPatch& neighbPatch = this->neighbPatch();
1152  const labelList& nbrMp = neighbPatch.meshPoints();
1153  const labelList& mp = meshPoints();
1154 
1155 
1156  coupledEdgesPtr_ = new edgeList(edgeMap.size());
1157  edgeList& coupledEdges = *coupledEdgesPtr_;
1158  label coupleI = 0;
1159 
1160  forAll(neighbPatch, patchFacei)
1161  {
1162  const labelList& fEdges = neighbPatch.faceEdges()[patchFacei];
1163 
1164  for (const label edgeI : fEdges)
1165  {
1166  const edge& e = neighbPatch.edges()[edgeI];
1167 
1168  // Look up A edge from HashTable.
1169  auto iter = edgeMap.find(e);
1170 
1171  if (iter.found())
1172  {
1173  const label edgeA = iter.val();
1174  const edge& eA = edges()[edgeA];
1175 
1176  // Store correspondence. Filter out edges on wedge axis.
1177  if
1178  (
1179  edge(mp[eA[0]], mp[eA[1]])
1180  != edge(nbrMp[e[0]], nbrMp[e[1]])
1181  )
1182  {
1183  coupledEdges[coupleI++] = edge(edgeA, edgeI);
1184  }
1185 
1186  // Remove so we build unique list
1187  edgeMap.erase(iter);
1188  }
1189  }
1190  }
1191  coupledEdges.setSize(coupleI);
1192 
1193 
1194  // Some checks
1195 
1196  forAll(coupledEdges, i)
1197  {
1198  const edge& e = coupledEdges[i];
1199 
1200  if (e[0] < 0 || e[1] < 0)
1201  {
1203  << "Problem : at position " << i
1204  << " illegal couple:" << e
1205  << abort(FatalError);
1206  }
1207  }
1208 
1209  if (debug)
1210  {
1211  OFstream str
1212  (
1213  boundaryMesh().mesh().time().path()
1214  /name() + "_coupledEdges.obj"
1215  );
1216  label vertI = 0;
1217 
1218  Pout<< "Writing file " << str.name() << " with centres of "
1219  << "coupled edges" << endl;
1220 
1221  for (const edge& e : coupledEdges)
1222  {
1223  const point& a = edges()[e[0]].centre(localPoints());
1224  const point& b = neighbPatch.edges()[e[1]].centre
1225  (
1226  neighbPatch.localPoints()
1227  );
1228 
1229  str<< "v " << a.x() << ' ' << a.y() << ' ' << a.z() << nl;
1230  str<< "v " << b.x() << ' ' << b.y() << ' ' << b.z() << nl;
1231  vertI += 2;
1232 
1233  str<< "l " << vertI-1 << ' ' << vertI << nl;
1234  }
1235  }
1236  }
1237  return *coupledEdgesPtr_;
1238 }
1239 
1240 
1243  PstreamBuffers&,
1244  const primitivePatch& pp
1245 ) const
1246 {
1247  if (owner())
1248  {
1249  // Save patch for use in non-owner side ordering. Equivalent to
1250  // processorPolyPatch using OPstream.
1251  ownerPatchPtr_.reset
1252  (
1253  new primitivePatch
1254  (
1255  pp,
1256  pp.points()
1257  )
1258  );
1259  }
1260 }
1261 
1262 
1265  PstreamBuffers& pBufs,
1266  const primitivePatch& pp,
1267  labelList& faceMap,
1268  labelList& rotation
1269 ) const
1270 {
1271  if (debug)
1272  {
1273  Pout<< "order : of " << pp.size()
1274  << " faces of patch:" << name()
1275  << " neighbour:" << neighbPatchName()
1276  << endl;
1277  }
1278  faceMap.setSize(pp.size());
1279  faceMap = -1;
1280 
1281  rotation.setSize(pp.size());
1282  rotation = 0;
1283 
1284  if (transform() == NOORDERING)
1285  {
1286  // No faces, nothing to change.
1287  return false;
1288  }
1289 
1290  if (owner())
1291  {
1292  // Do nothing (i.e. identical mapping, zero rotation).
1293  // See comment at top.
1294  forAll(faceMap, patchFacei)
1295  {
1296  faceMap[patchFacei] = patchFacei;
1297  }
1298 
1299  return false;
1300  }
1301  else
1302  {
1303  // Get stored geometry from initOrder invocation of owner.
1304  const primitivePatch& pp0 = neighbPatch().ownerPatchPtr_();
1305 
1306  // Get geometric quantities
1307  pointField half0Ctrs, half1Ctrs, anchors0;
1308  scalarField tols;
1309  getCentresAndAnchors
1310  (
1311  pp0,
1312  pp,
1313 
1314  half0Ctrs,
1315  half1Ctrs,
1316  anchors0,
1317  tols
1318  );
1319 
1320  if (debug)
1321  {
1322  Pout<< "half0 transformed faceCentres (avg) : "
1323  << gAverage(half0Ctrs) << nl
1324  << "half1 untransformed faceCentres (avg) : "
1325  << gAverage(half1Ctrs) << endl;
1326  }
1327 
1328  // Geometric match of face centre vectors
1329  bool matchedAll = matchPoints
1330  (
1331  half1Ctrs,
1332  half0Ctrs,
1333  tols,
1334  true,
1335  faceMap
1336  );
1337 
1338  if (!matchedAll || debug)
1339  {
1340  // Dump halves
1341  fileName nm0
1342  (
1343  boundaryMesh().mesh().time().path()
1344  /neighbPatch().name()+"_faces.obj"
1345  );
1346  Pout<< "cyclicPolyPatch::order : Writing neighbour"
1347  << " faces to OBJ file " << nm0 << endl;
1348  writeOBJ(nm0, pp0, pp0.points());
1349 
1350  fileName nm1
1351  (
1352  boundaryMesh().mesh().time().path()
1353  /name()+"_faces.obj"
1354  );
1355  Pout<< "cyclicPolyPatch::order : Writing my"
1356  << " faces to OBJ file " << nm1 << endl;
1357  writeOBJ(nm1, pp, pp.points());
1358 
1359  OFstream ccStr
1360  (
1361  boundaryMesh().mesh().time().path()
1362  /name() + "_faceCentres.obj"
1363  );
1364  Pout<< "cyclicPolyPatch::order : "
1365  << "Dumping currently found cyclic match as lines between"
1366  << " corresponding face centres to file " << ccStr.name()
1367  << endl;
1368 
1369  // Recalculate untransformed face centres
1370  //pointField rawHalf0Ctrs =
1371  // calcFaceCentres(half0Faces, pp.points());
1372  label vertI = 0;
1373 
1374  forAll(half1Ctrs, i)
1375  {
1376  if (faceMap[i] != -1)
1377  {
1378  // Write edge between c1 and c0
1379  const point& c0 = half0Ctrs[faceMap[i]];
1380  const point& c1 = half1Ctrs[i];
1381  writeOBJ(ccStr, c0, c1, vertI);
1382  }
1383  }
1384  }
1385 
1386  if (!matchedAll)
1387  {
1389  << "Patch:" << name() << " : "
1390  << "Cannot match vectors to faces on both sides of patch"
1391  << endl
1392  << " Perhaps your faces do not match?"
1393  << " The obj files written contain the current match." << endl
1394  << " Continuing with incorrect face ordering from now on!"
1395  << endl;
1396 
1397  return false;
1398  }
1399 
1400 
1401  // Set rotation.
1402  forAll(faceMap, oldFacei)
1403  {
1404  // The face f will be at newFacei (after morphing) and we want its
1405  // anchorPoint (= f[0]) to align with the anchorpoint for the
1406  // corresponding face on the other side.
1407 
1408  label newFacei = faceMap[oldFacei];
1409 
1410  const point& wantedAnchor = anchors0[newFacei];
1411 
1412  rotation[newFacei] = getRotation
1413  (
1414  pp.points(),
1415  pp[oldFacei],
1416  wantedAnchor,
1417  tols[oldFacei]
1418  );
1419 
1420  if (rotation[newFacei] == -1)
1421  {
1423  << "in patch " << name()
1424  << " : "
1425  << "Cannot find point on face " << pp[oldFacei]
1426  << " with vertices "
1427  << UIndirectList<point>(pp.points(), pp[oldFacei])
1428  << " that matches point " << wantedAnchor
1429  << " when matching the halves of processor patch " << name()
1430  << "Continuing with incorrect face ordering from now on!"
1431  << endl;
1432 
1433  return false;
1434  }
1435  }
1436 
1437  ownerPatchPtr_.clear();
1438 
1439  // Return false if no change necessary, true otherwise.
1440 
1441  forAll(faceMap, facei)
1442  {
1443  if (faceMap[facei] != facei || rotation[facei] != 0)
1444  {
1445  return true;
1446  }
1447  }
1448 
1449  return false;
1450  }
1451 }
1452 
1453 
1455 {
1457  if (!neighbPatchName_.empty())
1458  {
1459  os.writeEntry("neighbourPatch", neighbPatchName_);
1460  }
1461  coupleGroup_.write(os);
1462  switch (transform())
1463  {
1464  case ROTATIONAL:
1465  {
1466  os.writeEntry("rotationAxis", rotationAxis_);
1467  os.writeEntry("rotationCentre", rotationCentre_);
1468  break;
1469  }
1470  case TRANSLATIONAL:
1471  {
1472  os.writeEntry("separationVector", separationVector_);
1473  break;
1474  }
1475  case NOORDERING:
1476  {
1477  break;
1478  }
1479  default:
1480  {
1481  // no additional info to write
1482  }
1483  }
1484 }
1485 
1486 
1487 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::PrimitivePatch::points
const Field< point_type > & points() const noexcept
Return reference to global points.
Definition: PrimitivePatch.H:299
Foam::addToRunTimeSelectionTable
addToRunTimeSelectionTable(decompositionMethod, kahipDecomp, dictionary)
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
Foam::HashTable::size
label size() const noexcept
The number of elements in table.
Definition: HashTableI.H:52
Foam::Tensor< scalar >
Foam::scalarField
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Definition: primitiveFieldsFwd.H:52
setSize
points setSize(newPointi)
Foam::constant::atomic::mp
const dimensionedScalar mp
Proton mass.
Foam::Vector::x
const Cmpt & x() const
Access to the vector x component.
Definition: VectorI.H:73
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::faceMap
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Definition: blockMeshMergeTopological.C:94
Foam::cyclicPolyPatch::updateMesh
virtual void updateMesh(PstreamBuffers &)
Update of the patch topology.
Definition: cyclicPolyPatch.C:1022
Foam::cyclicPolyPatch::initMovePoints
virtual void initMovePoints(PstreamBuffers &, const pointField &)
Initialise the patches for moving points.
Definition: cyclicPolyPatch.C:996
Foam::edgeList
List< edge > edgeList
A List of edges.
Definition: edgeList.H:63
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::fileName
A class for handling file names.
Definition: fileName.H:73
SubField.H
s
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Definition: gmvOutputSpray.H:25
Foam::polyPatch::movePoints
virtual void movePoints(PstreamBuffers &, const pointField &p)
Correct patches after moving points.
Definition: polyPatch.C:61
Foam::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:63
Foam::PrimitivePatch::edges
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
Definition: PrimitivePatch.C:183
Foam::OFstream::name
virtual const fileName & name() const
Read/write access to the name of the stream.
Definition: OSstream.H:107
cyclicPolyPatch.H
Foam::cyclicPolyPatch
Cyclic plane patch.
Definition: cyclicPolyPatch.H:66
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::gAverage
Type gAverage(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:604
Foam::meshTools::writeOBJ
void writeOBJ(Ostream &os, const point &pt)
Write obj representation of a point.
Definition: meshTools.C:203
Foam::cyclicPolyPatch::initGeometry
virtual void initGeometry(PstreamBuffers &)
Initialise the calculation of the patch geometry.
Definition: cyclicPolyPatch.C:942
Foam::cyclicPolyPatch::order
virtual bool order(PstreamBuffers &, const primitivePatch &, labelList &faceMap, labelList &rotation) const
Return new ordering for primitivePatch.
Definition: cyclicPolyPatch.C:1264
demandDrivenData.H
Template functions to aid in the implementation of demand driven data.
Foam::PstreamBuffers
Buffers for inter-processor communications streams (UOPstream, UIPstream).
Definition: PstreamBuffers.H:88
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:63
Foam::tensorField
Field< tensor > tensorField
Specialisation of Field<T> for tensor.
Definition: primitiveFieldsFwd.H:57
Foam::HashTable::insert
bool insert(const Key &key, const T &obj)
Copy insert a new entry, not overwriting existing entries.
Definition: HashTableI.H:180
Foam::Map< label >
unitConversion.H
Unit conversion functions.
Foam::boolList
List< bool > boolList
A List of bools.
Definition: List.H:65
Foam::cyclicPolyPatch::initUpdateMesh
virtual void initUpdateMesh(PstreamBuffers &)
Initialise the update of the patch topology.
Definition: cyclicPolyPatch.C:1016
Foam::FatalIOError
IOerror FatalIOError
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::coupledPolyPatch
The coupledPolyPatch is an abstract base class for patches that couple regions of the computational d...
Definition: coupledPolyPatch.H:54
Foam::PrimitivePatch::faceEdges
const labelListList & faceEdges() const
Return face-edge addressing.
Definition: PrimitivePatch.C:275
Foam::Pout
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Foam::transform
dimensionSet transform(const dimensionSet &ds)
Return the argument; transformations do not change the dimensions.
Definition: dimensionSet.C:521
polyMesh.H
Foam::polyPatch::updateMesh
virtual void updateMesh(PstreamBuffers &)
Update of the patch topology.
Definition: polyPatch.C:67
Foam::Vector::z
const Cmpt & z() const
Access to the vector z component.
Definition: VectorI.H:85
transformField.H
Spatial transformation functions for primitive fields.
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
OFstream.H
Foam::vectorField
Field< vector > vectorField
Specialisation of Field<T> for vector.
Definition: primitiveFieldsFwd.H:54
Foam::magSqr
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
Foam::cyclicPolyPatch::coupledPoints
const edgeList & coupledPoints() const
Return connected points (from patch local to neighbour patch local)
Definition: cyclicPolyPatch.C:1030
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Foam::coupledPolyPatch::write
virtual void write(Ostream &os) const
Write the polyPatch data as a dictionary.
Definition: coupledPolyPatch.C:577
Foam::deleteDemandDrivenData
void deleteDemandDrivenData(DataPtr &dataPtr)
Definition: demandDrivenData.H:42
n
label n
Definition: TABSMDCalcMethod2.H:31
matchPoints.H
Determine correspondence between points. See below.
Foam::polyPatch::initUpdateMesh
virtual void initUpdateMesh(PstreamBuffers &)
Initialise the update of the patch topology.
Definition: polyPatch.H:114
Foam::constant::physicoChemical::c1
const dimensionedScalar c1
First radiation constant: default SI units: [W/m2].
Foam::constant::physicoChemical::b
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:27
Foam::Field< vector >
Foam::polyPatch::initMovePoints
virtual void initMovePoints(PstreamBuffers &, const pointField &)
Initialise the patches for moving points.
Definition: polyPatch.H:107
Foam::HashTable::erase
bool erase(const iterator &iter)
Erase an entry specified by given iterator.
Definition: HashTable.C:392
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
Foam::cyclicPolyPatch::calcGeometry
virtual void calcGeometry(PstreamBuffers &)
Calculate the patch geometry.
Definition: cyclicPolyPatch.C:980
Foam::OSstream::name
virtual const fileName & name() const
Get the name of the stream.
Definition: OSstream.H:107
Foam::List::setSize
void setSize(const label n)
Alias for resize()
Definition: List.H:222
patchID
label patchID
Definition: boundaryProcessorFaPatchPoints.H:5
Foam::Vector::centre
const Vector< Cmpt > & centre(const Foam::List< Vector< Cmpt >> &) const
Return *this (used for point which is a typedef to Vector<scalar>.
Definition: VectorI.H:114
Foam::T
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
Definition: FieldFieldFunctions.C:58
SeriousErrorInFunction
#define SeriousErrorInFunction
Report an error message using Foam::SeriousError.
Definition: messageStream.H:306
Foam::dictionary::readEntry
bool readEntry(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX, bool mandatory=true) const
Definition: dictionaryTemplates.C:302
Foam::radToDeg
constexpr scalar radToDeg(const scalar rad) noexcept
Conversion from radians to degrees.
Definition: unitConversion.H:54
Foam::polyPatch::initGeometry
virtual void initGeometry(PstreamBuffers &)
Initialise the calculation of the patch geometry.
Definition: polyPatch.H:99
Foam::cyclicPolyPatch::coupledEdges
const edgeList & coupledEdges() const
Return connected edges (from patch local to neighbour patch local).
Definition: cyclicPolyPatch.C:1111
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
Foam::word::valid
static bool valid(char c)
Is this character valid for a word?
Definition: wordI.H:59
Foam::cyclicPolyPatch::transformPosition
virtual void transformPosition(pointField &l) const
Transform a patch-based position from other side to this side.
Definition: cyclicPolyPatch.C:872
os
OBJstream os(runTime.globalPath()/outputName)
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
Foam::cyclicPolyPatch::~cyclicPolyPatch
virtual ~cyclicPolyPatch()
Destructor.
Definition: cyclicPolyPatch.C:815
Foam::Ostream::write
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
Foam::vector
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:51
Foam::HashTable::find
iterator find(const Key &key)
Find and return an iterator set at the hashed entry.
Definition: HashTableI.H:114
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::PrimitivePatch::localPoints
const Field< point_type > & localPoints() const
Return pointField of points in patch.
Definition: PrimitivePatch.C:359
Foam::OFstream
Output to file stream, using an OSstream.
Definition: OFstream.H:53
Foam::cyclicPolyPatch::movePoints
virtual void movePoints(PstreamBuffers &, const pointField &)
Correct patches after moving points.
Definition: cyclicPolyPatch.C:1006
Time.H
Foam::EdgeMap< label >
Foam::Vector::y
const Cmpt & y() const
Access to the vector y component.
Definition: VectorI.H:79
Foam::cyclicPolyPatch::initOrder
virtual void initOrder(PstreamBuffers &, const primitivePatch &) const
Initialize ordering for primitivePatch. Does not.
Definition: cyclicPolyPatch.C:1242
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
edgeHashes.H
clear
patchWriters clear()
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::polyPatch::faceCentres
const vectorField::subField faceCentres() const
Return face centres.
Definition: polyPatch.C:321
Foam::cyclicPolyPatch::write
virtual void write(Ostream &) const
Write the polyPatch data as a dictionary.
Definition: cyclicPolyPatch.C:1454
Foam::faceList
List< face > faceList
A List of faces.
Definition: faceListFwd.H:47
Foam::Vector
Templated 3D Vector derived from VectorSpace adding construction from 3 components,...
Definition: Vector.H:62
Foam::findMax
label findMax(const ListType &input, label start=0)
Foam::List< label >
Foam::sqrt
dimensionedScalar sqrt(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:144
Foam::acos
dimensionedScalar acos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:268
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::UList< label >
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
Foam::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:327
path
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
Foam::word::null
static const word null
An empty word.
Definition: word.H:80
Foam::cyclicPolyPatch::calcTransforms
virtual void calcTransforms()
Recalculate the transformation tensors.
Definition: cyclicPolyPatch.C:78
polyBoundaryMesh.H
Foam::Ostream::writeEntry
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
Definition: Ostream.H:236
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
Foam::UIndirectList
A List with indirect addressing.
Definition: faMatrix.H:60
Foam::boundaryMesh
Addressing for all faces on surface of mesh. Can either be read from polyMesh or from triSurface....
Definition: boundaryMesh.H:62
Foam::primitivePatch
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
A PrimitivePatch with a SubList addressing for the faces, const reference for the point field.
Definition: primitivePatch.H:51
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:72
FatalIOErrorInFunction
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
p0
const volScalarField & p0
Definition: EEqn.H:36
Foam::rotationTensor
tensor rotationTensor(const vector &n1, const vector &n2)
Rotational transformation tensor from vector n1 to n2.
Definition: transform.H:51
Foam::point
vector point
Point is a vector.
Definition: point.H:43
Foam::coupledPolyPatch::transformType
transformType
Definition: coupledPolyPatch.H:60
Foam::PrimitivePatch::meshPoints
const labelList & meshPoints() const
Return labelList of mesh points in patch.
Definition: PrimitivePatch.C:330
Foam::dictionary::getOrDefault
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:148
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::cyclicPolyPatch::neighbPatchID
virtual label neighbPatchID() const
Neighbour patchID.
Definition: cyclicPolyPatch.C:837
Foam::matchPoints
bool matchPoints(const UList< point > &pts0, const UList< point > &pts1, const UList< scalar > &matchDistance, const bool verbose, labelList &from0To1, const point &origin=point::zero)
Determine correspondence between pointFields. Gets passed.
Definition: matchPoints.C:36
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328
Foam::faceCells
Smooth ATC in cells next to a set of patches supplied by type.
Definition: faceCells.H:56
Foam::cyclicPolyPatch::neighbPatchName
const word & neighbPatchName() const
Neighbour patch name.
Definition: cyclicPolyPatch.C:824
Foam::tensor
Tensor< scalar > tensor
Tensor of scalars, i.e. Tensor<scalar>.
Definition: symmTensor.H:61
Foam::average
dimensioned< Type > average(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:328
Foam::PrimitivePatch
A list of faces which address into the list of points.
Definition: PrimitivePatch.H:79
Foam::cyclicPolyPatch::cyclicPolyPatch
cyclicPolyPatch(const word &name, const label size, const label start, const label index, const polyBoundaryMesh &bm, const word &patchType, const transformType transform=UNKNOWN)
Construct from components.
Definition: cyclicPolyPatch.C:593