Go to the documentation of this file.
32 #include "patchZones.H"
60 ctrs[faceI] = faces[faceI].centre(
points);
77 anchors[faceI] =
points[faces[faceI][0]];
91 scalar maxAreaSqr = -GREAT;
97 if (areaSqr > maxAreaSqr)
127 label nRegionEdges = 0;
131 const labelList& eFaces = edgeFaces[edgeI];
135 if (eFaces.
size() == 2)
137 if ((faceNormals[eFaces[0]] & faceNormals[eFaces[1]])< featureCos_)
139 regionEdge[edgeI] =
true;
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 "
165 for (
label zoneI = 0; zoneI < ppZones.
nZones(); zoneI++)
172 Pout<<
"oldCyclicPolyPatch::getGeometricHalves : Writing zone "
173 << zoneI <<
" face centres to OBJ file " << stream.
name()
183 nZoneFaces[zoneI] = zoneFaces.
size();
188 if (ppZones.
nZones() == 2)
197 Pout<<
"oldCyclicPolyPatch::getGeometricHalves :"
198 <<
" falling back to face-normal comparison" <<
endl;
201 half0ToPatch.
setSize(pp.size());
204 half1ToPatch.
setSize(pp.size());
207 forAll(faceNormals, faceI)
209 if ((faceNormals[faceI] & faceNormals[0]) > 0)
211 half0ToPatch[n0Faces++] = faceI;
215 half1ToPatch[n1Faces++] = faceI;
223 Pout<<
"oldCyclicPolyPatch::getGeometricHalves :"
224 <<
" Number of faces per zone:("
225 << n0Faces <<
' ' << n1Faces <<
')' <<
endl;
229 if (half0ToPatch.
size() != half1ToPatch.
size())
236 Pout<<
"oldCyclicPolyPatch::getGeometricHalves : Writing half0"
237 <<
" faces to OBJ file " << nm0 <<
endl;
241 Pout<<
"oldCyclicPolyPatch::getGeometricHalves : Writing half1"
242 <<
" faces to OBJ file " << nm1 <<
endl;
249 Pout<<
"oldCyclicPolyPatch::getGeometricHalves : Writing half0"
250 <<
" face centres to OBJ file " << str0.
name() <<
endl;
258 Pout<<
"oldCyclicPolyPatch::getGeometricHalves : Writing half1"
259 <<
" face centres to OBJ file " << str1.
name() <<
endl;
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;
302 half0Ctrs = calcFaceCentres(half0Faces, pp.
points());
303 anchors0 = getAnchorPoints(half0Faces, pp.
points());
304 half1Ctrs = calcFaceCentres(half1Faces, pp.
points());
310 label face0 = getConsistentRotationFace(half0Ctrs);
311 label face1 = getConsistentRotationFace(half1Ctrs);
313 vector n0 = ((half0Ctrs[face0] - rotationCentre_) ^ rotationAxis_);
314 vector n1 = ((half1Ctrs[face1] - rotationCentre_) ^ -rotationAxis_);
315 n0 /=
mag(n0) + VSMALL;
316 n1 /=
mag(n1) + VSMALL;
320 Pout<<
"oldCyclicPolyPatch::getCentresAndAnchors :"
321 <<
" Specified rotation :"
322 <<
" n0:" << n0 <<
" n1:" << n1 <<
endl;
363 label max0I = findMaxArea(pp.
points(), half0Faces);
365 n0 /=
mag(n0) + VSMALL;
367 label max1I = findMaxArea(pp.
points(), half1Faces);
369 n1 /=
mag(n1) + VSMALL;
371 if (
mag(n0 & n1) < 1-matchTolerance())
375 Pout<<
"oldCyclicPolyPatch::getCentresAndAnchors :"
376 <<
" Detected rotation :"
377 <<
" n0:" << n0 <<
" n1:" << n1 <<
endl;
405 const point ctr0(
sum(half0Pts)/half0Pts.size());
409 const point ctr1(
sum(half1Pts)/half1Pts.size());
413 Pout<<
"oldCyclicPolyPatch::getCentresAndAnchors :"
414 <<
" Detected translation :"
415 <<
" n0:" << n0 <<
" n1:" << n1
416 <<
" ctr0:" << ctr0 <<
" ctr1:" << ctr1 <<
endl;
419 half0Ctrs += ctr1 - ctr0;
420 anchors0 += ctr1 - ctr0;
421 ppPoints = pp.
points() + ctr1 - ctr0;
429 tols = matchTolerance()*calcFaceTol(half1Faces, pp.
points(), half1Ctrs);
454 forAll(half0ToPatch, half0FaceI)
457 label patchFaceI = half0ToPatch[half0FaceI];
459 faceMap[patchFaceI] = half0FaceI;
462 rotation[patchFaceI] = 0;
465 bool fullMatch =
true;
467 forAll(from1To0, half1FaceI)
469 label patchFaceI = half1ToPatch[half1FaceI];
472 label half0FaceI = from1To0[half1FaceI];
474 label newFaceI = half0FaceI + pp.size()/2;
476 faceMap[patchFaceI] = newFaceI;
482 const point& wantedAnchor = anchors0[half0FaceI];
484 rotation[newFaceI] = getRotation
487 half1Faces[half1FaceI],
492 if (rotation[newFaceI] == -1)
498 const face&
f = half1Faces[half1FaceI];
500 <<
"Patch:" <<
name() <<
" : "
501 <<
"Cannot find point on face " <<
f
504 <<
" that matches point " << wantedAnchor
505 <<
" when matching the halves of cyclic patch " <<
name()
507 <<
"Continuing with incorrect face ordering from now on!"
523 magSqr((faceCentres - rotationCentre_) ^ rotationAxis_)
527 (faceCentres - rotationCentre_) & rotationAxis_
529 axisLen = axisLen -
min(axisLen);
532 magRadSqr + axisLen*axisLen
536 scalar maxMagLenSqr = -GREAT;
537 scalar maxMagRadSqr = -GREAT;
540 if (magLenSqr[i] >= maxMagLenSqr)
542 if (magRadSqr[i] > maxMagRadSqr)
545 maxMagLenSqr = magLenSqr[i];
546 maxMagRadSqr = magRadSqr[i];
553 Info<<
"getConsistentRotationFace(const pointField&)" <<
nl
554 <<
" rotFace = " << rotFace <<
nl
555 <<
" point = " << faceCentres[rotFace] <<
endl;
571 const word& patchType,
577 rotationAxis_(vector::zero),
578 rotationCentre_(point::zero),
579 separationVector_(vector::zero)
589 const word& patchType
594 rotationAxis_(vector::zero),
595 rotationCentre_(point::zero),
596 separationVector_(vector::zero)
598 if (
dict.found(
"neighbourPatch"))
603 ) <<
"Found \"neighbourPatch\" entry when reading cyclic patch "
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"
611 dict.readIfPresent(
"featureCos", featureCos_);
617 dict.lookup(
"rotationAxis") >> rotationAxis_;
618 dict.lookup(
"rotationCentre") >> rotationCentre_;
623 dict.lookup(
"separationVector") >> separationVector_;
763 <<
"Size of cyclic " <<
name() <<
" should be a multiple of 2"
767 label halfSize = pp.size()/2;
785 half1ToPatch = half0ToPatch + halfSize;
792 pointField half0Ctrs, half1Ctrs, anchors0, ppPoints;
820 Pout<<
"oldCyclicPolyPatch::order : test if already ordered:"
821 << matchedAll <<
endl;
825 Pout<<
"oldCyclicPolyPatch::order : Writing half0"
826 <<
" faces to OBJ file " << nm0 <<
endl;
827 writeOBJ(nm0, half0Faces, ppPoints);
830 Pout<<
"oldCyclicPolyPatch::order : Writing half1"
831 <<
" faces to OBJ file " << nm1 <<
endl;
837 /
"match1_"+
name() +
"_faceCentres.obj"
839 Pout<<
"oldCyclicPolyPatch::order : "
840 <<
"Dumping currently found cyclic match as lines between"
841 <<
" corresponding face centres to file " << ccStr.
name()
855 const point& c0 = half0Ctrs[i];
856 const point&
c1 = half1Ctrs[i];
869 for (
label i = 0; i < halfSize; i++)
871 half0ToPatch[i] = faceI++;
872 half1ToPatch[i] = faceI++;
904 Pout<<
"oldCyclicPolyPatch::order : test if pairwise ordered:"
905 << matchedAll <<
endl;
908 Pout<<
"oldCyclicPolyPatch::order : Writing half0"
909 <<
" faces to OBJ file " << nm0 <<
endl;
910 writeOBJ(nm0, half0Faces, ppPoints);
913 Pout<<
"oldCyclicPolyPatch::order : Writing half1"
914 <<
" faces to OBJ file " << nm1 <<
endl;
920 /
"match2_"+
name()+
"_faceCentres.obj"
922 Pout<<
"oldCyclicPolyPatch::order : "
923 <<
"Dumping currently found cyclic match as lines between"
924 <<
" corresponding face centres to file " << ccStr.
name()
932 if (from1To0[i] != -1)
935 const point& c0 = half0Ctrs[from1To0[i]];
936 const point&
c1 = half1Ctrs[i];
956 label matchedFaceI = -1;
962 if (otherFaceI > faceI)
970 matchedFaceI = otherFaceI;
976 if (matchedFaceI != -1)
978 half0ToPatch[baffleI] = faceI;
979 half1ToPatch[baffleI] = matchedFaceI;
984 if (baffleI == halfSize)
1015 Pout<<
"oldCyclicPolyPatch::order : test if baffles:"
1016 << matchedAll <<
endl;
1019 Pout<<
"oldCyclicPolyPatch::order : Writing half0"
1020 <<
" faces to OBJ file " << nm0 <<
endl;
1021 writeOBJ(nm0, half0Faces, ppPoints);
1024 Pout<<
"oldCyclicPolyPatch::order : Writing half1"
1025 <<
" faces to OBJ file " << nm1 <<
endl;
1031 /
"match3_"+
name() +
"_faceCentres.obj"
1033 Pout<<
"oldCyclicPolyPatch::order : "
1034 <<
"Dumping currently found cyclic match as lines between"
1035 <<
" corresponding face centres to file " << ccStr.
name()
1043 if (from1To0[i] != -1)
1046 const point& c0 = half0Ctrs[from1To0[i]];
1047 const point&
c1 = half1Ctrs[i];
1062 bool okSplit = getGeometricHalves(pp, half0ToPatch, half1ToPatch);
1074 getCentresAndAnchors
1099 Pout<<
"oldCyclicPolyPatch::order : automatic ordering result:"
1100 << matchedAll <<
endl;
1103 Pout<<
"oldCyclicPolyPatch::order : Writing half0"
1104 <<
" faces to OBJ file " << nm0 <<
endl;
1105 writeOBJ(nm0, half0Faces, ppPoints);
1108 Pout<<
"oldCyclicPolyPatch::order : Writing half1"
1109 <<
" faces to OBJ file " << nm1 <<
endl;
1115 /
"match4_"+
name() +
"_faceCentres.obj"
1117 Pout<<
"oldCyclicPolyPatch::order : "
1118 <<
"Dumping currently found cyclic match as lines between"
1119 <<
" corresponding face centres to file " << ccStr.
name()
1127 if (from1To0[i] != -1)
1130 const point& c0 = half0Ctrs[from1To0[i]];
1131 const point&
c1 = half1Ctrs[i];
1139 if (!matchedAll || debug)
1143 Pout<<
"oldCyclicPolyPatch::order : Writing half0"
1144 <<
" faces to OBJ file " << nm0 <<
endl;
1148 Pout<<
"oldCyclicPolyPatch::order : Writing half1"
1149 <<
" faces to OBJ file " << nm1 <<
endl;
1155 /
name() +
"_faceCentres.obj"
1157 Pout<<
"oldCyclicPolyPatch::order : "
1158 <<
"Dumping currently found cyclic match as lines between"
1159 <<
" corresponding face centres to file " << ccStr.
name()
1168 if (from1To0[i] != -1)
1172 const point& c0 = half0Ctrs[from1To0[i]];
1173 const point&
c1 = half1Ctrs[i];
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!"
1214 if (
faceMap[faceI] != faceI || rotation[faceI] != 0)
1247 os.
writeKeyword(
"separationVector") << separationVector_
1258 <<
"Please run foamUpgradeCyclics to convert these old-style"
1259 <<
" cyclics into two separate cyclics patches."
virtual void updateMesh(PstreamBuffers &)
Update of the patch topology.
Templated 3D tensor derived from VectorSpace adding construction from 9 components,...
const labelListList & pointFaces() const
Return point-face addressing.
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
const Field< PointType > & points() const
Return reference to global points.
const labelListList & edgeFaces() const
Return edge-face addressing.
virtual void initGeometry(PstreamBuffers &)
Initialise the calculation of the patch geometry.
A class for handling words, derived from string.
virtual void write(Ostream &) const
Write the polyPatch data as a dictionary.
A class for handling file names.
virtual void movePoints(PstreamBuffers &, const pointField &p)
Correct patches after moving points.
#define forAll(list, i)
Loop across all elements in list.
void writeOBJ(Ostream &os, label &vertI, const tetPoints &tet)
virtual void movePoints(PstreamBuffers &, const pointField &)
Correct patches after moving points.
vector rotationAxis_
Axis of rotation for rotational cyclics.
addToRunTimeSelectionTable(ensightPart, ensightPartCells, istream)
Template functions to aid in the implementation of demand driven data.
const Field< PointType > & localPoints() const
Return pointField of points in patch.
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,.
label nEdges() const
Return number of edges in patch.
Buffers for inter-processor communications streams (UOPstream, UIPstream).
virtual void initMovePoints(PstreamBuffers &, const pointField &)
Initialise the patches for moving points.
Ostream & endl(Ostream &os)
Add newline and flush stream.
The coupledPolyPatch is an abstract base class for patches that couple regions of the computational d...
Calculates zone number for every face of patch.
dimensioned< scalar > mag(const dimensioned< Type > &)
virtual void updateMesh(PstreamBuffers &)
Update of the patch topology.
dimensionSet transform(const dimensionSet &)
label nZones() const
Number of zones.
virtual ~oldCyclicPolyPatch()
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]
bool getGeometricHalves(const primitivePatch &, labelList &, labelList &) const
Find the two parts of the faces of pp using feature edges.
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.
virtual bool order(PstreamBuffers &, const primitivePatch &, labelList &faceMap, labelList &rotation) const
Return new ordering for primitivePatch.
point rotationCentre_
Point on axis of rotation for rotational cyclics.
Determine correspondence between points. See below.
virtual void initUpdateMesh(PstreamBuffers &)
Initialise the update of the patch topology.
const dimensionedScalar c1
First radiation constant: default SI units: [W/m2].
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Pre-declare SubField and related Field type.
virtual void initMovePoints(PstreamBuffers &, const pointField &)
Initialise the patches for moving points.
#define SeriousErrorInFunction
Report an error message using Foam::SeriousError.
virtual void initGeometry(PstreamBuffers &)
Initialise the calculation of the patch geometry.
vector separationVector_
Translation vector.
scalar featureCos_
Morph:angle between normals of neighbouring faces.
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
A list of keyword definitions, which are a keyword followed by any number of values (e....
Macros for easy insertion into run-time selection tables.
virtual void initOrder(PstreamBuffers &, const primitivePatch &) const
Initialize ordering for primitivePatch. Does not.
virtual void initUpdateMesh(PstreamBuffers &)
Initialise the update of the patch topology.
errorManip< error > abort(error &err)
errorManipArg< error, int > exit(error &err, const int errNo=1)
void setSize(const label)
Reset size of List.
'old' style cyclic polyPatch with all faces in single patch. Does ordering but cannot be used to run....
virtual void calcGeometry(PstreamBuffers &)
Calculate the patch geometry.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
prefixOSstream Pout(cout, "Pout")
const Field< PointType > & faceNormals() const
Return face normals for patch.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Ostream & writeKeyword(const keyType &)
Write the keyword followed by an appropriate indentation.
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
const List< Face > & localFaces() const
Return patch faces addressing into local point list.
A List with indirect addressing.
Addressing for all faces on surface of mesh. Can either be read from polyMesh or from triSurface....
void calcFaceCentres() const
Calculate face centres.
A face is a list of labels corresponding to mesh vertices.
static pointField getAnchorPoints(const UList< face > &, const pointField &)
Get f[0] for all faces.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
const fileName & name() const
Return the name of the stream.
void size(const label)
Override size to be inconsistent with allocated storage.
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
tensor rotationTensor(const vector &n1, const vector &n2)
label size() const
Return the number of elements in the UList.
static label findMaxArea(const pointField &, const faceList &)
Find amongst selected faces the one with the largest area.
defineTypeNameAndDebug(combustionModel, 0)
labelList findIndices(const ListType &, typename ListType::const_reference, const label start=0)
Find all occurences of given element. Linear search.
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
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.
#define WarningInFunction
Report a warning using Foam::Warning.
label getConsistentRotationFace(const pointField &faceCentres) const
For rotational cases, try to find a unique face on each side.
void write(Ostream &) const
Write patchIdentifier as a dictionary.
dimensioned< scalar > magSqr(const dimensioned< Type > &)
word name(const complex &)
Return a string representation of a complex.
A normal distribution model.
A list of faces which address into the list of points.
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.