1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2004-2011 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
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.
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
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/>.
24 \*---------------------------------------------------------------------------*/
26 #include "oldCyclicPolyPatch.H"
27 #include "addToRunTimeSelectionTable.H"
28 #include "polyBoundaryMesh.H"
30 #include "demandDrivenData.H"
32 #include "patchZones.H"
33 #include "matchPoints.H"
35 #include "transformList.H"
36 #include "cyclicPolyPatch.H"
38 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
42 defineTypeNameAndDebug(oldCyclicPolyPatch, 0);
44 addToRunTimeSelectionTable(polyPatch, oldCyclicPolyPatch, word);
45 addToRunTimeSelectionTable(polyPatch, oldCyclicPolyPatch, dictionary);
48 const char* Foam::NamedEnum
50 Foam::oldCyclicPolyPatch::transformType,
60 const Foam::NamedEnum<Foam::oldCyclicPolyPatch::transformType, 3>
61 Foam::oldCyclicPolyPatch::transformTypeNames;
63 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
65 Foam::pointField Foam::oldCyclicPolyPatch::calcFaceCentres
67 const UList<face>& faces,
68 const pointField& points
71 pointField ctrs(faces.size());
75 ctrs[faceI] = faces[faceI].centre(points);
82 Foam::pointField Foam::oldCyclicPolyPatch::getAnchorPoints
84 const UList<face>& faces,
85 const pointField& points
88 pointField anchors(faces.size());
92 anchors[faceI] = points[faces[faceI][0]];
99 Foam::label Foam::oldCyclicPolyPatch::findMaxArea
101 const pointField& points,
102 const faceList& faces
106 scalar maxAreaSqr = -GREAT;
110 scalar areaSqr = magSqr(faces[faceI].normal(points));
112 if (areaSqr > maxAreaSqr)
114 maxAreaSqr = areaSqr;
122 // Get geometric zones of patch by looking at normals.
123 // Method 1: any edge with sharpish angle is edge between two halves.
124 // (this will handle e.g. wedge geometries).
125 // Also two fully disconnected regions will be handled this way.
126 // Method 2: sort faces into two halves based on face normal.
127 bool Foam::oldCyclicPolyPatch::getGeometricHalves
129 const primitivePatch& pp,
130 labelList& half0ToPatch,
131 labelList& half1ToPatch
135 const vectorField& faceNormals = pp.faceNormals();
137 // Find edges with sharp angles.
138 boolList regionEdge(pp.nEdges(), false);
140 const labelListList& edgeFaces = pp.edgeFaces();
142 label nRegionEdges = 0;
144 forAll(edgeFaces, edgeI)
146 const labelList& eFaces = edgeFaces[edgeI];
148 // Check manifold edges for sharp angle.
149 // (Non-manifold already handled by patchZones)
150 if (eFaces.size() == 2)
152 if ((faceNormals[eFaces[0]] & faceNormals[eFaces[1]])< featureCos_)
154 regionEdge[edgeI] = true;
162 // For every face determine zone it is connected to (without crossing
164 patchZones ppZones(pp, regionEdge);
168 Pout<< "oldCyclicPolyPatch::getGeometricHalves : "
169 << "Found " << nRegionEdges << " edges on patch " << name()
170 << " where the cos of the angle between two connected faces"
171 << " was less than " << featureCos_ << nl
172 << "Patch divided by these and by single sides edges into "
173 << ppZones.nZones() << " parts." << endl;
176 // Dumping zones to obj files.
178 labelList nZoneFaces(ppZones.nZones());
180 for (label zoneI = 0; zoneI < ppZones.nZones(); zoneI++)
184 boundaryMesh().mesh().time().path()
185 /name()+"_zone_"+Foam::name(zoneI)+".obj"
187 Pout<< "oldCyclicPolyPatch::getGeometricHalves : Writing zone "
188 << zoneI << " face centres to OBJ file " << stream.name()
191 labelList zoneFaces(findIndices(ppZones, zoneI));
195 writeOBJ(stream, pp[zoneFaces[i]].centre(pp.points()));
198 nZoneFaces[zoneI] = zoneFaces.size();
203 if (ppZones.nZones() == 2)
205 half0ToPatch = findIndices(ppZones, 0);
206 half1ToPatch = findIndices(ppZones, 1);
212 Pout<< "oldCyclicPolyPatch::getGeometricHalves :"
213 << " falling back to face-normal comparison" << endl;
216 half0ToPatch.setSize(pp.size());
219 half1ToPatch.setSize(pp.size());
221 // Compare to face 0 normal.
222 forAll(faceNormals, faceI)
224 if ((faceNormals[faceI] & faceNormals[0]) > 0)
226 half0ToPatch[n0Faces++] = faceI;
230 half1ToPatch[n1Faces++] = faceI;
233 half0ToPatch.setSize(n0Faces);
234 half1ToPatch.setSize(n1Faces);
238 Pout<< "oldCyclicPolyPatch::getGeometricHalves :"
239 << " Number of faces per zone:("
240 << n0Faces << ' ' << n1Faces << ')' << endl;
244 if (half0ToPatch.size() != half1ToPatch.size())
246 fileName casePath(boundaryMesh().mesh().time().path());
250 fileName nm0(casePath/name()+"_half0_faces.obj");
251 Pout<< "oldCyclicPolyPatch::getGeometricHalves : Writing half0"
252 << " faces to OBJ file " << nm0 << endl;
253 writeOBJ(nm0, UIndirectList<face>(pp, half0ToPatch)(), pp.points());
255 fileName nm1(casePath/name()+"_half1_faces.obj");
256 Pout<< "oldCyclicPolyPatch::getGeometricHalves : Writing half1"
257 << " faces to OBJ file " << nm1 << endl;
258 writeOBJ(nm1, UIndirectList<face>(pp, half1ToPatch)(), pp.points());
263 OFstream str0(casePath/name()+"_half0.obj");
264 Pout<< "oldCyclicPolyPatch::getGeometricHalves : Writing half0"
265 << " face centres to OBJ file " << str0.name() << endl;
267 forAll(half0ToPatch, i)
269 writeOBJ(str0, pp[half0ToPatch[i]].centre(pp.points()));
272 OFstream str1(casePath/name()+"_half1.obj");
273 Pout<< "oldCyclicPolyPatch::getGeometricHalves : Writing half1"
274 << " face centres to OBJ file " << str1.name() << endl;
275 forAll(half1ToPatch, i)
277 writeOBJ(str1, pp[half1ToPatch[i]].centre(pp.points()));
283 "oldCyclicPolyPatch::getGeometricHalves"
284 "(const primitivePatch&, labelList&, labelList&) const"
285 ) << "Patch " << name() << " gets decomposed in two zones of"
286 << "inequal size: " << half0ToPatch.size()
287 << " and " << half1ToPatch.size() << endl
288 << "This means that the patch is either not two separate regions"
289 << " or one region where the angle between the different regions"
290 << " is not sufficiently sharp." << endl
291 << "Please adapt the featureCos setting." << endl
292 << "Continuing with incorrect face ordering from now on!" << endl;
303 // Given a split of faces into left and right half calculate the centres
304 // and anchor points. Transform the left points so they align with the
306 void Foam::oldCyclicPolyPatch::getCentresAndAnchors
308 const primitivePatch& pp,
309 const faceList& half0Faces,
310 const faceList& half1Faces,
312 pointField& ppPoints,
313 pointField& half0Ctrs,
314 pointField& half1Ctrs,
315 pointField& anchors0,
319 // Get geometric data on both halves.
320 half0Ctrs = calcFaceCentres(half0Faces, pp.points());
321 anchors0 = getAnchorPoints(half0Faces, pp.points());
322 half1Ctrs = calcFaceCentres(half1Faces, pp.points());
328 label face0 = getConsistentRotationFace(half0Ctrs);
329 label face1 = getConsistentRotationFace(half1Ctrs);
331 vector n0 = ((half0Ctrs[face0] - rotationCentre_) ^ rotationAxis_);
332 vector n1 = ((half1Ctrs[face1] - rotationCentre_) ^ -rotationAxis_);
333 n0 /= mag(n0) + VSMALL;
334 n1 /= mag(n1) + VSMALL;
338 Pout<< "oldCyclicPolyPatch::getCentresAndAnchors :"
339 << " Specified rotation :"
340 << " n0:" << n0 << " n1:" << n1 << endl;
343 // Rotation (around origin)
344 const tensor reverseT(rotationTensor(n0, -n1));
347 forAll(half0Ctrs, faceI)
349 half0Ctrs[faceI] = Foam::transform(reverseT, half0Ctrs[faceI]);
350 anchors0[faceI] = Foam::transform(reverseT, anchors0[faceI]);
353 ppPoints = Foam::transform(reverseT, pp.points());
357 //- Problem: usually specified translation is not accurate enough
358 //- to get proper match so keep automatic determination over here.
359 //case TRANSLATIONAL:
361 // // Transform 0 points.
365 // Pout<< "oldCyclicPolyPatch::getCentresAndAnchors :"
366 // << "Specified translation : " << separationVector_
370 // half0Ctrs += separationVector_;
371 // anchors0 += separationVector_;
376 // Assumes that cyclic is planar. This is also the initial
377 // condition for patches without faces.
379 // Determine the face with max area on both halves. These
380 // two faces are used to determine the transformation tensors
381 label max0I = findMaxArea(pp.points(), half0Faces);
382 vector n0 = half0Faces[max0I].normal(pp.points());
383 n0 /= mag(n0) + VSMALL;
385 label max1I = findMaxArea(pp.points(), half1Faces);
386 vector n1 = half1Faces[max1I].normal(pp.points());
387 n1 /= mag(n1) + VSMALL;
389 if (mag(n0 & n1) < 1-matchTolerance())
393 Pout<< "oldCyclicPolyPatch::getCentresAndAnchors :"
394 << " Detected rotation :"
395 << " n0:" << n0 << " n1:" << n1 << endl;
398 // Rotation (around origin)
399 const tensor reverseT(rotationTensor(n0, -n1));
402 forAll(half0Ctrs, faceI)
404 half0Ctrs[faceI] = Foam::transform
409 anchors0[faceI] = Foam::transform
415 ppPoints = Foam::transform(reverseT, pp.points());
419 // Parallel translation. Get average of all used points.
421 primitiveFacePatch half0(half0Faces, pp.points());
422 const pointField& half0Pts = half0.localPoints();
423 const point ctr0(sum(half0Pts)/half0Pts.size());
425 primitiveFacePatch half1(half1Faces, pp.points());
426 const pointField& half1Pts = half1.localPoints();
427 const point ctr1(sum(half1Pts)/half1Pts.size());
431 Pout<< "oldCyclicPolyPatch::getCentresAndAnchors :"
432 << " Detected translation :"
433 << " n0:" << n0 << " n1:" << n1
434 << " ctr0:" << ctr0 << " ctr1:" << ctr1 << endl;
437 half0Ctrs += ctr1 - ctr0;
438 anchors0 += ctr1 - ctr0;
439 ppPoints = pp.points() + ctr1 - ctr0;
446 // Calculate typical distance per face
447 tols = calcFaceTol(matchTolerance(), half1Faces, pp.points(), half1Ctrs);
451 // Calculates faceMap and rotation. Returns true if all ok.
452 bool Foam::oldCyclicPolyPatch::matchAnchors
455 const primitivePatch& pp,
456 const labelList& half0ToPatch,
457 const pointField& anchors0,
459 const labelList& half1ToPatch,
460 const faceList& half1Faces,
461 const labelList& from1To0,
463 const scalarField& tols,
469 // Set faceMap such that half0 faces get first and corresponding half1
472 forAll(half0ToPatch, half0FaceI)
474 // Label in original patch
475 label patchFaceI = half0ToPatch[half0FaceI];
477 faceMap[patchFaceI] = half0FaceI;
480 rotation[patchFaceI] = 0;
483 bool fullMatch = true;
485 forAll(from1To0, half1FaceI)
487 label patchFaceI = half1ToPatch[half1FaceI];
489 // This face has to match the corresponding one on half0.
490 label half0FaceI = from1To0[half1FaceI];
492 label newFaceI = half0FaceI + pp.size()/2;
494 faceMap[patchFaceI] = newFaceI;
496 // Rotate patchFaceI such that its f[0] aligns with that of
497 // the corresponding face
498 // (which after shuffling will be at position half0FaceI)
500 const point& wantedAnchor = anchors0[half0FaceI];
502 rotation[newFaceI] = getRotation
505 half1Faces[half1FaceI],
510 if (rotation[newFaceI] == -1)
516 const face& f = half1Faces[half1FaceI];
519 "oldCyclicPolyPatch::matchAnchors(..)"
520 ) << "Patch:" << name() << " : "
521 << "Cannot find point on face " << f
523 << UIndirectList<point>(pp.points(), f)()
524 << " that matches point " << wantedAnchor
525 << " when matching the halves of cyclic patch " << name()
527 << "Continuing with incorrect face ordering from now on!"
536 Foam::label Foam::oldCyclicPolyPatch::getConsistentRotationFace
538 const pointField& faceCentres
541 const scalarField magRadSqr
543 magSqr((faceCentres - rotationCentre_) ^ rotationAxis_)
547 (faceCentres - rotationCentre_) & rotationAxis_
549 axisLen = axisLen - min(axisLen);
550 const scalarField magLenSqr
552 magRadSqr + axisLen*axisLen
556 scalar maxMagLenSqr = -GREAT;
557 scalar maxMagRadSqr = -GREAT;
558 forAll(faceCentres, i)
560 if (magLenSqr[i] >= maxMagLenSqr)
562 if (magRadSqr[i] > maxMagRadSqr)
565 maxMagLenSqr = magLenSqr[i];
566 maxMagRadSqr = magRadSqr[i];
573 Info<< "getConsistentRotationFace(const pointField&)" << nl
574 << " rotFace = " << rotFace << nl
575 << " point = " << faceCentres[rotFace] << endl;
582 // * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * * * * //
584 Foam::oldCyclicPolyPatch::oldCyclicPolyPatch
590 const polyBoundaryMesh& bm
593 coupledPolyPatch(name, size, start, index, bm),
596 rotationAxis_(vector::zero),
597 rotationCentre_(point::zero),
598 separationVector_(vector::zero)
602 Foam::oldCyclicPolyPatch::oldCyclicPolyPatch
605 const dictionary& dict,
607 const polyBoundaryMesh& bm
610 coupledPolyPatch(name, dict, index, bm),
613 rotationAxis_(vector::zero),
614 rotationCentre_(point::zero),
615 separationVector_(vector::zero)
617 if (dict.found("neighbourPatch"))
621 "oldCyclicPolyPatch::oldCyclicPolyPatch\n"
623 " const word& name,\n"
624 " const dictionary& dict,\n"
625 " const label index,\n"
626 " const polyBoundaryMesh& bm\n"
629 ) << "Found \"neighbourPatch\" entry when reading cyclic patch "
631 << "Is this mesh already with split cyclics?" << endl
632 << "If so run a newer version that supports it"
633 << ", if not comment out the \"neighbourPatch\" entry and re-run"
634 << exit(FatalIOError);
637 dict.readIfPresent("featureCos", featureCos_);
639 if (dict.found("transform"))
641 transform_ = transformTypeNames.read(dict.lookup("transform"));
646 dict.lookup("rotationAxis") >> rotationAxis_;
647 dict.lookup("rotationCentre") >> rotationCentre_;
652 dict.lookup("separationVector") >> separationVector_;
657 // no additional info required
664 Foam::oldCyclicPolyPatch::oldCyclicPolyPatch
666 const oldCyclicPolyPatch& pp,
667 const polyBoundaryMesh& bm
670 coupledPolyPatch(pp, bm),
671 featureCos_(pp.featureCos_),
672 transform_(pp.transform_),
673 rotationAxis_(pp.rotationAxis_),
674 rotationCentre_(pp.rotationCentre_),
675 separationVector_(pp.separationVector_)
679 Foam::oldCyclicPolyPatch::oldCyclicPolyPatch
681 const oldCyclicPolyPatch& pp,
682 const polyBoundaryMesh& bm,
688 coupledPolyPatch(pp, bm, index, newSize, newStart),
689 featureCos_(pp.featureCos_),
690 transform_(pp.transform_),
691 rotationAxis_(pp.rotationAxis_),
692 rotationCentre_(pp.rotationCentre_),
693 separationVector_(pp.separationVector_)
697 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
699 Foam::oldCyclicPolyPatch::~oldCyclicPolyPatch()
703 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
705 void Foam::oldCyclicPolyPatch::initGeometry(PstreamBuffers& pBufs)
707 polyPatch::initGeometry(pBufs);
711 void Foam::oldCyclicPolyPatch::calcGeometry
713 const primitivePatch& referPatch,
714 const pointField& thisCtrs,
715 const vectorField& thisAreas,
716 const pointField& thisCc,
717 const pointField& nbrCtrs,
718 const vectorField& nbrAreas,
719 const pointField& nbrCc
724 void Foam::oldCyclicPolyPatch::calcGeometry(PstreamBuffers& pBufs)
728 void Foam::oldCyclicPolyPatch::initMovePoints
730 PstreamBuffers& pBufs,
734 polyPatch::initMovePoints(pBufs, p);
738 void Foam::oldCyclicPolyPatch::movePoints
740 PstreamBuffers& pBufs,
744 polyPatch::movePoints(pBufs, p);
748 void Foam::oldCyclicPolyPatch::initUpdateMesh(PstreamBuffers& pBufs)
750 polyPatch::initUpdateMesh(pBufs);
754 void Foam::oldCyclicPolyPatch::updateMesh(PstreamBuffers& pBufs)
756 polyPatch::updateMesh(pBufs);
760 void Foam::oldCyclicPolyPatch::initOrder
763 const primitivePatch& pp
768 // Return new ordering. Ordering is -faceMap: for every face index
769 // the new face -rotation:for every new face the clockwise shift
770 // of the original face. Return false if nothing changes (faceMap
771 // is identity, rotation is 0)
772 bool Foam::oldCyclicPolyPatch::order
775 const primitivePatch& pp,
780 faceMap.setSize(pp.size());
783 rotation.setSize(pp.size());
788 // No faces, nothing to change.
794 FatalErrorIn("oldCyclicPolyPatch::order(..)")
795 << "Size of cyclic " << name() << " should be a multiple of 2"
796 << ". It is " << pp.size() << abort(FatalError);
799 label halfSize = pp.size()/2;
801 // Supplied primitivePatch already with new points.
802 // Cyclics are limited to one transformation tensor
803 // currently anyway (i.e. straight plane) so should not be too big a
807 // Indices of faces on half0
808 labelList half0ToPatch;
809 // Indices of faces on half1
810 labelList half1ToPatch;
813 // 1. Test if already correctly oriented by starting from trivial ordering.
814 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
816 half0ToPatch = identity(halfSize);
817 half1ToPatch = half0ToPatch + halfSize;
820 faceList half0Faces(UIndirectList<face>(pp, half0ToPatch));
821 faceList half1Faces(UIndirectList<face>(pp, half1ToPatch));
823 // Get geometric quantities
824 pointField half0Ctrs, half1Ctrs, anchors0, ppPoints;
839 // Geometric match of face centre vectors
841 bool matchedAll = matchPoints
852 Pout<< "oldCyclicPolyPatch::order : test if already ordered:"
853 << matchedAll << endl;
856 fileName nm0("match1_"+name()+"_half0_faces.obj");
857 Pout<< "oldCyclicPolyPatch::order : Writing half0"
858 << " faces to OBJ file " << nm0 << endl;
859 writeOBJ(nm0, half0Faces, ppPoints);
861 fileName nm1("match1_"+name()+"_half1_faces.obj");
862 Pout<< "oldCyclicPolyPatch::order : Writing half1"
863 << " faces to OBJ file " << nm1 << endl;
864 writeOBJ(nm1, half1Faces, pp.points());
868 boundaryMesh().mesh().time().path()
869 /"match1_"+ name() + "_faceCentres.obj"
871 Pout<< "oldCyclicPolyPatch::order : "
872 << "Dumping currently found cyclic match as lines between"
873 << " corresponding face centres to file " << ccStr.name()
876 // Recalculate untransformed face centres
877 //pointField rawHalf0Ctrs = calcFaceCentres(half0Faces, pp.points());
882 //if (from1To0[i] != -1)
884 // Write edge between c1 and c0
885 //const point& c0 = rawHalf0Ctrs[from1To0[i]];
886 //const point& c0 = half0Ctrs[from1To0[i]];
887 const point& c0 = half0Ctrs[i];
888 const point& c1 = half1Ctrs[i];
889 writeOBJ(ccStr, c0, c1, vertI);
895 // 2. Ordered in pairs (so 0,1 coupled and 2,3 etc.)
896 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
901 for (label i = 0; i < halfSize; i++)
903 half0ToPatch[i] = faceI++;
904 half1ToPatch[i] = faceI++;
907 // And redo all matching
908 half0Faces = UIndirectList<face>(pp, half0ToPatch);
909 half1Faces = UIndirectList<face>(pp, half1ToPatch);
924 // Geometric match of face centre vectors
925 matchedAll = matchPoints
936 Pout<< "oldCyclicPolyPatch::order : test if pairwise ordered:"
937 << matchedAll << endl;
939 fileName nm0("match2_"+name()+"_half0_faces.obj");
940 Pout<< "oldCyclicPolyPatch::order : Writing half0"
941 << " faces to OBJ file " << nm0 << endl;
942 writeOBJ(nm0, half0Faces, ppPoints);
944 fileName nm1("match2_"+name()+"_half1_faces.obj");
945 Pout<< "oldCyclicPolyPatch::order : Writing half1"
946 << " faces to OBJ file " << nm1 << endl;
947 writeOBJ(nm1, half1Faces, pp.points());
951 boundaryMesh().mesh().time().path()
952 /"match2_"+name()+"_faceCentres.obj"
954 Pout<< "oldCyclicPolyPatch::order : "
955 << "Dumping currently found cyclic match as lines between"
956 << " corresponding face centres to file " << ccStr.name()
959 // Recalculate untransformed face centres
964 if (from1To0[i] != -1)
966 // Write edge between c1 and c0
967 const point& c0 = half0Ctrs[from1To0[i]];
968 const point& c1 = half1Ctrs[i];
969 writeOBJ(ccStr, c0, c1, vertI);
976 // 3. Baffles(coincident faces) converted into cyclics (e.g. jump)
977 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
985 const face& f = pp.localFaces()[faceI];
986 const labelList& pFaces = pp.pointFaces()[f[0]];
988 label matchedFaceI = -1;
992 label otherFaceI = pFaces[i];
994 if (otherFaceI > faceI)
996 const face& otherF = pp.localFaces()[otherFaceI];
998 // Note: might pick up two similar oriented faces
999 // (but that is illegal anyway)
1002 matchedFaceI = otherFaceI;
1008 if (matchedFaceI != -1)
1010 half0ToPatch[baffleI] = faceI;
1011 half1ToPatch[baffleI] = matchedFaceI;
1016 if (baffleI == halfSize)
1018 // And redo all matching
1019 half0Faces = UIndirectList<face>(pp, half0ToPatch);
1020 half1Faces = UIndirectList<face>(pp, half1ToPatch);
1022 getCentresAndAnchors
1035 // Geometric match of face centre vectors
1036 matchedAll = matchPoints
1047 Pout<< "oldCyclicPolyPatch::order : test if baffles:"
1048 << matchedAll << endl;
1050 fileName nm0("match3_"+name()+"_half0_faces.obj");
1051 Pout<< "oldCyclicPolyPatch::order : Writing half0"
1052 << " faces to OBJ file " << nm0 << endl;
1053 writeOBJ(nm0, half0Faces, ppPoints);
1055 fileName nm1("match3_"+name()+"_half1_faces.obj");
1056 Pout<< "oldCyclicPolyPatch::order : Writing half1"
1057 << " faces to OBJ file " << nm1 << endl;
1058 writeOBJ(nm1, half1Faces, pp.points());
1062 boundaryMesh().mesh().time().path()
1063 /"match3_"+ name() + "_faceCentres.obj"
1065 Pout<< "oldCyclicPolyPatch::order : "
1066 << "Dumping currently found cyclic match as lines between"
1067 << " corresponding face centres to file " << ccStr.name()
1070 // Recalculate untransformed face centres
1073 forAll(half1Ctrs, i)
1075 if (from1To0[i] != -1)
1077 // Write edge between c1 and c0
1078 const point& c0 = half0Ctrs[from1To0[i]];
1079 const point& c1 = half1Ctrs[i];
1080 writeOBJ(ccStr, c0, c1, vertI);
1088 // 4. Automatic geometric ordering
1089 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1093 // Split faces according to feature angle or topology
1094 bool okSplit = getGeometricHalves(pp, half0ToPatch, half1ToPatch);
1098 // Did not split into two equal parts.
1102 // And redo all matching
1103 half0Faces = UIndirectList<face>(pp, half0ToPatch);
1104 half1Faces = UIndirectList<face>(pp, half1ToPatch);
1106 getCentresAndAnchors
1119 // Geometric match of face centre vectors
1120 matchedAll = matchPoints
1131 Pout<< "oldCyclicPolyPatch::order : automatic ordering result:"
1132 << matchedAll << endl;
1134 fileName nm0("match4_"+name()+"_half0_faces.obj");
1135 Pout<< "oldCyclicPolyPatch::order : Writing half0"
1136 << " faces to OBJ file " << nm0 << endl;
1137 writeOBJ(nm0, half0Faces, ppPoints);
1139 fileName nm1("match4_"+name()+"_half1_faces.obj");
1140 Pout<< "oldCyclicPolyPatch::order : Writing half1"
1141 << " faces to OBJ file " << nm1 << endl;
1142 writeOBJ(nm1, half1Faces, pp.points());
1146 boundaryMesh().mesh().time().path()
1147 /"match4_"+ name() + "_faceCentres.obj"
1149 Pout<< "oldCyclicPolyPatch::order : "
1150 << "Dumping currently found cyclic match as lines between"
1151 << " corresponding face centres to file " << ccStr.name()
1154 // Recalculate untransformed face centres
1157 forAll(half1Ctrs, i)
1159 if (from1To0[i] != -1)
1161 // Write edge between c1 and c0
1162 const point& c0 = half0Ctrs[from1To0[i]];
1163 const point& c1 = half1Ctrs[i];
1164 writeOBJ(ccStr, c0, c1, vertI);
1171 if (!matchedAll || debug)
1174 fileName nm0(name()+"_half0_faces.obj");
1175 Pout<< "oldCyclicPolyPatch::order : Writing half0"
1176 << " faces to OBJ file " << nm0 << endl;
1177 writeOBJ(nm0, half0Faces, pp.points());
1179 fileName nm1(name()+"_half1_faces.obj");
1180 Pout<< "oldCyclicPolyPatch::order : Writing half1"
1181 << " faces to OBJ file " << nm1 << endl;
1182 writeOBJ(nm1, half1Faces, pp.points());
1186 boundaryMesh().mesh().time().path()
1187 /name() + "_faceCentres.obj"
1189 Pout<< "oldCyclicPolyPatch::order : "
1190 << "Dumping currently found cyclic match as lines between"
1191 << " corresponding face centres to file " << ccStr.name()
1194 // Recalculate untransformed face centres
1195 //pointField rawHalf0Ctrs = calcFaceCentres(half0Faces, pp.points());
1198 forAll(half1Ctrs, i)
1200 if (from1To0[i] != -1)
1202 // Write edge between c1 and c0
1203 //const point& c0 = rawHalf0Ctrs[from1To0[i]];
1204 const point& c0 = half0Ctrs[from1To0[i]];
1205 const point& c1 = half1Ctrs[i];
1206 writeOBJ(ccStr, c0, c1, vertI);
1216 "oldCyclicPolyPatch::order"
1217 "(const primitivePatch&, labelList&, labelList&) const"
1218 ) << "Patch:" << name() << " : "
1219 << "Cannot match vectors to faces on both sides of patch" << endl
1220 << " Perhaps your faces do not match?"
1221 << " The obj files written contain the current match." << endl
1222 << " Continuing with incorrect face ordering from now on!"
1229 // Set faceMap such that half0 faces get first and corresponding half1
1233 true, // report if anchor matching error
1245 // Return false if no change neccesary, true otherwise.
1247 forAll(faceMap, faceI)
1249 if (faceMap[faceI] != faceI || rotation[faceI] != 0)
1259 void Foam::oldCyclicPolyPatch::write(Ostream& os) const
1261 // Replacement of polyPatch::write to write 'cyclic' instead of type():
1262 os.writeKeyword("type") << cyclicPolyPatch::typeName
1263 << token::END_STATEMENT << nl;
1264 patchIdentifier::write(os);
1265 os.writeKeyword("nFaces") << size() << token::END_STATEMENT << nl;
1266 os.writeKeyword("startFace") << start() << token::END_STATEMENT << nl;
1269 os.writeKeyword("featureCos") << featureCos_ << token::END_STATEMENT << nl;
1274 os.writeKeyword("transform") << transformTypeNames[transform_]
1275 << token::END_STATEMENT << nl;
1276 os.writeKeyword("rotationAxis") << rotationAxis_
1277 << token::END_STATEMENT << nl;
1278 os.writeKeyword("rotationCentre") << rotationCentre_
1279 << token::END_STATEMENT << nl;
1284 os.writeKeyword("transform") << transformTypeNames[transform_]
1285 << token::END_STATEMENT << nl;
1286 os.writeKeyword("separationVector") << separationVector_
1287 << token::END_STATEMENT << nl;
1292 // no additional info to write
1296 WarningIn("oldCyclicPolyPatch::write(Ostream& os) const")
1297 << "Please run foamUpgradeCyclics to convert these old-style"
1298 << " cyclics into two separate cyclics patches."
1303 // ************************************************************************* //