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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2019 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 "oldCyclicPolyPatch.H"
31 #include "polyBoundaryMesh.H"
32 #include "polyMesh.H"
33 #include "OFstream.H"
34 #include "patchZones.H"
35 #include "matchPoints.H"
36 #include "Time.H"
37 #include "transformList.H"
38 #include "cyclicPolyPatch.H"
39 
40 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
41 
42 namespace Foam
43 {
44  defineTypeNameAndDebug(oldCyclicPolyPatch, 0);
45 
46  addToRunTimeSelectionTable(polyPatch, oldCyclicPolyPatch, word);
47  addToRunTimeSelectionTable(polyPatch, oldCyclicPolyPatch, dictionary);
48 }
49 
50 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
51 
52 Foam::pointField Foam::oldCyclicPolyPatch::calcFaceCentres
53 (
54  const UList<face>& faces,
55  const pointField& points
56 )
57 {
58  pointField ctrs(faces.size());
59 
60  forAll(faces, facei)
61  {
62  ctrs[facei] = faces[facei].centre(points);
63  }
64 
65  return ctrs;
66 }
67 
68 
69 Foam::pointField Foam::oldCyclicPolyPatch::getAnchorPoints
70 (
71  const UList<face>& faces,
72  const pointField& points
73 )
74 {
75  pointField anchors(faces.size());
76 
77  forAll(faces, facei)
78  {
79  anchors[facei] = points[faces[facei][0]];
80  }
81 
82  return anchors;
83 }
84 
85 
86 Foam::label Foam::oldCyclicPolyPatch::findMaxArea
87 (
88  const pointField& points,
89  const faceList& faces
90 )
91 {
92  label maxI = -1;
93  scalar maxAreaSqr = -GREAT;
94 
95  forAll(faces, facei)
96  {
97  scalar areaSqr = magSqr(faces[facei].areaNormal(points));
98 
99  if (maxAreaSqr < areaSqr)
100  {
101  maxAreaSqr = areaSqr;
102  maxI = facei;
103  }
104  }
105  return maxI;
106 }
107 
108 
109 bool Foam::oldCyclicPolyPatch::getGeometricHalves
110 (
111  const primitivePatch& pp,
112  labelList& half0ToPatch,
113  labelList& half1ToPatch
114 ) const
115 {
116  // Get geometric zones of patch by looking at normals.
117  // Method 1: any edge with sharpish angle is edge between two halves.
118  // (this will handle e.g. wedge geometries).
119  // Also two fully disconnected regions will be handled this way.
120  // Method 2: sort faces into two halves based on face normal.
121 
122  // Calculate normals
123  const vectorField& faceNormals = pp.faceNormals();
124 
125  // Find edges with sharp angles.
126  boolList regionEdge(pp.nEdges(), false);
127 
128  const labelListList& edgeFaces = pp.edgeFaces();
129 
130  label nRegionEdges = 0;
131 
132  forAll(edgeFaces, edgeI)
133  {
134  const labelList& eFaces = edgeFaces[edgeI];
135 
136  // Check manifold edges for sharp angle.
137  // (Non-manifold already handled by patchZones)
138  if (eFaces.size() == 2)
139  {
140  if ((faceNormals[eFaces[0]] & faceNormals[eFaces[1]])< featureCos_)
141  {
142  regionEdge[edgeI] = true;
143 
144  nRegionEdges++;
145  }
146  }
147  }
148 
149 
150  // For every face determine zone it is connected to (without crossing
151  // any regionEdge)
152  patchZones ppZones(pp, regionEdge);
153 
154  if (debug)
155  {
156  Pout<< "oldCyclicPolyPatch::getGeometricHalves : "
157  << "Found " << nRegionEdges << " edges on patch " << name()
158  << " where the cos of the angle between two connected faces"
159  << " was less than " << featureCos_ << nl
160  << "Patch divided by these and by single sides edges into "
161  << ppZones.nZones() << " parts." << endl;
162 
163 
164  // Dumping zones to obj files.
165 
166  labelList nZoneFaces(ppZones.nZones());
167 
168  for (label zoneI = 0; zoneI < ppZones.nZones(); zoneI++)
169  {
170  OFstream stream
171  (
172  boundaryMesh().mesh().time().path()
173  /name()+"_zone_"+Foam::name(zoneI)+".obj"
174  );
175  Pout<< "oldCyclicPolyPatch::getGeometricHalves : Writing zone "
176  << zoneI << " face centres to OBJ file " << stream.name()
177  << endl;
178 
179  labelList zoneFaces(findIndices(ppZones, zoneI));
180 
181  forAll(zoneFaces, i)
182  {
183  writeOBJ(stream, pp[zoneFaces[i]].centre(pp.points()));
184  }
185 
186  nZoneFaces[zoneI] = zoneFaces.size();
187  }
188  }
189 
190 
191  if (ppZones.nZones() == 2)
192  {
193  half0ToPatch = findIndices(ppZones, 0);
194  half1ToPatch = findIndices(ppZones, 1);
195  }
196  else
197  {
198  if (debug)
199  {
200  Pout<< "oldCyclicPolyPatch::getGeometricHalves :"
201  << " falling back to face-normal comparison" << endl;
202  }
203  label n0Faces = 0;
204  half0ToPatch.setSize(pp.size());
205 
206  label n1Faces = 0;
207  half1ToPatch.setSize(pp.size());
208 
209  // Compare to face 0 normal.
210  forAll(faceNormals, facei)
211  {
212  if ((faceNormals[facei] & faceNormals[0]) > 0)
213  {
214  half0ToPatch[n0Faces++] = facei;
215  }
216  else
217  {
218  half1ToPatch[n1Faces++] = facei;
219  }
220  }
221  half0ToPatch.setSize(n0Faces);
222  half1ToPatch.setSize(n1Faces);
223 
224  if (debug)
225  {
226  Pout<< "oldCyclicPolyPatch::getGeometricHalves :"
227  << " Number of faces per zone:("
228  << n0Faces << ' ' << n1Faces << ')' << endl;
229  }
230  }
231 
232  if (half0ToPatch.size() != half1ToPatch.size())
233  {
234  fileName casePath(boundaryMesh().mesh().time().path());
235 
236  // Dump halves
237  {
238  fileName nm0(casePath/name()+"_half0_faces.obj");
239  Pout<< "oldCyclicPolyPatch::getGeometricHalves : Writing half0"
240  << " faces to OBJ file " << nm0 << endl;
241  writeOBJ(nm0, UIndirectList<face>(pp, half0ToPatch)(), pp.points());
242 
243  fileName nm1(casePath/name()+"_half1_faces.obj");
244  Pout<< "oldCyclicPolyPatch::getGeometricHalves : Writing half1"
245  << " faces to OBJ file " << nm1 << endl;
246  writeOBJ(nm1, UIndirectList<face>(pp, half1ToPatch)(), pp.points());
247  }
248 
249  // Dump face centres
250  {
251  OFstream str0(casePath/name()+"_half0.obj");
252  Pout<< "oldCyclicPolyPatch::getGeometricHalves : Writing half0"
253  << " face centres to OBJ file " << str0.name() << endl;
254 
255  forAll(half0ToPatch, i)
256  {
257  writeOBJ(str0, pp[half0ToPatch[i]].centre(pp.points()));
258  }
259 
260  OFstream str1(casePath/name()+"_half1.obj");
261  Pout<< "oldCyclicPolyPatch::getGeometricHalves : Writing half1"
262  << " face centres to OBJ file " << str1.name() << endl;
263  forAll(half1ToPatch, i)
264  {
265  writeOBJ(str1, pp[half1ToPatch[i]].centre(pp.points()));
266  }
267  }
268 
270  << "Patch " << name() << " gets decomposed in two zones of"
271  << "inequal size: " << half0ToPatch.size()
272  << " and " << half1ToPatch.size() << endl
273  << "This means that the patch is either not two separate regions"
274  << " or one region where the angle between the different regions"
275  << " is not sufficiently sharp." << endl
276  << "Please adapt the featureCos setting." << endl
277  << "Continuing with incorrect face ordering from now on!" << endl;
278 
279  return false;
280  }
281 
282  return true;
283 }
284 
285 
286 void Foam::oldCyclicPolyPatch::getCentresAndAnchors
287 (
288  const primitivePatch& pp,
289  const faceList& half0Faces,
290  const faceList& half1Faces,
291 
292  pointField& ppPoints,
293  pointField& half0Ctrs,
294  pointField& half1Ctrs,
295  pointField& anchors0,
296  scalarField& tols
297 ) const
298 {
299  // Get geometric data on both halves.
300  half0Ctrs = calcFaceCentres(half0Faces, pp.points());
301  anchors0 = getAnchorPoints(half0Faces, pp.points());
302  half1Ctrs = calcFaceCentres(half1Faces, pp.points());
303 
304  switch (transform())
305  {
306  case ROTATIONAL:
307  {
308  label face0 = getConsistentRotationFace(half0Ctrs);
309  label face1 = getConsistentRotationFace(half1Ctrs);
310 
311  const vector n0 =
312  normalised
313  (
314  (half0Ctrs[face0] - rotationCentre_) ^ rotationAxis_
315  );
316 
317  const vector n1 =
318  normalised
319  (
320  (half1Ctrs[face1] - rotationCentre_) ^ -rotationAxis_
321  );
322 
323  if (debug)
324  {
325  Pout<< "oldCyclicPolyPatch::getCentresAndAnchors :"
326  << " Specified rotation :"
327  << " n0:" << n0 << " n1:" << n1 << endl;
328  }
329 
330  // Rotation (around origin)
331  const tensor reverseT(rotationTensor(n0, -n1));
332 
333  // Rotation
334  forAll(half0Ctrs, facei)
335  {
336  half0Ctrs[facei] = Foam::transform(reverseT, half0Ctrs[facei]);
337  anchors0[facei] = Foam::transform(reverseT, anchors0[facei]);
338  }
339 
340  ppPoints = Foam::transform(reverseT, pp.points());
341 
342  break;
343  }
344  //- Problem: usually specified translation is not accurate enough
345  //- To get proper match so keep automatic determination over here.
346  //case TRANSLATIONAL:
347  //{
348  // // Transform 0 points.
349  //
350  // if (debug)
351  // {
352  // Pout<< "oldCyclicPolyPatch::getCentresAndAnchors :"
353  // << "Specified translation : " << separationVector_
354  // << endl;
355  // }
356  //
357  // half0Ctrs += separationVector_;
358  // anchors0 += separationVector_;
359  // break;
360  //}
361  default:
362  {
363  // Assumes that cyclic is planar. This is also the initial
364  // condition for patches without faces.
365 
366  // Determine the face with max area on both halves. These
367  // two faces are used to determine the transformation tensors
368  label max0I = findMaxArea(pp.points(), half0Faces);
369  const vector n0 = half0Faces[max0I].unitNormal(pp.points());
370 
371  label max1I = findMaxArea(pp.points(), half1Faces);
372  const vector n1 = half1Faces[max1I].unitNormal(pp.points());
373 
374  if (mag(n0 & n1) < 1-matchTolerance())
375  {
376  if (debug)
377  {
378  Pout<< "oldCyclicPolyPatch::getCentresAndAnchors :"
379  << " Detected rotation :"
380  << " n0:" << n0 << " n1:" << n1 << endl;
381  }
382 
383  // Rotation (around origin)
384  const tensor reverseT(rotationTensor(n0, -n1));
385 
386  // Rotation
387  forAll(half0Ctrs, facei)
388  {
389  half0Ctrs[facei] = Foam::transform
390  (
391  reverseT,
392  half0Ctrs[facei]
393  );
394  anchors0[facei] = Foam::transform
395  (
396  reverseT,
397  anchors0[facei]
398  );
399  }
400  ppPoints = Foam::transform(reverseT, pp.points());
401  }
402  else
403  {
404  // Parallel translation. Get average of all used points.
405 
406  primitiveFacePatch half0(half0Faces, pp.points());
407  const pointField& half0Pts = half0.localPoints();
408  const point ctr0(sum(half0Pts)/half0Pts.size());
409 
410  primitiveFacePatch half1(half1Faces, pp.points());
411  const pointField& half1Pts = half1.localPoints();
412  const point ctr1(sum(half1Pts)/half1Pts.size());
413 
414  if (debug)
415  {
416  Pout<< "oldCyclicPolyPatch::getCentresAndAnchors :"
417  << " Detected translation :"
418  << " n0:" << n0 << " n1:" << n1
419  << " ctr0:" << ctr0 << " ctr1:" << ctr1 << endl;
420  }
421 
422  half0Ctrs += ctr1 - ctr0;
423  anchors0 += ctr1 - ctr0;
424  ppPoints = pp.points() + ctr1 - ctr0;
425  }
426  break;
427  }
428  }
429 
430 
431  // Calculate typical distance per face
432  tols = matchTolerance()*calcFaceTol(half1Faces, pp.points(), half1Ctrs);
433 }
434 
435 
436 bool Foam::oldCyclicPolyPatch::matchAnchors
437 (
438  const bool report,
439  const primitivePatch& pp,
440  const labelList& half0ToPatch,
441  const pointField& anchors0,
442 
443  const labelList& half1ToPatch,
444  const faceList& half1Faces,
445  const labelList& from1To0,
446 
447  const scalarField& tols,
448 
450  labelList& rotation
451 ) const
452 {
453  // Set faceMap such that half0 faces get first and corresponding half1
454  // faces last.
455 
456  forAll(half0ToPatch, half0Facei)
457  {
458  // Label in original patch
459  label patchFacei = half0ToPatch[half0Facei];
460 
461  faceMap[patchFacei] = half0Facei;
462 
463  // No rotation
464  rotation[patchFacei] = 0;
465  }
466 
467  bool fullMatch = true;
468 
469  forAll(from1To0, half1Facei)
470  {
471  label patchFacei = half1ToPatch[half1Facei];
472 
473  // This face has to match the corresponding one on half0.
474  label half0Facei = from1To0[half1Facei];
475 
476  label newFacei = half0Facei + pp.size()/2;
477 
478  faceMap[patchFacei] = newFacei;
479 
480  // Rotate patchFacei such that its f[0] aligns with that of
481  // the corresponding face
482  // (which after shuffling will be at position half0Facei)
483 
484  const point& wantedAnchor = anchors0[half0Facei];
485 
486  rotation[newFacei] = getRotation
487  (
488  pp.points(),
489  half1Faces[half1Facei],
490  wantedAnchor,
491  tols[half1Facei]
492  );
493 
494  if (rotation[newFacei] == -1)
495  {
496  fullMatch = false;
497 
498  if (report)
499  {
500  const face& f = half1Faces[half1Facei];
502  << "Patch:" << name() << " : "
503  << "Cannot find point on face " << f
504  << " with vertices:"
505  << UIndirectList<point>(pp.points(), f)
506  << " that matches point " << wantedAnchor
507  << " when matching the halves of cyclic patch " << name()
508  << endl
509  << "Continuing with incorrect face ordering from now on!"
510  << endl;
511  }
512  }
513  }
514  return fullMatch;
515 }
516 
517 
518 Foam::label Foam::oldCyclicPolyPatch::getConsistentRotationFace
519 (
520  const pointField& faceCentres
521 ) const
522 {
523  const scalarField magRadSqr
524  (
525  magSqr((faceCentres - rotationCentre_) ^ rotationAxis_)
526  );
527  scalarField axisLen
528  (
529  (faceCentres - rotationCentre_) & rotationAxis_
530  );
531  axisLen = axisLen - min(axisLen);
532  const scalarField magLenSqr
533  (
534  magRadSqr + axisLen*axisLen
535  );
536 
537  label rotFace = -1;
538  scalar maxMagLenSqr = -GREAT;
539  scalar maxMagRadSqr = -GREAT;
540  forAll(faceCentres, i)
541  {
542  if (magLenSqr[i] >= maxMagLenSqr)
543  {
544  if (magRadSqr[i] > maxMagRadSqr)
545  {
546  rotFace = i;
547  maxMagLenSqr = magLenSqr[i];
548  maxMagRadSqr = magRadSqr[i];
549  }
550  }
551  }
552 
553  if (debug)
554  {
555  Info<< "getConsistentRotationFace(const pointField&)" << nl
556  << " rotFace = " << rotFace << nl
557  << " point = " << faceCentres[rotFace] << endl;
558  }
559 
560  return rotFace;
561 }
562 
563 
564 // * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * * * * //
565 
567 (
568  const word& name,
569  const label size,
570  const label start,
571  const label index,
572  const polyBoundaryMesh& bm,
573  const word& patchType,
575 )
576 :
577  coupledPolyPatch(name, size, start, index, bm, patchType, transform),
578  featureCos_(0.9),
579  rotationAxis_(Zero),
580  rotationCentre_(Zero),
581  separationVector_(Zero)
582 {}
583 
584 
586 (
587  const word& name,
588  const dictionary& dict,
589  const label index,
590  const polyBoundaryMesh& bm,
591  const word& patchType
592 )
593 :
594  coupledPolyPatch(name, dict, index, bm, patchType),
595  featureCos_(0.9),
596  rotationAxis_(Zero),
597  rotationCentre_(Zero),
598  separationVector_(Zero)
599 {
600  if (dict.found("neighbourPatch"))
601  {
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.readEntry("rotationAxis", rotationAxis_);
618  dict.readEntry("rotationCentre", rotationCentre_);
619  break;
620  }
621  case TRANSLATIONAL:
622  {
623  dict.readEntry("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 necessary, 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.writeEntry("type", cyclicPolyPatch::typeName);
1229  os.writeEntry("nFaces", size());
1230  os.writeEntry("startFace", start());
1231 
1232 
1233  os.writeEntry("featureCos", featureCos_);
1234  switch (transform())
1235  {
1236  case ROTATIONAL:
1237  {
1238  os.writeEntry("rotationAxis", rotationAxis_);
1239  os.writeEntry("rotationCentre", rotationCentre_);
1240  break;
1241  }
1242  case TRANSLATIONAL:
1243  {
1244  os.writeEntry("separationVector", separationVector_);
1245  break;
1246  }
1247  default:
1248  {
1249  // no additional info to write
1250  }
1251  }
1252 
1254  << "Please run foamUpgradeCyclics to convert these old-style"
1255  << " cyclics into two separate cyclics patches."
1256  << endl;
1257 }
1258 
1259 
1260 // ************************************************************************* //
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::labelList
List< label > labelList
A List of labels.
Definition: List.H:67
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
Foam::oldCyclicPolyPatch::updateMesh
virtual void updateMesh(PstreamBuffers &)
Update of the patch topology.
Definition: oldCyclicPolyPatch.C:722
Foam::scalarField
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Definition: primitiveFieldsFwd.H:52
Foam::PrimitivePatch::pointFaces
const labelListList & pointFaces() const
Return point-face addressing.
Definition: PrimitivePatch.C:301
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::oldCyclicPolyPatch::initGeometry
virtual void initGeometry(PstreamBuffers &)
Initialise the calculation of the patch geometry.
Definition: oldCyclicPolyPatch.C:673
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
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:73
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
cyclicPolyPatch.H
Foam::primitiveFacePatch
PrimitivePatch< List< face >, const pointField & > primitiveFacePatch
A PrimitivePatch with List storage for the faces, const reference for the point field.
Definition: primitiveFacePatch.H:51
Foam::oldCyclicPolyPatch::movePoints
virtual void movePoints(PstreamBuffers &, const pointField &)
Correct patches after moving points.
Definition: oldCyclicPolyPatch.C:707
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::dictionary::found
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Search for an entry (const access) with the given keyword.
Definition: dictionaryI.H:87
Foam::meshTools::writeOBJ
void writeOBJ(Ostream &os, const point &pt)
Write obj representation of a point.
Definition: meshTools.C:203
Foam::PstreamBuffers
Buffers for inter-processor communications streams (UOPstream, UIPstream).
Definition: PstreamBuffers.H:88
Foam::boolList
List< bool > boolList
A List of bools.
Definition: List.H:65
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:369
Foam::coupledPolyPatch
The coupledPolyPatch is an abstract base class for patches that couple regions of the computational d...
Definition: coupledPolyPatch.H:54
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::min
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::oldCyclicPolyPatch::~oldCyclicPolyPatch
virtual ~oldCyclicPolyPatch()
Definition: oldCyclicPolyPatch.C:667
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)
oldCyclicPolyPatch.H
Foam::oldCyclicPolyPatch::order
virtual bool order(PstreamBuffers &, const primitivePatch &, labelList &faceMap, labelList &rotation) const
Return new ordering for primitivePatch.
Definition: oldCyclicPolyPatch.C:741
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].
faceNormals
surfaceVectorField faceNormals(mesh.Sf()/mesh.magSf())
Foam::Field< vector >
Foam::polyPatch::initMovePoints
virtual void initMovePoints(PstreamBuffers &, const pointField &)
Initialise the patches for moving points.
Definition: polyPatch.H:107
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
patchZones.H
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
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::polyPatch::initGeometry
virtual void initGeometry(PstreamBuffers &)
Initialise the calculation of the patch geometry.
Definition: polyPatch.H:99
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
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::oldCyclicPolyPatch::initOrder
virtual void initOrder(PstreamBuffers &, const primitivePatch &) const
Initialize ordering for primitivePatch. Does not.
Definition: oldCyclicPolyPatch.C:729
Foam::PrimitivePatch::localFaces
const List< face_type > & localFaces() const
Return patch faces addressing into local point list.
Definition: PrimitivePatch.C:317
Foam::oldCyclicPolyPatch::initUpdateMesh
virtual void initUpdateMesh(PstreamBuffers &)
Initialise the update of the patch topology.
Definition: oldCyclicPolyPatch.C:716
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::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::OFstream
Output to file stream, using an OSstream.
Definition: OFstream.H:53
Foam::normalised
VectorSpace< Form, Cmpt, Ncmpts > normalised(const VectorSpace< Form, Cmpt, Ncmpts > &vs)
Definition: VectorSpaceI.H:487
Time.H
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
Foam::oldCyclicPolyPatch
'old' style cyclic polyPatch with all faces in single patch. Does ordering but cannot be used to run....
Definition: oldCyclicPolyPatch.H:54
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:453
Foam::nl
constexpr char nl
Definition: Ostream.H:404
f
labelList f(nPoints)
Foam::faceList
List< face > faceList
A List of faces.
Definition: faceListFwd.H:47
Foam::Vector< scalar >
Foam::List< label >
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::identity
labelList identity(const label len, label start=0)
Create identity map of the given length with (map[i] == i)
Definition: labelList.C:38
Foam::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:327
path
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
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::patchIdentifier::write
void write(Ostream &os) const
Definition: patchIdentifier.C:96
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::findIndices
labelList findIndices(const ListType &input, typename ListType::const_reference val, label start=0)
Linear search to find all occurrences of given element.
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
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
transformList.H
Spatial transformation functions for list of values and primitive fields.
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
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::tensor
Tensor< scalar > tensor
Tensor of scalars, i.e. Tensor<scalar>.
Definition: symmTensor.H:61
pFaces
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=cellModel::ref(cellModel::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].reset(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::dictionary::readIfPresent
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:405
Foam::PrimitivePatch
A list of faces which address into the list of points.
Definition: PrimitivePatch.H:79
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:567