oldCyclicPolyPatch.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 | Copyright (C) 2011-2015 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 "oldCyclicPolyPatch.H"
28 #include "polyBoundaryMesh.H"
29 #include "polyMesh.H"
30 #include "demandDrivenData.H"
31 #include "OFstream.H"
32 #include "patchZones.H"
33 #include "matchPoints.H"
34 #include "Time.H"
35 #include "transformList.H"
36 #include "cyclicPolyPatch.H"
37 
38 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
39 
40 namespace Foam
41 {
42  defineTypeNameAndDebug(oldCyclicPolyPatch, 0);
43 
44  addToRunTimeSelectionTable(polyPatch, oldCyclicPolyPatch, word);
45  addToRunTimeSelectionTable(polyPatch, oldCyclicPolyPatch, dictionary);
46 }
47 
48 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
49 
51 (
52  const UList<face>& faces,
53  const pointField& points
54 )
55 {
56  pointField ctrs(faces.size());
57 
58  forAll(faces, faceI)
59  {
60  ctrs[faceI] = faces[faceI].centre(points);
61  }
62 
63  return ctrs;
64 }
65 
66 
68 (
69  const UList<face>& faces,
70  const pointField& points
71 )
72 {
73  pointField anchors(faces.size());
74 
75  forAll(faces, faceI)
76  {
77  anchors[faceI] = points[faces[faceI][0]];
78  }
79 
80  return anchors;
81 }
82 
83 
85 (
86  const pointField& points,
87  const faceList& faces
88 )
89 {
90  label maxI = -1;
91  scalar maxAreaSqr = -GREAT;
92 
93  forAll(faces, faceI)
94  {
95  scalar areaSqr = magSqr(faces[faceI].normal(points));
96 
97  if (areaSqr > maxAreaSqr)
98  {
99  maxAreaSqr = areaSqr;
100  maxI = faceI;
101  }
102  }
103  return maxI;
104 }
105 
106 
107 // Get geometric zones of patch by looking at normals.
108 // Method 1: any edge with sharpish angle is edge between two halves.
109 // (this will handle e.g. wedge geometries).
110 // Also two fully disconnected regions will be handled this way.
111 // Method 2: sort faces into two halves based on face normal.
113 (
114  const primitivePatch& pp,
115  labelList& half0ToPatch,
116  labelList& half1ToPatch
117 ) const
118 {
119  // Calculate normals
120  const vectorField& faceNormals = pp.faceNormals();
121 
122  // Find edges with sharp angles.
123  boolList regionEdge(pp.nEdges(), false);
124 
125  const labelListList& edgeFaces = pp.edgeFaces();
126 
127  label nRegionEdges = 0;
128 
129  forAll(edgeFaces, edgeI)
130  {
131  const labelList& eFaces = edgeFaces[edgeI];
132 
133  // Check manifold edges for sharp angle.
134  // (Non-manifold already handled by patchZones)
135  if (eFaces.size() == 2)
136  {
137  if ((faceNormals[eFaces[0]] & faceNormals[eFaces[1]])< featureCos_)
138  {
139  regionEdge[edgeI] = true;
140 
141  nRegionEdges++;
142  }
143  }
144  }
145 
146 
147  // For every face determine zone it is connected to (without crossing
148  // any regionEdge)
149  patchZones ppZones(pp, regionEdge);
150 
151  if (debug)
152  {
153  Pout<< "oldCyclicPolyPatch::getGeometricHalves : "
154  << "Found " << nRegionEdges << " edges on patch " << name()
155  << " where the cos of the angle between two connected faces"
156  << " was less than " << featureCos_ << nl
157  << "Patch divided by these and by single sides edges into "
158  << ppZones.nZones() << " parts." << endl;
159 
160 
161  // Dumping zones to obj files.
162 
163  labelList nZoneFaces(ppZones.nZones());
164 
165  for (label zoneI = 0; zoneI < ppZones.nZones(); zoneI++)
166  {
167  OFstream stream
168  (
169  boundaryMesh().mesh().time().path()
170  /name()+"_zone_"+Foam::name(zoneI)+".obj"
171  );
172  Pout<< "oldCyclicPolyPatch::getGeometricHalves : Writing zone "
173  << zoneI << " face centres to OBJ file " << stream.name()
174  << endl;
175 
176  labelList zoneFaces(findIndices(ppZones, zoneI));
177 
178  forAll(zoneFaces, i)
179  {
180  writeOBJ(stream, pp[zoneFaces[i]].centre(pp.points()));
181  }
182 
183  nZoneFaces[zoneI] = zoneFaces.size();
184  }
185  }
186 
187 
188  if (ppZones.nZones() == 2)
189  {
190  half0ToPatch = findIndices(ppZones, 0);
191  half1ToPatch = findIndices(ppZones, 1);
192  }
193  else
194  {
195  if (debug)
196  {
197  Pout<< "oldCyclicPolyPatch::getGeometricHalves :"
198  << " falling back to face-normal comparison" << endl;
199  }
200  label n0Faces = 0;
201  half0ToPatch.setSize(pp.size());
202 
203  label n1Faces = 0;
204  half1ToPatch.setSize(pp.size());
205 
206  // Compare to face 0 normal.
207  forAll(faceNormals, faceI)
208  {
209  if ((faceNormals[faceI] & faceNormals[0]) > 0)
210  {
211  half0ToPatch[n0Faces++] = faceI;
212  }
213  else
214  {
215  half1ToPatch[n1Faces++] = faceI;
216  }
217  }
218  half0ToPatch.setSize(n0Faces);
219  half1ToPatch.setSize(n1Faces);
220 
221  if (debug)
222  {
223  Pout<< "oldCyclicPolyPatch::getGeometricHalves :"
224  << " Number of faces per zone:("
225  << n0Faces << ' ' << n1Faces << ')' << endl;
226  }
227  }
228 
229  if (half0ToPatch.size() != half1ToPatch.size())
230  {
231  fileName casePath(boundaryMesh().mesh().time().path());
232 
233  // Dump halves
234  {
235  fileName nm0(casePath/name()+"_half0_faces.obj");
236  Pout<< "oldCyclicPolyPatch::getGeometricHalves : Writing half0"
237  << " faces to OBJ file " << nm0 << endl;
238  writeOBJ(nm0, UIndirectList<face>(pp, half0ToPatch)(), pp.points());
239 
240  fileName nm1(casePath/name()+"_half1_faces.obj");
241  Pout<< "oldCyclicPolyPatch::getGeometricHalves : Writing half1"
242  << " faces to OBJ file " << nm1 << endl;
243  writeOBJ(nm1, UIndirectList<face>(pp, half1ToPatch)(), pp.points());
244  }
245 
246  // Dump face centres
247  {
248  OFstream str0(casePath/name()+"_half0.obj");
249  Pout<< "oldCyclicPolyPatch::getGeometricHalves : Writing half0"
250  << " face centres to OBJ file " << str0.name() << endl;
251 
252  forAll(half0ToPatch, i)
253  {
254  writeOBJ(str0, pp[half0ToPatch[i]].centre(pp.points()));
255  }
256 
257  OFstream str1(casePath/name()+"_half1.obj");
258  Pout<< "oldCyclicPolyPatch::getGeometricHalves : Writing half1"
259  << " face centres to OBJ file " << str1.name() << endl;
260  forAll(half1ToPatch, i)
261  {
262  writeOBJ(str1, pp[half1ToPatch[i]].centre(pp.points()));
263  }
264  }
265 
267  << "Patch " << name() << " gets decomposed in two zones of"
268  << "inequal size: " << half0ToPatch.size()
269  << " and " << half1ToPatch.size() << endl
270  << "This means that the patch is either not two separate regions"
271  << " or one region where the angle between the different regions"
272  << " is not sufficiently sharp." << endl
273  << "Please adapt the featureCos setting." << endl
274  << "Continuing with incorrect face ordering from now on!" << endl;
275 
276  return false;
277  }
278  else
279  {
280  return true;
281  }
282 }
283 
284 
285 // Given a split of faces into left and right half calculate the centres
286 // and anchor points. Transform the left points so they align with the
287 // right ones.
289 (
290  const primitivePatch& pp,
291  const faceList& half0Faces,
292  const faceList& half1Faces,
293 
294  pointField& ppPoints,
295  pointField& half0Ctrs,
296  pointField& half1Ctrs,
297  pointField& anchors0,
298  scalarField& tols
299 ) const
300 {
301  // Get geometric data on both halves.
302  half0Ctrs = calcFaceCentres(half0Faces, pp.points());
303  anchors0 = getAnchorPoints(half0Faces, pp.points());
304  half1Ctrs = calcFaceCentres(half1Faces, pp.points());
305 
306  switch (transform())
307  {
308  case ROTATIONAL:
309  {
310  label face0 = getConsistentRotationFace(half0Ctrs);
311  label face1 = getConsistentRotationFace(half1Ctrs);
312 
313  vector n0 = ((half0Ctrs[face0] - rotationCentre_) ^ rotationAxis_);
314  vector n1 = ((half1Ctrs[face1] - rotationCentre_) ^ -rotationAxis_);
315  n0 /= mag(n0) + VSMALL;
316  n1 /= mag(n1) + VSMALL;
317 
318  if (debug)
319  {
320  Pout<< "oldCyclicPolyPatch::getCentresAndAnchors :"
321  << " Specified rotation :"
322  << " n0:" << n0 << " n1:" << n1 << endl;
323  }
324 
325  // Rotation (around origin)
326  const tensor reverseT(rotationTensor(n0, -n1));
327 
328  // Rotation
329  forAll(half0Ctrs, faceI)
330  {
331  half0Ctrs[faceI] = Foam::transform(reverseT, half0Ctrs[faceI]);
332  anchors0[faceI] = Foam::transform(reverseT, anchors0[faceI]);
333  }
334 
335  ppPoints = Foam::transform(reverseT, pp.points());
336 
337  break;
338  }
339  //- Problem: usually specified translation is not accurate enough
340  //- To get proper match so keep automatic determination over here.
341  //case TRANSLATIONAL:
342  //{
343  // // Transform 0 points.
344  //
345  // if (debug)
346  // {
347  // Pout<< "oldCyclicPolyPatch::getCentresAndAnchors :"
348  // << "Specified translation : " << separationVector_
349  // << endl;
350  // }
351  //
352  // half0Ctrs += separationVector_;
353  // anchors0 += separationVector_;
354  // break;
355  //}
356  default:
357  {
358  // Assumes that cyclic is planar. This is also the initial
359  // condition for patches without faces.
360 
361  // Determine the face with max area on both halves. These
362  // two faces are used to determine the transformation tensors
363  label max0I = findMaxArea(pp.points(), half0Faces);
364  vector n0 = half0Faces[max0I].normal(pp.points());
365  n0 /= mag(n0) + VSMALL;
366 
367  label max1I = findMaxArea(pp.points(), half1Faces);
368  vector n1 = half1Faces[max1I].normal(pp.points());
369  n1 /= mag(n1) + VSMALL;
370 
371  if (mag(n0 & n1) < 1-matchTolerance())
372  {
373  if (debug)
374  {
375  Pout<< "oldCyclicPolyPatch::getCentresAndAnchors :"
376  << " Detected rotation :"
377  << " n0:" << n0 << " n1:" << n1 << endl;
378  }
379 
380  // Rotation (around origin)
381  const tensor reverseT(rotationTensor(n0, -n1));
382 
383  // Rotation
384  forAll(half0Ctrs, faceI)
385  {
386  half0Ctrs[faceI] = Foam::transform
387  (
388  reverseT,
389  half0Ctrs[faceI]
390  );
391  anchors0[faceI] = Foam::transform
392  (
393  reverseT,
394  anchors0[faceI]
395  );
396  }
397  ppPoints = Foam::transform(reverseT, pp.points());
398  }
399  else
400  {
401  // Parallel translation. Get average of all used points.
402 
403  primitiveFacePatch half0(half0Faces, pp.points());
404  const pointField& half0Pts = half0.localPoints();
405  const point ctr0(sum(half0Pts)/half0Pts.size());
406 
407  primitiveFacePatch half1(half1Faces, pp.points());
408  const pointField& half1Pts = half1.localPoints();
409  const point ctr1(sum(half1Pts)/half1Pts.size());
410 
411  if (debug)
412  {
413  Pout<< "oldCyclicPolyPatch::getCentresAndAnchors :"
414  << " Detected translation :"
415  << " n0:" << n0 << " n1:" << n1
416  << " ctr0:" << ctr0 << " ctr1:" << ctr1 << endl;
417  }
418 
419  half0Ctrs += ctr1 - ctr0;
420  anchors0 += ctr1 - ctr0;
421  ppPoints = pp.points() + ctr1 - ctr0;
422  }
423  break;
424  }
425  }
426 
427 
428  // Calculate typical distance per face
429  tols = matchTolerance()*calcFaceTol(half1Faces, pp.points(), half1Ctrs);
430 }
431 
432 
433 // Calculates faceMap and rotation. Returns true if all ok.
435 (
436  const bool report,
437  const primitivePatch& pp,
438  const labelList& half0ToPatch,
439  const pointField& anchors0,
440 
441  const labelList& half1ToPatch,
442  const faceList& half1Faces,
443  const labelList& from1To0,
444 
445  const scalarField& tols,
446 
448  labelList& rotation
449 ) const
450 {
451  // Set faceMap such that half0 faces get first and corresponding half1
452  // faces last.
453 
454  forAll(half0ToPatch, half0FaceI)
455  {
456  // Label in original patch
457  label patchFaceI = half0ToPatch[half0FaceI];
458 
459  faceMap[patchFaceI] = half0FaceI;
460 
461  // No rotation
462  rotation[patchFaceI] = 0;
463  }
464 
465  bool fullMatch = true;
466 
467  forAll(from1To0, half1FaceI)
468  {
469  label patchFaceI = half1ToPatch[half1FaceI];
470 
471  // This face has to match the corresponding one on half0.
472  label half0FaceI = from1To0[half1FaceI];
473 
474  label newFaceI = half0FaceI + pp.size()/2;
475 
476  faceMap[patchFaceI] = newFaceI;
477 
478  // Rotate patchFaceI such that its f[0] aligns with that of
479  // the corresponding face
480  // (which after shuffling will be at position half0FaceI)
481 
482  const point& wantedAnchor = anchors0[half0FaceI];
483 
484  rotation[newFaceI] = getRotation
485  (
486  pp.points(),
487  half1Faces[half1FaceI],
488  wantedAnchor,
489  tols[half1FaceI]
490  );
491 
492  if (rotation[newFaceI] == -1)
493  {
494  fullMatch = false;
495 
496  if (report)
497  {
498  const face& f = half1Faces[half1FaceI];
500  << "Patch:" << name() << " : "
501  << "Cannot find point on face " << f
502  << " with vertices:"
503  << UIndirectList<point>(pp.points(), f)()
504  << " that matches point " << wantedAnchor
505  << " when matching the halves of cyclic patch " << name()
506  << endl
507  << "Continuing with incorrect face ordering from now on!"
508  << endl;
509  }
510  }
511  }
512  return fullMatch;
513 }
514 
515 
517 (
518  const pointField& faceCentres
519 ) const
520 {
521  const scalarField magRadSqr
522  (
523  magSqr((faceCentres - rotationCentre_) ^ rotationAxis_)
524  );
525  scalarField axisLen
526  (
527  (faceCentres - rotationCentre_) & rotationAxis_
528  );
529  axisLen = axisLen - min(axisLen);
530  const scalarField magLenSqr
531  (
532  magRadSqr + axisLen*axisLen
533  );
534 
535  label rotFace = -1;
536  scalar maxMagLenSqr = -GREAT;
537  scalar maxMagRadSqr = -GREAT;
538  forAll(faceCentres, i)
539  {
540  if (magLenSqr[i] >= maxMagLenSqr)
541  {
542  if (magRadSqr[i] > maxMagRadSqr)
543  {
544  rotFace = i;
545  maxMagLenSqr = magLenSqr[i];
546  maxMagRadSqr = magRadSqr[i];
547  }
548  }
549  }
550 
551  if (debug)
552  {
553  Info<< "getConsistentRotationFace(const pointField&)" << nl
554  << " rotFace = " << rotFace << nl
555  << " point = " << faceCentres[rotFace] << endl;
556  }
557 
558  return rotFace;
559 }
560 
561 
562 // * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * * * * //
563 
565 (
566  const word& name,
567  const label size,
568  const label start,
569  const label index,
570  const polyBoundaryMesh& bm,
571  const word& patchType,
573 )
574 :
575  coupledPolyPatch(name, size, start, index, bm, patchType, transform),
576  featureCos_(0.9),
577  rotationAxis_(vector::zero),
578  rotationCentre_(point::zero),
579  separationVector_(vector::zero)
580 {}
581 
582 
584 (
585  const word& name,
586  const dictionary& dict,
587  const label index,
588  const polyBoundaryMesh& bm,
589  const word& patchType
590 )
591 :
592  coupledPolyPatch(name, dict, index, bm, patchType),
593  featureCos_(0.9),
594  rotationAxis_(vector::zero),
595  rotationCentre_(point::zero),
596  separationVector_(vector::zero)
597 {
598  if (dict.found("neighbourPatch"))
599  {
601  (
602  dict
603  ) << "Found \"neighbourPatch\" entry when reading cyclic patch "
604  << name << endl
605  << "Is this mesh already with split cyclics?" << endl
606  << "If so run a newer version that supports it"
607  << ", if not comment out the \"neighbourPatch\" entry and re-run"
608  << exit(FatalIOError);
609  }
610 
611  dict.readIfPresent("featureCos", featureCos_);
612 
613  switch (transform())
614  {
615  case ROTATIONAL:
616  {
617  dict.lookup("rotationAxis") >> rotationAxis_;
618  dict.lookup("rotationCentre") >> rotationCentre_;
619  break;
620  }
621  case TRANSLATIONAL:
622  {
623  dict.lookup("separationVector") >> separationVector_;
624  break;
625  }
626  default:
627  {
628  // no additional info required
629  }
630  }
631 }
632 
633 
635 (
636  const oldCyclicPolyPatch& pp,
637  const polyBoundaryMesh& bm
638 )
639 :
640  coupledPolyPatch(pp, bm),
641  featureCos_(pp.featureCos_),
642  rotationAxis_(pp.rotationAxis_),
643  rotationCentre_(pp.rotationCentre_),
644  separationVector_(pp.separationVector_)
645 {}
646 
647 
649 (
650  const oldCyclicPolyPatch& pp,
651  const polyBoundaryMesh& bm,
652  const label index,
653  const label newSize,
654  const label newStart
655 )
656 :
657  coupledPolyPatch(pp, bm, index, newSize, newStart),
658  featureCos_(pp.featureCos_),
659  rotationAxis_(pp.rotationAxis_),
660  rotationCentre_(pp.rotationCentre_),
661  separationVector_(pp.separationVector_)
662 {}
663 
664 
665 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
666 
668 {}
669 
670 
671 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
672 
674 {
676 }
677 
678 
680 (
681  const primitivePatch& referPatch,
682  const pointField& thisCtrs,
683  const vectorField& thisAreas,
684  const pointField& thisCc,
685  const pointField& nbrCtrs,
686  const vectorField& nbrAreas,
687  const pointField& nbrCc
688 )
689 {}
690 
691 
693 {}
694 
695 
697 (
698  PstreamBuffers& pBufs,
699  const pointField& p
700 )
701 {
703 }
704 
705 
707 (
708  PstreamBuffers& pBufs,
709  const pointField& p
710 )
711 {
712  polyPatch::movePoints(pBufs, p);
713 }
714 
715 
717 {
719 }
720 
721 
723 {
724  polyPatch::updateMesh(pBufs);
725 }
726 
727 
729 (
731  const primitivePatch& pp
732 ) const
733 {}
734 
735 
736 // Return new ordering. Ordering is -faceMap: for every face index
737 // the new face -rotation:for every new face the clockwise shift
738 // of the original face. Return false if nothing changes (faceMap
739 // is identity, rotation is 0)
741 (
743  const primitivePatch& pp,
745  labelList& rotation
746 ) const
747 {
748  faceMap.setSize(pp.size());
749  faceMap = -1;
750 
751  rotation.setSize(pp.size());
752  rotation = 0;
753 
754  if (pp.empty())
755  {
756  // No faces, nothing to change.
757  return false;
758  }
759 
760  if (pp.size()&1)
761  {
763  << "Size of cyclic " << name() << " should be a multiple of 2"
764  << ". It is " << pp.size() << abort(FatalError);
765  }
766 
767  label halfSize = pp.size()/2;
768 
769  // Supplied primitivePatch already with new points.
770  // Cyclics are limited to one transformation tensor
771  // currently anyway (i.e. straight plane) so should not be too big a
772  // problem.
773 
774 
775  // Indices of faces on half0
776  labelList half0ToPatch;
777  // Indices of faces on half1
778  labelList half1ToPatch;
779 
780 
781  // 1. Test if already correctly oriented by starting from trivial ordering.
782  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
783 
784  half0ToPatch = identity(halfSize);
785  half1ToPatch = half0ToPatch + halfSize;
786 
787  // Get faces
788  faceList half0Faces(UIndirectList<face>(pp, half0ToPatch));
789  faceList half1Faces(UIndirectList<face>(pp, half1ToPatch));
790 
791  // Get geometric quantities
792  pointField half0Ctrs, half1Ctrs, anchors0, ppPoints;
793  scalarField tols;
794  getCentresAndAnchors
795  (
796  pp,
797  half0Faces,
798  half1Faces,
799 
800  ppPoints,
801  half0Ctrs,
802  half1Ctrs,
803  anchors0,
804  tols
805  );
806 
807  // Geometric match of face centre vectors
808  labelList from1To0;
809  bool matchedAll = matchPoints
810  (
811  half1Ctrs,
812  half0Ctrs,
813  tols,
814  false,
815  from1To0
816  );
817 
818  if (debug)
819  {
820  Pout<< "oldCyclicPolyPatch::order : test if already ordered:"
821  << matchedAll << endl;
822 
823  // Dump halves
824  fileName nm0("match1_"+name()+"_half0_faces.obj");
825  Pout<< "oldCyclicPolyPatch::order : Writing half0"
826  << " faces to OBJ file " << nm0 << endl;
827  writeOBJ(nm0, half0Faces, ppPoints);
828 
829  fileName nm1("match1_"+name()+"_half1_faces.obj");
830  Pout<< "oldCyclicPolyPatch::order : Writing half1"
831  << " faces to OBJ file " << nm1 << endl;
832  writeOBJ(nm1, half1Faces, pp.points());
833 
834  OFstream ccStr
835  (
836  boundaryMesh().mesh().time().path()
837  /"match1_"+ name() + "_faceCentres.obj"
838  );
839  Pout<< "oldCyclicPolyPatch::order : "
840  << "Dumping currently found cyclic match as lines between"
841  << " corresponding face centres to file " << ccStr.name()
842  << endl;
843 
844  // Recalculate untransformed face centres
845  //pointField rawHalf0Ctrs = calcFaceCentres(half0Faces, pp.points());
846  label vertI = 0;
847 
848  forAll(half1Ctrs, i)
849  {
850  //if (from1To0[i] != -1)
851  {
852  // Write edge between c1 and c0
853  //const point& c0 = rawHalf0Ctrs[from1To0[i]];
854  //const point& c0 = half0Ctrs[from1To0[i]];
855  const point& c0 = half0Ctrs[i];
856  const point& c1 = half1Ctrs[i];
857  writeOBJ(ccStr, c0, c1, vertI);
858  }
859  }
860  }
861 
862 
863  // 2. Ordered in pairs (so 0,1 coupled and 2,3 etc.)
864  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
865 
866  if (!matchedAll)
867  {
868  label faceI = 0;
869  for (label i = 0; i < halfSize; i++)
870  {
871  half0ToPatch[i] = faceI++;
872  half1ToPatch[i] = faceI++;
873  }
874 
875  // And redo all matching
876  half0Faces = UIndirectList<face>(pp, half0ToPatch);
877  half1Faces = UIndirectList<face>(pp, half1ToPatch);
878 
879  getCentresAndAnchors
880  (
881  pp,
882  half0Faces,
883  half1Faces,
884 
885  ppPoints,
886  half0Ctrs,
887  half1Ctrs,
888  anchors0,
889  tols
890  );
891 
892  // Geometric match of face centre vectors
893  matchedAll = matchPoints
894  (
895  half1Ctrs,
896  half0Ctrs,
897  tols,
898  false,
899  from1To0
900  );
901 
902  if (debug)
903  {
904  Pout<< "oldCyclicPolyPatch::order : test if pairwise ordered:"
905  << matchedAll << endl;
906  // Dump halves
907  fileName nm0("match2_"+name()+"_half0_faces.obj");
908  Pout<< "oldCyclicPolyPatch::order : Writing half0"
909  << " faces to OBJ file " << nm0 << endl;
910  writeOBJ(nm0, half0Faces, ppPoints);
911 
912  fileName nm1("match2_"+name()+"_half1_faces.obj");
913  Pout<< "oldCyclicPolyPatch::order : Writing half1"
914  << " faces to OBJ file " << nm1 << endl;
915  writeOBJ(nm1, half1Faces, pp.points());
916 
917  OFstream ccStr
918  (
919  boundaryMesh().mesh().time().path()
920  /"match2_"+name()+"_faceCentres.obj"
921  );
922  Pout<< "oldCyclicPolyPatch::order : "
923  << "Dumping currently found cyclic match as lines between"
924  << " corresponding face centres to file " << ccStr.name()
925  << endl;
926 
927  // Recalculate untransformed face centres
928  label vertI = 0;
929 
930  forAll(half1Ctrs, i)
931  {
932  if (from1To0[i] != -1)
933  {
934  // Write edge between c1 and c0
935  const point& c0 = half0Ctrs[from1To0[i]];
936  const point& c1 = half1Ctrs[i];
937  writeOBJ(ccStr, c0, c1, vertI);
938  }
939  }
940  }
941  }
942 
943 
944  // 3. Baffles(coincident faces) converted into cyclics (e.g. jump)
945  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
946 
947  if (!matchedAll)
948  {
949  label baffleI = 0;
950 
951  forAll(pp, faceI)
952  {
953  const face& f = pp.localFaces()[faceI];
954  const labelList& pFaces = pp.pointFaces()[f[0]];
955 
956  label matchedFaceI = -1;
957 
958  forAll(pFaces, i)
959  {
960  label otherFaceI = pFaces[i];
961 
962  if (otherFaceI > faceI)
963  {
964  const face& otherF = pp.localFaces()[otherFaceI];
965 
966  // Note: might pick up two similar oriented faces
967  // (but that is illegal anyway)
968  if (f == otherF)
969  {
970  matchedFaceI = otherFaceI;
971  break;
972  }
973  }
974  }
975 
976  if (matchedFaceI != -1)
977  {
978  half0ToPatch[baffleI] = faceI;
979  half1ToPatch[baffleI] = matchedFaceI;
980  baffleI++;
981  }
982  }
983 
984  if (baffleI == halfSize)
985  {
986  // And redo all matching
987  half0Faces = UIndirectList<face>(pp, half0ToPatch);
988  half1Faces = UIndirectList<face>(pp, half1ToPatch);
989 
990  getCentresAndAnchors
991  (
992  pp,
993  half0Faces,
994  half1Faces,
995 
996  ppPoints,
997  half0Ctrs,
998  half1Ctrs,
999  anchors0,
1000  tols
1001  );
1002 
1003  // Geometric match of face centre vectors
1004  matchedAll = matchPoints
1005  (
1006  half1Ctrs,
1007  half0Ctrs,
1008  tols,
1009  false,
1010  from1To0
1011  );
1012 
1013  if (debug)
1014  {
1015  Pout<< "oldCyclicPolyPatch::order : test if baffles:"
1016  << matchedAll << endl;
1017  // Dump halves
1018  fileName nm0("match3_"+name()+"_half0_faces.obj");
1019  Pout<< "oldCyclicPolyPatch::order : Writing half0"
1020  << " faces to OBJ file " << nm0 << endl;
1021  writeOBJ(nm0, half0Faces, ppPoints);
1022 
1023  fileName nm1("match3_"+name()+"_half1_faces.obj");
1024  Pout<< "oldCyclicPolyPatch::order : Writing half1"
1025  << " faces to OBJ file " << nm1 << endl;
1026  writeOBJ(nm1, half1Faces, pp.points());
1027 
1028  OFstream ccStr
1029  (
1030  boundaryMesh().mesh().time().path()
1031  /"match3_"+ name() + "_faceCentres.obj"
1032  );
1033  Pout<< "oldCyclicPolyPatch::order : "
1034  << "Dumping currently found cyclic match as lines between"
1035  << " corresponding face centres to file " << ccStr.name()
1036  << endl;
1037 
1038  // Recalculate untransformed face centres
1039  label vertI = 0;
1040 
1041  forAll(half1Ctrs, i)
1042  {
1043  if (from1To0[i] != -1)
1044  {
1045  // Write edge between c1 and c0
1046  const point& c0 = half0Ctrs[from1To0[i]];
1047  const point& c1 = half1Ctrs[i];
1048  writeOBJ(ccStr, c0, c1, vertI);
1049  }
1050  }
1051  }
1052  }
1053  }
1054 
1055 
1056  // 4. Automatic geometric ordering
1057  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1058 
1059  if (!matchedAll)
1060  {
1061  // Split faces according to feature angle or topology
1062  bool okSplit = getGeometricHalves(pp, half0ToPatch, half1ToPatch);
1063 
1064  if (!okSplit)
1065  {
1066  // Did not split into two equal parts.
1067  return false;
1068  }
1069 
1070  // And redo all matching
1071  half0Faces = UIndirectList<face>(pp, half0ToPatch);
1072  half1Faces = UIndirectList<face>(pp, half1ToPatch);
1073 
1074  getCentresAndAnchors
1075  (
1076  pp,
1077  half0Faces,
1078  half1Faces,
1079 
1080  ppPoints,
1081  half0Ctrs,
1082  half1Ctrs,
1083  anchors0,
1084  tols
1085  );
1086 
1087  // Geometric match of face centre vectors
1088  matchedAll = matchPoints
1089  (
1090  half1Ctrs,
1091  half0Ctrs,
1092  tols,
1093  false,
1094  from1To0
1095  );
1096 
1097  if (debug)
1098  {
1099  Pout<< "oldCyclicPolyPatch::order : automatic ordering result:"
1100  << matchedAll << endl;
1101  // Dump halves
1102  fileName nm0("match4_"+name()+"_half0_faces.obj");
1103  Pout<< "oldCyclicPolyPatch::order : Writing half0"
1104  << " faces to OBJ file " << nm0 << endl;
1105  writeOBJ(nm0, half0Faces, ppPoints);
1106 
1107  fileName nm1("match4_"+name()+"_half1_faces.obj");
1108  Pout<< "oldCyclicPolyPatch::order : Writing half1"
1109  << " faces to OBJ file " << nm1 << endl;
1110  writeOBJ(nm1, half1Faces, pp.points());
1111 
1112  OFstream ccStr
1113  (
1114  boundaryMesh().mesh().time().path()
1115  /"match4_"+ name() + "_faceCentres.obj"
1116  );
1117  Pout<< "oldCyclicPolyPatch::order : "
1118  << "Dumping currently found cyclic match as lines between"
1119  << " corresponding face centres to file " << ccStr.name()
1120  << endl;
1121 
1122  // Recalculate untransformed face centres
1123  label vertI = 0;
1124 
1125  forAll(half1Ctrs, i)
1126  {
1127  if (from1To0[i] != -1)
1128  {
1129  // Write edge between c1 and c0
1130  const point& c0 = half0Ctrs[from1To0[i]];
1131  const point& c1 = half1Ctrs[i];
1132  writeOBJ(ccStr, c0, c1, vertI);
1133  }
1134  }
1135  }
1136  }
1137 
1138 
1139  if (!matchedAll || debug)
1140  {
1141  // Dump halves
1142  fileName nm0(name()+"_half0_faces.obj");
1143  Pout<< "oldCyclicPolyPatch::order : Writing half0"
1144  << " faces to OBJ file " << nm0 << endl;
1145  writeOBJ(nm0, half0Faces, pp.points());
1146 
1147  fileName nm1(name()+"_half1_faces.obj");
1148  Pout<< "oldCyclicPolyPatch::order : Writing half1"
1149  << " faces to OBJ file " << nm1 << endl;
1150  writeOBJ(nm1, half1Faces, pp.points());
1151 
1152  OFstream ccStr
1153  (
1154  boundaryMesh().mesh().time().path()
1155  /name() + "_faceCentres.obj"
1156  );
1157  Pout<< "oldCyclicPolyPatch::order : "
1158  << "Dumping currently found cyclic match as lines between"
1159  << " corresponding face centres to file " << ccStr.name()
1160  << endl;
1161 
1162  // Recalculate untransformed face centres
1163  //pointField rawHalf0Ctrs = calcFaceCentres(half0Faces, pp.points());
1164  label vertI = 0;
1165 
1166  forAll(half1Ctrs, i)
1167  {
1168  if (from1To0[i] != -1)
1169  {
1170  // Write edge between c1 and c0
1171  //const point& c0 = rawHalf0Ctrs[from1To0[i]];
1172  const point& c0 = half0Ctrs[from1To0[i]];
1173  const point& c1 = half1Ctrs[i];
1174  writeOBJ(ccStr, c0, c1, vertI);
1175  }
1176  }
1177  }
1178 
1179 
1180  if (!matchedAll)
1181  {
1183  << "Patch:" << name() << " : "
1184  << "Cannot match vectors to faces on both sides of patch" << endl
1185  << " Perhaps your faces do not match?"
1186  << " The obj files written contain the current match." << endl
1187  << " Continuing with incorrect face ordering from now on!"
1188  << endl;
1189 
1190  return false;
1191  }
1192 
1193 
1194  // Set faceMap such that half0 faces get first and corresponding half1
1195  // faces last.
1196  matchAnchors
1197  (
1198  true, // report if anchor matching error
1199  pp,
1200  half0ToPatch,
1201  anchors0,
1202  half1ToPatch,
1203  half1Faces,
1204  from1To0,
1205  tols,
1206  faceMap,
1207  rotation
1208  );
1209 
1210  // Return false if no change neccesary, true otherwise.
1211 
1212  forAll(faceMap, faceI)
1213  {
1214  if (faceMap[faceI] != faceI || rotation[faceI] != 0)
1215  {
1216  return true;
1217  }
1218  }
1219 
1220  return false;
1221 }
1222 
1223 
1225 {
1226  // Replacement of polyPatch::write to write 'cyclic' instead of type():
1227  os.writeKeyword("type") << cyclicPolyPatch::typeName
1228  << token::END_STATEMENT << nl;
1230  os.writeKeyword("nFaces") << size() << token::END_STATEMENT << nl;
1231  os.writeKeyword("startFace") << start() << token::END_STATEMENT << nl;
1232 
1233 
1234  os.writeKeyword("featureCos") << featureCos_ << token::END_STATEMENT << nl;
1235  switch (transform())
1236  {
1237  case ROTATIONAL:
1238  {
1239  os.writeKeyword("rotationAxis") << rotationAxis_
1240  << token::END_STATEMENT << nl;
1241  os.writeKeyword("rotationCentre") << rotationCentre_
1242  << token::END_STATEMENT << nl;
1243  break;
1244  }
1245  case TRANSLATIONAL:
1246  {
1247  os.writeKeyword("separationVector") << separationVector_
1248  << token::END_STATEMENT << nl;
1249  break;
1250  }
1251  default:
1252  {
1253  // no additional info to write
1254  }
1255  }
1256 
1258  << "Please run foamUpgradeCyclics to convert these old-style"
1259  << " cyclics into two separate cyclics patches."
1260  << endl;
1261 }
1262 
1263 
1264 // ************************************************************************* //
Foam::oldCyclicPolyPatch::updateMesh
virtual void updateMesh(PstreamBuffers &)
Update of the patch topology.
Definition: oldCyclicPolyPatch.C:722
Foam::Tensor
Templated 3D tensor derived from VectorSpace adding construction from 9 components,...
Definition: complexI.H:224
Foam::token::END_STATEMENT
@ END_STATEMENT
Definition: token.H:99
Foam::PrimitivePatch::pointFaces
const labelListList & pointFaces() const
Return point-face addressing.
Definition: PrimitivePatchTemplate.C:352
Foam::faceMap
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Definition: blockMeshMergeFast.C:90
Foam::PrimitivePatch::points
const Field< PointType > & points() const
Return reference to global points.
Definition: PrimitivePatchTemplate.H:282
Foam::PrimitivePatch::edgeFaces
const labelListList & edgeFaces() const
Return edge-face addressing.
Definition: PrimitivePatchTemplate.C:292
Foam::oldCyclicPolyPatch::initGeometry
virtual void initGeometry(PstreamBuffers &)
Initialise the calculation of the patch geometry.
Definition: oldCyclicPolyPatch.C:673
p
p
Definition: pEqn.H:62
Foam::word
A class for handling words, derived from string.
Definition: word.H:59
Foam::oldCyclicPolyPatch::write
virtual void write(Ostream &) const
Write the polyPatch data as a dictionary.
Definition: oldCyclicPolyPatch.C:1224
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
Foam::polyPatch::movePoints
virtual void movePoints(PstreamBuffers &, const pointField &p)
Correct patches after moving points.
Definition: polyPatch.C:57
Foam::polyBoundaryMesh
Foam::polyBoundaryMesh.
Definition: polyBoundaryMesh.H:60
cyclicPolyPatch.H
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
writeOBJ
void writeOBJ(Ostream &os, label &vertI, const tetPoints &tet)
Definition: Test-tetTetOverlap.C:38
Foam::oldCyclicPolyPatch::movePoints
virtual void movePoints(PstreamBuffers &, const pointField &)
Correct patches after moving points.
Definition: oldCyclicPolyPatch.C:707
Foam::oldCyclicPolyPatch::rotationAxis_
vector rotationAxis_
Axis of rotation for rotational cyclics.
Definition: oldCyclicPolyPatch.H:66
Foam::addToRunTimeSelectionTable
addToRunTimeSelectionTable(ensightPart, ensightPartCells, istream)
demandDrivenData.H
Template functions to aid in the implementation of demand driven data.
Foam::PrimitivePatch::localPoints
const Field< PointType > & localPoints() const
Return pointField of points in patch.
Definition: PrimitivePatchTemplate.C:432
Foam::oldCyclicPolyPatch::matchAnchors
bool matchAnchors(const bool report, const primitivePatch &, const labelList &, const pointField &, const labelList &, const faceList &, const labelList &, const scalarField &, labelList &faceMap, labelList &rotation) const
Given matched faces matches the anchor point. Sets faceMap,.
Definition: oldCyclicPolyPatch.C:435
Foam::PrimitivePatch::nEdges
label nEdges() const
Return number of edges in patch.
Definition: PrimitivePatchTemplate.H:299
Foam::PstreamBuffers
Buffers for inter-processor communications streams (UOPstream, UIPstream).
Definition: PstreamBuffers.H:85
Foam::FatalIOError
IOerror FatalIOError
Foam::oldCyclicPolyPatch::initMovePoints
virtual void initMovePoints(PstreamBuffers &, const pointField &)
Initialise the patches for moving points.
Definition: oldCyclicPolyPatch.C:697
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Foam::coupledPolyPatch
The coupledPolyPatch is an abstract base class for patches that couple regions of the computational d...
Definition: coupledPolyPatch.H:51
Foam::patchZones
Calculates zone number for every face of patch.
Definition: patchZones.H:53
Foam::mag
dimensioned< scalar > mag(const dimensioned< Type > &)
polyMesh.H
Foam::polyPatch::updateMesh
virtual void updateMesh(PstreamBuffers &)
Update of the patch topology.
Definition: polyPatch.C:62
Foam::transform
dimensionSet transform(const dimensionSet &)
Definition: dimensionSet.C:465
Foam::patchZones::nZones
label nZones() const
Number of zones.
Definition: patchZones.H:103
Foam::oldCyclicPolyPatch::~oldCyclicPolyPatch
virtual ~oldCyclicPolyPatch()
Definition: oldCyclicPolyPatch.C:667
OFstream.H
pFaces
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=*(cellModeller::lookup("hex"));labelList hexLabels(8);label activeCells=0;labelList pointMap(nPoints);forAll(pointMap, i){ pointMap[i]=i;}for(label i=0;i< nPoints;i++){ if(f[i] > 0.0) { hexLabels[0]=i;hexLabels[1]=i1tab[i];hexLabels[2]=i3tab[i1tab[i]];hexLabels[3]=i3tab[i];hexLabels[4]=i8tab[i];hexLabels[5]=i1tab[i8tab[i]];hexLabels[6]=i3tab[i1tab[i8tab[i]]];hexLabels[7]=i3tab[i8tab[i]];cellShapes[activeCells]=cellShape(hex, hexLabels);edgeList edges=cellShapes[activeCells].edges();forAll(edges, ei) { if(edges[ei].mag(points)< SMALL) { label start=pointMap[edges[ei].start()];while(start !=pointMap[start]) { start=pointMap[start];} label end=pointMap[edges[ei].end()];while(end !=pointMap[end]) { end=pointMap[end];} label minLabel=min(start, end);pointMap[start]=pointMap[end]=minLabel;} } cellZoning[activeCells]=idreg[i];activeCells++;}}cellShapes.setSize(activeCells);cellZoning.setSize(activeCells);forAll(cellShapes, celli){ cellShape &cs=cellShapes[celli];forAll(cs, i) { cs[i]=pointMap[cs[i]];} cs.collapse();}label bcIDs[11]={-1, 0, 2, 4, -1, 5, -1, 6, 7, 8, 9};const label nBCs=12;const word *kivaPatchTypes[nBCs]={ &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &symmetryPolyPatch::typeName, &wedgePolyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &symmetryPolyPatch::typeName, &oldCyclicPolyPatch::typeName};enum patchTypeNames{ PISTON, VALVE, LINER, CYLINDERHEAD, AXIS, WEDGE, INFLOW, OUTFLOW, PRESIN, PRESOUT, SYMMETRYPLANE, CYCLIC};const char *kivaPatchNames[nBCs]={ "piston", "valve", "liner", "cylinderHead", "axis", "wedge", "inflow", "outflow", "presin", "presout", "symmetryPlane", "cyclic"};List< SLList< face > > pFaces[nBCs]
Definition: readKivaGrid.H:235
Foam::oldCyclicPolyPatch::getGeometricHalves
bool getGeometricHalves(const primitivePatch &, labelList &, labelList &) const
Find the two parts of the faces of pp using feature edges.
Definition: oldCyclicPolyPatch.C:113
oldCyclicPolyPatch.H
Foam::oldCyclicPolyPatch::getCentresAndAnchors
void getCentresAndAnchors(const primitivePatch &, const faceList &half0Faces, const faceList &half1Faces, pointField &ppPoints, pointField &half0Ctrs, pointField &half1Ctrs, pointField &anchors0, scalarField &tols) const
Calculate geometric factors of the two halves.
Definition: oldCyclicPolyPatch.C:289
Foam::oldCyclicPolyPatch::order
virtual bool order(PstreamBuffers &, const primitivePatch &, labelList &faceMap, labelList &rotation) const
Return new ordering for primitivePatch.
Definition: oldCyclicPolyPatch.C:741
Foam::oldCyclicPolyPatch::rotationCentre_
point rotationCentre_
Point on axis of rotation for rotational cyclics.
Definition: oldCyclicPolyPatch.H:69
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:115
Foam::constant::physicoChemical::c1
const dimensionedScalar c1
First radiation constant: default SI units: [W/m2].
Foam::label
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
Foam::Field
Pre-declare SubField and related Field type.
Definition: Field.H:57
Foam::polyPatch::initMovePoints
virtual void initMovePoints(PstreamBuffers &, const pointField &)
Initialise the patches for moving points.
Definition: polyPatch.H:108
Foam::nl
static const char nl
Definition: Ostream.H:260
Foam::Info
messageStream Info
SeriousErrorInFunction
#define SeriousErrorInFunction
Report an error message using Foam::SeriousError.
Definition: messageStream.H:237
Foam::polyPatch::initGeometry
virtual void initGeometry(PstreamBuffers &)
Initialise the calculation of the patch geometry.
Definition: polyPatch.H:100
Foam::oldCyclicPolyPatch::separationVector_
vector separationVector_
Translation vector.
Definition: oldCyclicPolyPatch.H:74
Foam::oldCyclicPolyPatch::featureCos_
scalar featureCos_
Morph:angle between normals of neighbouring faces.
Definition: oldCyclicPolyPatch.H:60
Foam::identity
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:137
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:18
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
Foam::oldCyclicPolyPatch::initOrder
virtual void initOrder(PstreamBuffers &, const primitivePatch &) const
Initialize ordering for primitivePatch. Does not.
Definition: oldCyclicPolyPatch.C:729
Foam::oldCyclicPolyPatch::initUpdateMesh
virtual void initUpdateMesh(PstreamBuffers &)
Initialise the update of the patch topology.
Definition: oldCyclicPolyPatch.C:716
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:131
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
Foam::OFstream
Output to file stream.
Definition: OFstream.H:81
Foam::List::setSize
void setSize(const label)
Reset size of List.
Foam::oldCyclicPolyPatch
'old' style cyclic polyPatch with all faces in single patch. Does ordering but cannot be used to run....
Definition: oldCyclicPolyPatch.H:52
Foam::oldCyclicPolyPatch::calcGeometry
virtual void calcGeometry(PstreamBuffers &)
Calculate the patch geometry.
Definition: oldCyclicPolyPatch.C:692
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:318
Foam::Pout
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
Foam::PrimitivePatch::faceNormals
const Field< PointType > & faceNormals() const
Return face normals for patch.
Definition: PrimitivePatchTemplate.C:520
f
labelList f(nPoints)
Foam::Vector< scalar >
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
Foam::Ostream::writeKeyword
Ostream & writeKeyword(const keyType &)
Write the keyword followed by an appropriate indentation.
Definition: Ostream.C:59
Foam::UList< face >
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:333
path
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
polyBoundaryMesh.H
Foam::PrimitivePatch::localFaces
const List< Face > & localFaces() const
Return patch faces addressing into local point list.
Definition: PrimitivePatchTemplate.C:372
Foam::UIndirectList
A List with indirect addressing.
Definition: fvMatrix.H:106
Foam::boundaryMesh
Addressing for all faces on surface of mesh. Can either be read from polyMesh or from triSurface....
Definition: boundaryMesh.H:59
Foam::PrimitivePatch::calcFaceCentres
void calcFaceCentres() const
Calculate face centres.
Definition: PrimitivePatchMeshData.C:329
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
Foam::oldCyclicPolyPatch::getAnchorPoints
static pointField getAnchorPoints(const UList< face > &, const pointField &)
Get f[0] for all faces.
Definition: oldCyclicPolyPatch.C:68
FatalIOErrorInFunction
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:330
Foam::OFstream::name
const fileName & name() const
Return the name of the stream.
Definition: OFstream.H:118
Foam::List::size
void size(const label)
Override size to be inconsistent with allocated storage.
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:53
Foam::rotationTensor
tensor rotationTensor(const vector &n1, const vector &n2)
Definition: transform.H:46
Foam::coupledPolyPatch::transformType
transformType
Definition: coupledPolyPatch.H:57
Foam::UList::size
label size() const
Return the number of elements in the UList.
Definition: UListI.H:299
transformList.H
Spatial transformation functions for primitive fields.
Foam::oldCyclicPolyPatch::findMaxArea
static label findMaxArea(const pointField &, const faceList &)
Find amongst selected faces the one with the largest area.
Definition: oldCyclicPolyPatch.C:85
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::findIndices
labelList findIndices(const ListType &, typename ListType::const_reference, const label start=0)
Find all occurences of given element. Linear search.
Foam::min
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
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:33
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:259
Foam::oldCyclicPolyPatch::getConsistentRotationFace
label getConsistentRotationFace(const pointField &faceCentres) const
For rotational cases, try to find a unique face on each side.
Definition: oldCyclicPolyPatch.C:517
Foam::patchIdentifier::write
void write(Ostream &) const
Write patchIdentifier as a dictionary.
Definition: patchIdentifier.C:89
Foam::magSqr
dimensioned< scalar > magSqr(const dimensioned< Type > &)
Foam::name
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
normal
A normal distribution model.
Foam::PrimitivePatch
A list of faces which address into the list of points.
Definition: PrimitivePatchTemplate.H:88
Foam::oldCyclicPolyPatch::oldCyclicPolyPatch
oldCyclicPolyPatch(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: oldCyclicPolyPatch.C:565