diff --git a/applications/utilities/mesh/conversion/fluent3DMeshToFoam/fluent3DMeshToFoam.L b/applications/utilities/mesh/conversion/fluent3DMeshToFoam/fluent3DMeshToFoam.L index 5fd94ef38dde348c9de1d82a08e8ccbb02e13303..6f0f7c976dff5c8215346adf0c726761612fabc1 100644 --- a/applications/utilities/mesh/conversion/fluent3DMeshToFoam/fluent3DMeshToFoam.L +++ b/applications/utilities/mesh/conversion/fluent3DMeshToFoam/fluent3DMeshToFoam.L @@ -43,7 +43,7 @@ Description #include "polyMeshZipUpCells.H" #include "wallPolyPatch.H" #include "symmetryPolyPatch.H" -#include "cyclicPolyPatch.H" +#include "oldCyclicPolyPatch.H" #include "Swap.H" #include "IFstream.H" #include "readHexLabel.H" @@ -900,7 +900,7 @@ int main(int argc, char *argv[]) fluentToFoamType.insert("interface", polyPatch::typeName); fluentToFoamType.insert("internal", polyPatch::typeName); fluentToFoamType.insert("solid", polyPatch::typeName); - fluentToFoamType.insert("fan", cyclicPolyPatch::typeName); + fluentToFoamType.insert("fan", oldCyclicPolyPatch::typeName); fluentToFoamType.insert("radiator", polyPatch::typeName); fluentToFoamType.insert("porous-jump", polyPatch::typeName); diff --git a/applications/utilities/mesh/conversion/kivaToFoam/kivaToFoam.C b/applications/utilities/mesh/conversion/kivaToFoam/kivaToFoam.C index ab764547a3582a9900246754f22ebf967da1a3a5..066fab386f3757c17abc4716ce4a8b0405a9225a 100644 --- a/applications/utilities/mesh/conversion/kivaToFoam/kivaToFoam.C +++ b/applications/utilities/mesh/conversion/kivaToFoam/kivaToFoam.C @@ -41,7 +41,7 @@ Description #include "wallPolyPatch.H" #include "symmetryPolyPatch.H" #include "wedgePolyPatch.H" -#include "cyclicPolyPatch.H" +#include "oldCyclicPolyPatch.H" #include "unitConversion.H" using namespace Foam; diff --git a/applications/utilities/mesh/conversion/kivaToFoam/readKivaGrid.H b/applications/utilities/mesh/conversion/kivaToFoam/readKivaGrid.H index 04b36020ea210bf0e3a5d88e8ea8e8297d2d36e2..1a559559e92509c4273e482d5ce937f9cfd4c083 100644 --- a/applications/utilities/mesh/conversion/kivaToFoam/readKivaGrid.H +++ b/applications/utilities/mesh/conversion/kivaToFoam/readKivaGrid.H @@ -196,7 +196,7 @@ const word* kivaPatchTypes[nBCs] = &polyPatch::typeName, &polyPatch::typeName, &symmetryPolyPatch::typeName, - &cyclicPolyPatch::typeName + &oldCyclicPolyPatch::typeName }; enum patchTypeNames diff --git a/applications/utilities/mesh/conversion/sammToFoam/readBoundary.C b/applications/utilities/mesh/conversion/sammToFoam/readBoundary.C index 53dffd39c6bca64173bc5b5d6f7881e02d9e72ea..d01a114111ab7707bfe4c2569db8bc32fcffe910 100644 --- a/applications/utilities/mesh/conversion/sammToFoam/readBoundary.C +++ b/applications/utilities/mesh/conversion/sammToFoam/readBoundary.C @@ -29,7 +29,7 @@ Description #include "sammMesh.H" #include "Time.H" #include "wallPolyPatch.H" -#include "cyclicPolyPatch.H" +#include "oldCyclicPolyPatch.H" #include "symmetryPolyPatch.H" #include "preservePatchTypes.H" #include "IFstream.H" @@ -208,7 +208,7 @@ void sammMesh::readBoundary() { // incorrect. should be cyclicPatch but this // requires info on connected faces. - patchTypes_[patchLabel] = cyclicPolyPatch::typeName; + patchTypes_[patchLabel] = oldCyclicPolyPatch::typeName; } else { diff --git a/applications/utilities/mesh/conversion/star3ToFoam/readBoundary.C b/applications/utilities/mesh/conversion/star3ToFoam/readBoundary.C index a96ee6e96bb71a7df1ae627caf201cce00339f51..75a18600062522c62dd70f4bc143cea90f9a52c9 100644 --- a/applications/utilities/mesh/conversion/star3ToFoam/readBoundary.C +++ b/applications/utilities/mesh/conversion/star3ToFoam/readBoundary.C @@ -29,7 +29,7 @@ Description #include "starMesh.H" #include "Time.H" #include "wallPolyPatch.H" -#include "cyclicPolyPatch.H" +#include "oldCyclicPolyPatch.H" #include "symmetryPolyPatch.H" #include "preservePatchTypes.H" #include "IFstream.H" @@ -206,7 +206,7 @@ void starMesh::readBoundary() { // incorrect. should be cyclicPatch but this // requires info on connected faces. - patchTypes_[patchLabel] = cyclicPolyPatch::typeName; + patchTypes_[patchLabel] = oldCyclicPolyPatch::typeName; } else { diff --git a/applications/utilities/mesh/manipulation/subsetMesh/Make/options b/applications/utilities/mesh/manipulation/subsetMesh/Make/options index d27c95d033dd5d7b1995c8ff8dc406e35ca1f586..969020c4afaf5d784299462b9e1af282040ba6b4 100644 --- a/applications/utilities/mesh/manipulation/subsetMesh/Make/options +++ b/applications/utilities/mesh/manipulation/subsetMesh/Make/options @@ -4,4 +4,5 @@ EXE_INC = \ EXE_LIBS = \ -lfiniteVolume \ - -lmeshTools + -lmeshTools \ + -lgenericPatchFields diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files index 97513b339d4a3a3ecf513e47f95b365a81a98b06..09fa5faa9468bfbfae097d1f3412e990b8c58ff7 100644 --- a/src/OpenFOAM/Make/files +++ b/src/OpenFOAM/Make/files @@ -346,6 +346,7 @@ $(basicPolyPatches)/generic/genericPolyPatch.C constraintPolyPatches = $(polyPatches)/constraint $(constraintPolyPatches)/cyclic/cyclicPolyPatch.C $(constraintPolyPatches)/cyclicSlip/cyclicSlipPolyPatch.C +$(constraintPolyPatches)/oldCyclic/oldCyclicPolyPatch.C $(constraintPolyPatches)/empty/emptyPolyPatch.C $(constraintPolyPatches)/nonuniformTransformCyclic/nonuniformTransformCyclicPolyPatch.C $(constraintPolyPatches)/processorCyclic/processorCyclicPolyPatch.C diff --git a/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/oldCyclic/oldCyclicPolyPatch.C b/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/oldCyclic/oldCyclicPolyPatch.C new file mode 100644 index 0000000000000000000000000000000000000000..218debfa5b0b0df7e7571e368309a5e2c209f00b --- /dev/null +++ b/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/oldCyclic/oldCyclicPolyPatch.C @@ -0,0 +1,1293 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "oldCyclicPolyPatch.H" +#include "addToRunTimeSelectionTable.H" +#include "polyBoundaryMesh.H" +#include "polyMesh.H" +#include "demandDrivenData.H" +#include "OFstream.H" +#include "patchZones.H" +#include "matchPoints.H" +#include "Time.H" +#include "transformList.H" +#include "cyclicPolyPatch.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + defineTypeNameAndDebug(oldCyclicPolyPatch, 0); + + addToRunTimeSelectionTable(polyPatch, oldCyclicPolyPatch, word); + addToRunTimeSelectionTable(polyPatch, oldCyclicPolyPatch, dictionary); + + +template<> +const char* NamedEnum<oldCyclicPolyPatch::transformType, 3>::names[] = +{ + "unknown", + "rotational", + "translational" +}; + +const NamedEnum<oldCyclicPolyPatch::transformType, 3> + oldCyclicPolyPatch::transformTypeNames; +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +Foam::pointField Foam::oldCyclicPolyPatch::calcFaceCentres +( + const UList<face>& faces, + const pointField& points +) +{ + pointField ctrs(faces.size()); + + forAll(faces, faceI) + { + ctrs[faceI] = faces[faceI].centre(points); + } + + return ctrs; +} + + +Foam::pointField Foam::oldCyclicPolyPatch::getAnchorPoints +( + const UList<face>& faces, + const pointField& points +) +{ + pointField anchors(faces.size()); + + forAll(faces, faceI) + { + anchors[faceI] = points[faces[faceI][0]]; + } + + return anchors; +} + + +Foam::label Foam::oldCyclicPolyPatch::findMaxArea +( + const pointField& points, + const faceList& faces +) +{ + label maxI = -1; + scalar maxAreaSqr = -GREAT; + + forAll(faces, faceI) + { + scalar areaSqr = magSqr(faces[faceI].normal(points)); + + if (areaSqr > maxAreaSqr) + { + maxAreaSqr = areaSqr; + maxI = faceI; + } + } + return maxI; +} + + +// Get geometric zones of patch by looking at normals. +// Method 1: any edge with sharpish angle is edge between two halves. +// (this will handle e.g. wedge geometries). +// Also two fully disconnected regions will be handled this way. +// Method 2: sort faces into two halves based on face normal. +bool Foam::oldCyclicPolyPatch::getGeometricHalves +( + const primitivePatch& pp, + labelList& half0ToPatch, + labelList& half1ToPatch +) const +{ + // Calculate normals + const vectorField& faceNormals = pp.faceNormals(); + + // Find edges with sharp angles. + boolList regionEdge(pp.nEdges(), false); + + const labelListList& edgeFaces = pp.edgeFaces(); + + label nRegionEdges = 0; + + forAll(edgeFaces, edgeI) + { + const labelList& eFaces = edgeFaces[edgeI]; + + // Check manifold edges for sharp angle. + // (Non-manifold already handled by patchZones) + if (eFaces.size() == 2) + { + if ((faceNormals[eFaces[0]] & faceNormals[eFaces[1]])< featureCos_) + { + regionEdge[edgeI] = true; + + nRegionEdges++; + } + } + } + + + // For every face determine zone it is connected to (without crossing + // any regionEdge) + patchZones ppZones(pp, regionEdge); + + if (debug) + { + Pout<< "oldCyclicPolyPatch::getGeometricHalves : " + << "Found " << nRegionEdges << " edges on patch " << name() + << " where the cos of the angle between two connected faces" + << " was less than " << featureCos_ << nl + << "Patch divided by these and by single sides edges into " + << ppZones.nZones() << " parts." << endl; + + + // Dumping zones to obj files. + + labelList nZoneFaces(ppZones.nZones()); + + for (label zoneI = 0; zoneI < ppZones.nZones(); zoneI++) + { + OFstream stream + ( + boundaryMesh().mesh().time().path() + /name()+"_zone_"+Foam::name(zoneI)+".obj" + ); + Pout<< "oldCyclicPolyPatch::getGeometricHalves : Writing zone " + << zoneI << " face centres to OBJ file " << stream.name() + << endl; + + labelList zoneFaces(findIndices(ppZones, zoneI)); + + forAll(zoneFaces, i) + { + writeOBJ(stream, pp[zoneFaces[i]].centre(pp.points())); + } + + nZoneFaces[zoneI] = zoneFaces.size(); + } + } + + + if (ppZones.nZones() == 2) + { + half0ToPatch = findIndices(ppZones, 0); + half1ToPatch = findIndices(ppZones, 1); + } + else + { + if (debug) + { + Pout<< "oldCyclicPolyPatch::getGeometricHalves :" + << " falling back to face-normal comparison" << endl; + } + label n0Faces = 0; + half0ToPatch.setSize(pp.size()); + + label n1Faces = 0; + half1ToPatch.setSize(pp.size()); + + // Compare to face 0 normal. + forAll(faceNormals, faceI) + { + if ((faceNormals[faceI] & faceNormals[0]) > 0) + { + half0ToPatch[n0Faces++] = faceI; + } + else + { + half1ToPatch[n1Faces++] = faceI; + } + } + half0ToPatch.setSize(n0Faces); + half1ToPatch.setSize(n1Faces); + + if (debug) + { + Pout<< "oldCyclicPolyPatch::getGeometricHalves :" + << " Number of faces per zone:(" + << n0Faces << ' ' << n1Faces << ')' << endl; + } + } + + if (half0ToPatch.size() != half1ToPatch.size()) + { + fileName casePath(boundaryMesh().mesh().time().path()); + + // Dump halves + { + fileName nm0(casePath/name()+"_half0_faces.obj"); + Pout<< "oldCyclicPolyPatch::getGeometricHalves : Writing half0" + << " faces to OBJ file " << nm0 << endl; + writeOBJ(nm0, UIndirectList<face>(pp, half0ToPatch)(), pp.points()); + + fileName nm1(casePath/name()+"_half1_faces.obj"); + Pout<< "oldCyclicPolyPatch::getGeometricHalves : Writing half1" + << " faces to OBJ file " << nm1 << endl; + writeOBJ(nm1, UIndirectList<face>(pp, half1ToPatch)(), pp.points()); + } + + // Dump face centres + { + OFstream str0(casePath/name()+"_half0.obj"); + Pout<< "oldCyclicPolyPatch::getGeometricHalves : Writing half0" + << " face centres to OBJ file " << str0.name() << endl; + + forAll(half0ToPatch, i) + { + writeOBJ(str0, pp[half0ToPatch[i]].centre(pp.points())); + } + + OFstream str1(casePath/name()+"_half1.obj"); + Pout<< "oldCyclicPolyPatch::getGeometricHalves : Writing half1" + << " face centres to OBJ file " << str1.name() << endl; + forAll(half1ToPatch, i) + { + writeOBJ(str1, pp[half1ToPatch[i]].centre(pp.points())); + } + } + + SeriousErrorIn + ( + "oldCyclicPolyPatch::getGeometricHalves" + "(const primitivePatch&, labelList&, labelList&) const" + ) << "Patch " << name() << " gets decomposed in two zones of" + << "inequal size: " << half0ToPatch.size() + << " and " << half1ToPatch.size() << endl + << "This means that the patch is either not two separate regions" + << " or one region where the angle between the different regions" + << " is not sufficiently sharp." << endl + << "Please adapt the featureCos setting." << endl + << "Continuing with incorrect face ordering from now on!" << endl; + + return false; + } + else + { + return true; + } +} + + +// Given a split of faces into left and right half calculate the centres +// and anchor points. Transform the left points so they align with the +// right ones. +void Foam::oldCyclicPolyPatch::getCentresAndAnchors +( + const primitivePatch& pp, + const faceList& half0Faces, + const faceList& half1Faces, + + pointField& ppPoints, + pointField& half0Ctrs, + pointField& half1Ctrs, + pointField& anchors0, + scalarField& tols +) const +{ + // Get geometric data on both halves. + half0Ctrs = calcFaceCentres(half0Faces, pp.points()); + anchors0 = getAnchorPoints(half0Faces, pp.points()); + half1Ctrs = calcFaceCentres(half1Faces, pp.points()); + + switch (transform_) + { + case ROTATIONAL: + { + label face0 = getConsistentRotationFace(half0Ctrs); + label face1 = getConsistentRotationFace(half1Ctrs); + + vector n0 = ((half0Ctrs[face0] - rotationCentre_) ^ rotationAxis_); + vector n1 = ((half1Ctrs[face1] - rotationCentre_) ^ -rotationAxis_); + n0 /= mag(n0) + VSMALL; + n1 /= mag(n1) + VSMALL; + + if (debug) + { + Pout<< "oldCyclicPolyPatch::getCentresAndAnchors :" + << " Specified rotation :" + << " n0:" << n0 << " n1:" << n1 << endl; + } + + // Rotation (around origin) + const tensor reverseT(rotationTensor(n0, -n1)); + + // Rotation + forAll(half0Ctrs, faceI) + { + half0Ctrs[faceI] = Foam::transform(reverseT, half0Ctrs[faceI]); + anchors0[faceI] = Foam::transform(reverseT, anchors0[faceI]); + } + + ppPoints = Foam::transform(reverseT, pp.points()); + + break; + } + //- Problem: usually specified translation is not accurate enough + //- to get proper match so keep automatic determination over here. + //case TRANSLATIONAL: + //{ + // // Transform 0 points. + // + // if (debug) + // { + // Pout<< "oldCyclicPolyPatch::getCentresAndAnchors :" + // << "Specified translation : " << separationVector_ + // << endl; + // } + // + // half0Ctrs += separationVector_; + // anchors0 += separationVector_; + // break; + //} + default: + { + // Assumes that cyclic is planar. This is also the initial + // condition for patches without faces. + + // Determine the face with max area on both halves. These + // two faces are used to determine the transformation tensors + label max0I = findMaxArea(pp.points(), half0Faces); + vector n0 = half0Faces[max0I].normal(pp.points()); + n0 /= mag(n0) + VSMALL; + + label max1I = findMaxArea(pp.points(), half1Faces); + vector n1 = half1Faces[max1I].normal(pp.points()); + n1 /= mag(n1) + VSMALL; + + if (mag(n0 & n1) < 1-coupledPolyPatch::matchTol) + { + if (debug) + { + Pout<< "oldCyclicPolyPatch::getCentresAndAnchors :" + << " Detected rotation :" + << " n0:" << n0 << " n1:" << n1 << endl; + } + + // Rotation (around origin) + const tensor reverseT(rotationTensor(n0, -n1)); + + // Rotation + forAll(half0Ctrs, faceI) + { + half0Ctrs[faceI] = Foam::transform + ( + reverseT, + half0Ctrs[faceI] + ); + anchors0[faceI] = Foam::transform + ( + reverseT, + anchors0[faceI] + ); + } + ppPoints = Foam::transform(reverseT, pp.points()); + } + else + { + // Parallel translation. Get average of all used points. + + primitiveFacePatch half0(half0Faces, pp.points()); + const pointField& half0Pts = half0.localPoints(); + const point ctr0(sum(half0Pts)/half0Pts.size()); + + primitiveFacePatch half1(half1Faces, pp.points()); + const pointField& half1Pts = half1.localPoints(); + const point ctr1(sum(half1Pts)/half1Pts.size()); + + if (debug) + { + Pout<< "oldCyclicPolyPatch::getCentresAndAnchors :" + << " Detected translation :" + << " n0:" << n0 << " n1:" << n1 + << " ctr0:" << ctr0 << " ctr1:" << ctr1 << endl; + } + + half0Ctrs += ctr1 - ctr0; + anchors0 += ctr1 - ctr0; + ppPoints = pp.points() + ctr1 - ctr0; + } + break; + } + } + + + // Calculate typical distance per face + tols = calcFaceTol(half1Faces, pp.points(), half1Ctrs); +} + + +// Calculates faceMap and rotation. Returns true if all ok. +bool Foam::oldCyclicPolyPatch::matchAnchors +( + const bool report, + const primitivePatch& pp, + const labelList& half0ToPatch, + const pointField& anchors0, + + const labelList& half1ToPatch, + const faceList& half1Faces, + const labelList& from1To0, + + const scalarField& tols, + + labelList& faceMap, + labelList& rotation +) const +{ + // Set faceMap such that half0 faces get first and corresponding half1 + // faces last. + + forAll(half0ToPatch, half0FaceI) + { + // Label in original patch + label patchFaceI = half0ToPatch[half0FaceI]; + + faceMap[patchFaceI] = half0FaceI; + + // No rotation + rotation[patchFaceI] = 0; + } + + bool fullMatch = true; + + forAll(from1To0, half1FaceI) + { + label patchFaceI = half1ToPatch[half1FaceI]; + + // This face has to match the corresponding one on half0. + label half0FaceI = from1To0[half1FaceI]; + + label newFaceI = half0FaceI + pp.size()/2; + + faceMap[patchFaceI] = newFaceI; + + // Rotate patchFaceI such that its f[0] aligns with that of + // the corresponding face + // (which after shuffling will be at position half0FaceI) + + const point& wantedAnchor = anchors0[half0FaceI]; + + rotation[newFaceI] = getRotation + ( + pp.points(), + half1Faces[half1FaceI], + wantedAnchor, + tols[half1FaceI] + ); + + if (rotation[newFaceI] == -1) + { + fullMatch = false; + + if (report) + { + const face& f = half1Faces[half1FaceI]; + SeriousErrorIn + ( + "oldCyclicPolyPatch::matchAnchors(..)" + ) << "Patch:" << name() << " : " + << "Cannot find point on face " << f + << " with vertices:" + << UIndirectList<point>(pp.points(), f)() + << " that matches point " << wantedAnchor + << " when matching the halves of cyclic patch " << name() + << endl + << "Continuing with incorrect face ordering from now on!" + << endl; + } + } + } + return fullMatch; +} + + +Foam::label Foam::oldCyclicPolyPatch::getConsistentRotationFace +( + const pointField& faceCentres +) const +{ + const scalarField magRadSqr = + magSqr((faceCentres - rotationCentre_) ^ rotationAxis_); + scalarField axisLen = (faceCentres - rotationCentre_) & rotationAxis_; + axisLen = axisLen - min(axisLen); + const scalarField magLenSqr = magRadSqr + axisLen*axisLen; + + label rotFace = -1; + scalar maxMagLenSqr = -GREAT; + scalar maxMagRadSqr = -GREAT; + forAll(faceCentres, i) + { + if (magLenSqr[i] >= maxMagLenSqr) + { + if (magRadSqr[i] > maxMagRadSqr) + { + rotFace = i; + maxMagLenSqr = magLenSqr[i]; + maxMagRadSqr = magRadSqr[i]; + } + } + } + + if (debug) + { + Info<< "getConsistentRotationFace(const pointField&)" << nl + << " rotFace = " << rotFace << nl + << " point = " << faceCentres[rotFace] << endl; + } + + return rotFace; +} + + +// * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * * * * // + +Foam::oldCyclicPolyPatch::oldCyclicPolyPatch +( + const word& name, + const label size, + const label start, + const label index, + const polyBoundaryMesh& bm +) +: + coupledPolyPatch(name, size, start, index, bm), + featureCos_(0.9), + transform_(UNKNOWN), + rotationAxis_(vector::zero), + rotationCentre_(point::zero), + separationVector_(vector::zero) +{} + + +Foam::oldCyclicPolyPatch::oldCyclicPolyPatch +( + const word& name, + const dictionary& dict, + const label index, + const polyBoundaryMesh& bm +) +: + coupledPolyPatch(name, dict, index, bm), + featureCos_(0.9), + transform_(UNKNOWN), + rotationAxis_(vector::zero), + rotationCentre_(point::zero), + separationVector_(vector::zero) +{ + if (dict.found("neighbourPatch")) + { + FatalIOErrorIn + ( + "oldCyclicPolyPatch::oldCyclicPolyPatch\n" + "(\n" + " const word& name,\n" + " const dictionary& dict,\n" + " const label index,\n" + " const polyBoundaryMesh& bm\n" + ")", + dict + ) << "Found \"neighbourPatch\" entry when reading cyclic patch " + << name << endl + << "Is this mesh already with split cyclics?" << endl + << "If so run a newer version that supports it" + << ", if not comment out the \"neighbourPatch\" entry and re-run" + << exit(FatalIOError); + } + + dict.readIfPresent("featureCos", featureCos_); + + if (dict.found("transform")) + { + transform_ = transformTypeNames.read(dict.lookup("transform")); + switch (transform_) + { + case ROTATIONAL: + { + dict.lookup("rotationAxis") >> rotationAxis_; + dict.lookup("rotationCentre") >> rotationCentre_; + break; + } + case TRANSLATIONAL: + { + dict.lookup("separationVector") >> separationVector_; + break; + } + default: + { + // no additional info required + } + } + } +} + + +Foam::oldCyclicPolyPatch::oldCyclicPolyPatch +( + const oldCyclicPolyPatch& pp, + const polyBoundaryMesh& bm +) +: + coupledPolyPatch(pp, bm), + featureCos_(pp.featureCos_), + transform_(pp.transform_), + rotationAxis_(pp.rotationAxis_), + rotationCentre_(pp.rotationCentre_), + separationVector_(pp.separationVector_) +{} + + +Foam::oldCyclicPolyPatch::oldCyclicPolyPatch +( + const oldCyclicPolyPatch& pp, + const polyBoundaryMesh& bm, + const label index, + const label newSize, + const label newStart +) +: + coupledPolyPatch(pp, bm, index, newSize, newStart), + featureCos_(pp.featureCos_), + transform_(pp.transform_), + rotationAxis_(pp.rotationAxis_), + rotationCentre_(pp.rotationCentre_), + separationVector_(pp.separationVector_) +{} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::oldCyclicPolyPatch::~oldCyclicPolyPatch() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::oldCyclicPolyPatch::initGeometry(PstreamBuffers& pBufs) +{ + polyPatch::initGeometry(pBufs); +} + + +void Foam::oldCyclicPolyPatch::calcGeometry +( + const primitivePatch& referPatch, + const UList<point>& thisCtrs, + const UList<point>& thisAreas, + const UList<point>& thisCc, + const UList<point>& nbrCtrs, + const UList<point>& nbrAreas, + const UList<point>& nbrCc +) +{} + + +void Foam::oldCyclicPolyPatch::calcGeometry(PstreamBuffers& pBufs) +{} + + +void Foam::oldCyclicPolyPatch::initMovePoints +( + PstreamBuffers& pBufs, + const pointField& p +) +{ + polyPatch::initMovePoints(pBufs, p); +} + + +void Foam::oldCyclicPolyPatch::movePoints +( + PstreamBuffers& pBufs, + const pointField& p +) +{ + polyPatch::movePoints(pBufs, p); +} + + +void Foam::oldCyclicPolyPatch::initUpdateMesh(PstreamBuffers& pBufs) +{ + polyPatch::initUpdateMesh(pBufs); +} + + +void Foam::oldCyclicPolyPatch::updateMesh(PstreamBuffers& pBufs) +{ + polyPatch::updateMesh(pBufs); +} + + +void Foam::oldCyclicPolyPatch::initOrder +( + PstreamBuffers&, + const primitivePatch& pp +) const +{} + + +// Return new ordering. Ordering is -faceMap: for every face index +// the new face -rotation:for every new face the clockwise shift +// of the original face. Return false if nothing changes (faceMap +// is identity, rotation is 0) +bool Foam::oldCyclicPolyPatch::order +( + PstreamBuffers&, + const primitivePatch& pp, + labelList& faceMap, + labelList& rotation +) const +{ + faceMap.setSize(pp.size()); + faceMap = -1; + + rotation.setSize(pp.size()); + rotation = 0; + + if (pp.empty()) + { + // No faces, nothing to change. + return false; + } + + if (pp.size()&1) + { + FatalErrorIn("oldCyclicPolyPatch::order(..)") + << "Size of cyclic " << name() << " should be a multiple of 2" + << ". It is " << pp.size() << abort(FatalError); + } + + label halfSize = pp.size()/2; + + // Supplied primitivePatch already with new points. + // Cyclics are limited to one transformation tensor + // currently anyway (i.e. straight plane) so should not be too big a + // problem. + + + // Indices of faces on half0 + labelList half0ToPatch; + // Indices of faces on half1 + labelList half1ToPatch; + + + // 1. Test if already correctly oriented by starting from trivial ordering. + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + half0ToPatch = identity(halfSize); + half1ToPatch = half0ToPatch + halfSize; + + // Get faces + faceList half0Faces(UIndirectList<face>(pp, half0ToPatch)); + faceList half1Faces(UIndirectList<face>(pp, half1ToPatch)); + + // Get geometric quantities + pointField half0Ctrs, half1Ctrs, anchors0, ppPoints; + scalarField tols; + getCentresAndAnchors + ( + pp, + half0Faces, + half1Faces, + + ppPoints, + half0Ctrs, + half1Ctrs, + anchors0, + tols + ); + + // Geometric match of face centre vectors + labelList from1To0; + bool matchedAll = matchPoints + ( + half1Ctrs, + half0Ctrs, + tols, + false, + from1To0 + ); + + if (debug) + { + Pout<< "oldCyclicPolyPatch::order : test if already ordered:" + << matchedAll << endl; + + // Dump halves + fileName nm0("match1_"+name()+"_half0_faces.obj"); + Pout<< "oldCyclicPolyPatch::order : Writing half0" + << " faces to OBJ file " << nm0 << endl; + writeOBJ(nm0, half0Faces, ppPoints); + + fileName nm1("match1_"+name()+"_half1_faces.obj"); + Pout<< "oldCyclicPolyPatch::order : Writing half1" + << " faces to OBJ file " << nm1 << endl; + writeOBJ(nm1, half1Faces, pp.points()); + + OFstream ccStr + ( + boundaryMesh().mesh().time().path() + /"match1_"+ name() + "_faceCentres.obj" + ); + Pout<< "oldCyclicPolyPatch::order : " + << "Dumping currently found cyclic match as lines between" + << " corresponding face centres to file " << ccStr.name() + << endl; + + // Recalculate untransformed face centres + //pointField rawHalf0Ctrs = calcFaceCentres(half0Faces, pp.points()); + label vertI = 0; + + forAll(half1Ctrs, i) + { + //if (from1To0[i] != -1) + { + // Write edge between c1 and c0 + //const point& c0 = rawHalf0Ctrs[from1To0[i]]; + //const point& c0 = half0Ctrs[from1To0[i]]; + const point& c0 = half0Ctrs[i]; + const point& c1 = half1Ctrs[i]; + writeOBJ(ccStr, c0, c1, vertI); + } + } + } + + + // 2. Ordered in pairs (so 0,1 coupled and 2,3 etc.) + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + if (!matchedAll) + { + label faceI = 0; + for (label i = 0; i < halfSize; i++) + { + half0ToPatch[i] = faceI++; + half1ToPatch[i] = faceI++; + } + + // And redo all matching + half0Faces = UIndirectList<face>(pp, half0ToPatch); + half1Faces = UIndirectList<face>(pp, half1ToPatch); + + getCentresAndAnchors + ( + pp, + half0Faces, + half1Faces, + + ppPoints, + half0Ctrs, + half1Ctrs, + anchors0, + tols + ); + + // Geometric match of face centre vectors + matchedAll = matchPoints + ( + half1Ctrs, + half0Ctrs, + tols, + false, + from1To0 + ); + + if (debug) + { + Pout<< "oldCyclicPolyPatch::order : test if pairwise ordered:" + << matchedAll << endl; + // Dump halves + fileName nm0("match2_"+name()+"_half0_faces.obj"); + Pout<< "oldCyclicPolyPatch::order : Writing half0" + << " faces to OBJ file " << nm0 << endl; + writeOBJ(nm0, half0Faces, ppPoints); + + fileName nm1("match2_"+name()+"_half1_faces.obj"); + Pout<< "oldCyclicPolyPatch::order : Writing half1" + << " faces to OBJ file " << nm1 << endl; + writeOBJ(nm1, half1Faces, pp.points()); + + OFstream ccStr + ( + boundaryMesh().mesh().time().path() + /"match2_"+name()+"_faceCentres.obj" + ); + Pout<< "oldCyclicPolyPatch::order : " + << "Dumping currently found cyclic match as lines between" + << " corresponding face centres to file " << ccStr.name() + << endl; + + // Recalculate untransformed face centres + label vertI = 0; + + forAll(half1Ctrs, i) + { + if (from1To0[i] != -1) + { + // Write edge between c1 and c0 + const point& c0 = half0Ctrs[from1To0[i]]; + const point& c1 = half1Ctrs[i]; + writeOBJ(ccStr, c0, c1, vertI); + } + } + } + } + + + // 3. Baffles(coincident faces) converted into cyclics (e.g. jump) + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + if (!matchedAll) + { + label baffleI = 0; + + forAll(pp, faceI) + { + const face& f = pp.localFaces()[faceI]; + const labelList& pFaces = pp.pointFaces()[f[0]]; + + label matchedFaceI = -1; + + forAll(pFaces, i) + { + label otherFaceI = pFaces[i]; + + if (otherFaceI > faceI) + { + const face& otherF = pp.localFaces()[otherFaceI]; + + // Note: might pick up two similar oriented faces + // (but that is illegal anyway) + if (f == otherF) + { + matchedFaceI = otherFaceI; + break; + } + } + } + + if (matchedFaceI != -1) + { + half0ToPatch[baffleI] = faceI; + half1ToPatch[baffleI] = matchedFaceI; + baffleI++; + } + } + + if (baffleI == halfSize) + { + // And redo all matching + half0Faces = UIndirectList<face>(pp, half0ToPatch); + half1Faces = UIndirectList<face>(pp, half1ToPatch); + + getCentresAndAnchors + ( + pp, + half0Faces, + half1Faces, + + ppPoints, + half0Ctrs, + half1Ctrs, + anchors0, + tols + ); + + // Geometric match of face centre vectors + matchedAll = matchPoints + ( + half1Ctrs, + half0Ctrs, + tols, + false, + from1To0 + ); + + if (debug) + { + Pout<< "oldCyclicPolyPatch::order : test if baffles:" + << matchedAll << endl; + // Dump halves + fileName nm0("match3_"+name()+"_half0_faces.obj"); + Pout<< "oldCyclicPolyPatch::order : Writing half0" + << " faces to OBJ file " << nm0 << endl; + writeOBJ(nm0, half0Faces, ppPoints); + + fileName nm1("match3_"+name()+"_half1_faces.obj"); + Pout<< "oldCyclicPolyPatch::order : Writing half1" + << " faces to OBJ file " << nm1 << endl; + writeOBJ(nm1, half1Faces, pp.points()); + + OFstream ccStr + ( + boundaryMesh().mesh().time().path() + /"match3_"+ name() + "_faceCentres.obj" + ); + Pout<< "oldCyclicPolyPatch::order : " + << "Dumping currently found cyclic match as lines between" + << " corresponding face centres to file " << ccStr.name() + << endl; + + // Recalculate untransformed face centres + label vertI = 0; + + forAll(half1Ctrs, i) + { + if (from1To0[i] != -1) + { + // Write edge between c1 and c0 + const point& c0 = half0Ctrs[from1To0[i]]; + const point& c1 = half1Ctrs[i]; + writeOBJ(ccStr, c0, c1, vertI); + } + } + } + } + } + + + // 4. Automatic geometric ordering + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + if (!matchedAll) + { + // Split faces according to feature angle or topology + bool okSplit = getGeometricHalves(pp, half0ToPatch, half1ToPatch); + + if (!okSplit) + { + // Did not split into two equal parts. + return false; + } + + // And redo all matching + half0Faces = UIndirectList<face>(pp, half0ToPatch); + half1Faces = UIndirectList<face>(pp, half1ToPatch); + + getCentresAndAnchors + ( + pp, + half0Faces, + half1Faces, + + ppPoints, + half0Ctrs, + half1Ctrs, + anchors0, + tols + ); + + // Geometric match of face centre vectors + matchedAll = matchPoints + ( + half1Ctrs, + half0Ctrs, + tols, + false, + from1To0 + ); + + if (debug) + { + Pout<< "oldCyclicPolyPatch::order : automatic ordering result:" + << matchedAll << endl; + // Dump halves + fileName nm0("match4_"+name()+"_half0_faces.obj"); + Pout<< "oldCyclicPolyPatch::order : Writing half0" + << " faces to OBJ file " << nm0 << endl; + writeOBJ(nm0, half0Faces, ppPoints); + + fileName nm1("match4_"+name()+"_half1_faces.obj"); + Pout<< "oldCyclicPolyPatch::order : Writing half1" + << " faces to OBJ file " << nm1 << endl; + writeOBJ(nm1, half1Faces, pp.points()); + + OFstream ccStr + ( + boundaryMesh().mesh().time().path() + /"match4_"+ name() + "_faceCentres.obj" + ); + Pout<< "oldCyclicPolyPatch::order : " + << "Dumping currently found cyclic match as lines between" + << " corresponding face centres to file " << ccStr.name() + << endl; + + // Recalculate untransformed face centres + label vertI = 0; + + forAll(half1Ctrs, i) + { + if (from1To0[i] != -1) + { + // Write edge between c1 and c0 + const point& c0 = half0Ctrs[from1To0[i]]; + const point& c1 = half1Ctrs[i]; + writeOBJ(ccStr, c0, c1, vertI); + } + } + } + } + + + if (!matchedAll || debug) + { + // Dump halves + fileName nm0(name()+"_half0_faces.obj"); + Pout<< "oldCyclicPolyPatch::order : Writing half0" + << " faces to OBJ file " << nm0 << endl; + writeOBJ(nm0, half0Faces, pp.points()); + + fileName nm1(name()+"_half1_faces.obj"); + Pout<< "oldCyclicPolyPatch::order : Writing half1" + << " faces to OBJ file " << nm1 << endl; + writeOBJ(nm1, half1Faces, pp.points()); + + OFstream ccStr + ( + boundaryMesh().mesh().time().path() + /name() + "_faceCentres.obj" + ); + Pout<< "oldCyclicPolyPatch::order : " + << "Dumping currently found cyclic match as lines between" + << " corresponding face centres to file " << ccStr.name() + << endl; + + // Recalculate untransformed face centres + //pointField rawHalf0Ctrs = calcFaceCentres(half0Faces, pp.points()); + label vertI = 0; + + forAll(half1Ctrs, i) + { + if (from1To0[i] != -1) + { + // Write edge between c1 and c0 + //const point& c0 = rawHalf0Ctrs[from1To0[i]]; + const point& c0 = half0Ctrs[from1To0[i]]; + const point& c1 = half1Ctrs[i]; + writeOBJ(ccStr, c0, c1, vertI); + } + } + } + + + if (!matchedAll) + { + SeriousErrorIn + ( + "oldCyclicPolyPatch::order" + "(const primitivePatch&, labelList&, labelList&) const" + ) << "Patch:" << name() << " : " + << "Cannot match vectors to faces on both sides of patch" << endl + << " Perhaps your faces do not match?" + << " The obj files written contain the current match." << endl + << " Continuing with incorrect face ordering from now on!" + << endl; + + return false; + } + + + // Set faceMap such that half0 faces get first and corresponding half1 + // faces last. + matchAnchors + ( + true, // report if anchor matching error + pp, + half0ToPatch, + anchors0, + half1ToPatch, + half1Faces, + from1To0, + tols, + faceMap, + rotation + ); + + // Return false if no change neccesary, true otherwise. + + forAll(faceMap, faceI) + { + if (faceMap[faceI] != faceI || rotation[faceI] != 0) + { + return true; + } + } + + return false; +} + + +void Foam::oldCyclicPolyPatch::write(Ostream& os) const +{ + // Replacement of polyPatch::write to write 'cyclic' instead of type(): + os.writeKeyword("type") << cyclicPolyPatch::typeName + << token::END_STATEMENT << nl; + patchIdentifier::write(os); + os.writeKeyword("nFaces") << size() << token::END_STATEMENT << nl; + os.writeKeyword("startFace") << start() << token::END_STATEMENT << nl; + + + os.writeKeyword("featureCos") << featureCos_ << token::END_STATEMENT << nl; + switch (transform_) + { + case ROTATIONAL: + { + os.writeKeyword("transform") << transformTypeNames[transform_] + << token::END_STATEMENT << nl; + os.writeKeyword("rotationAxis") << rotationAxis_ + << token::END_STATEMENT << nl; + os.writeKeyword("rotationCentre") << rotationCentre_ + << token::END_STATEMENT << nl; + break; + } + case TRANSLATIONAL: + { + os.writeKeyword("transform") << transformTypeNames[transform_] + << token::END_STATEMENT << nl; + os.writeKeyword("separationVector") << separationVector_ + << token::END_STATEMENT << nl; + break; + } + default: + { + // no additional info to write + } + } + + WarningIn("oldCyclicPolyPatch::write(Ostream& os) const") + << "Please run foamUpgradeCyclics to convert these old-style" + << " cyclics into two separate cyclics patches." + << endl; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/oldCyclic/oldCyclicPolyPatch.H b/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/oldCyclic/oldCyclicPolyPatch.H new file mode 100644 index 0000000000000000000000000000000000000000..f8cfb169c0eaf609da95868c462f9df7b006eda1 --- /dev/null +++ b/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/oldCyclic/oldCyclicPolyPatch.H @@ -0,0 +1,318 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::oldCyclicPolyPatch + +Description + 'old' style cyclic polyPatch with all faces in single patch. Does ordering + but cannot be used to run. Writes 'type cyclic' so foamUpgradeCyclics + can be run afterwards. + Used to get cyclics from mesh converters that assume cyclics in single + patch (e.g. fluent3DMeshToFoam) + +SourceFiles + oldCyclicPolyPatch.C + +\*---------------------------------------------------------------------------*/ + +#ifndef oldCyclicPolyPatch_H +#define oldCyclicPolyPatch_H + +#include "coupledPolyPatch.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class oldCyclicPolyPatch Declaration +\*---------------------------------------------------------------------------*/ + +class oldCyclicPolyPatch +: + public coupledPolyPatch +{ +public: + + enum transformType + { + UNKNOWN, + ROTATIONAL, + TRANSLATIONAL + }; + static const NamedEnum<transformType, 3> transformTypeNames; + + +private: + + // Private data + + //- Morph:angle between normals of neighbouring faces. + // Used to split cyclic into halves. + scalar featureCos_; + + //- Type of transformation - rotational or translational + transformType transform_; + + // For rotation + + //- Axis of rotation for rotational cyclics + vector rotationAxis_; + + //- point on axis of rotation for rotational cyclics + point rotationCentre_; + + // For translation + + //- Translation vector + vector separationVector_; + + + // Private member functions + + //- Find amongst selected faces the one with the largest area + static label findMaxArea(const pointField&, const faceList&); + + void calcTransforms(); + + //- Calculate face centres + static pointField calcFaceCentres + ( + const UList<face>&, + const pointField& + ); + + //- Get f[0] for all faces + static pointField getAnchorPoints + ( + const UList<face>&, + const pointField& + ); + + // Face ordering + + //- Find the two parts of the faces of pp using feature edges. + // Returns true if successfull. + bool getGeometricHalves + ( + const primitivePatch&, + labelList&, + labelList& + ) const; + + //- Calculate geometric factors of the two halves. + void getCentresAndAnchors + ( + const primitivePatch&, + const faceList& half0Faces, + const faceList& half1Faces, + + pointField& ppPoints, + pointField& half0Ctrs, + pointField& half1Ctrs, + pointField& anchors0, + scalarField& tols + ) const; + + //- Given matched faces matches the anchor point. Sets faceMap, + // rotation. Returns true if all matched. + bool matchAnchors + ( + const bool report, + const primitivePatch&, + const labelList&, + const pointField&, + const labelList&, + const faceList&, + const labelList&, + const scalarField&, + + labelList& faceMap, + labelList& rotation + ) const; + + //- For rotational cases, try to find a unique face on each side + // of the cyclic. + label getConsistentRotationFace + ( + const pointField& faceCentres + ) const; + + +protected: + + // Protected Member functions + + //- Initialise the calculation of the patch geometry + virtual void initGeometry(PstreamBuffers&); + + //- Calculate the patch geometry + virtual void calcGeometry(PstreamBuffers&); + + //- Initialise the patches for moving points + virtual void initMovePoints(PstreamBuffers&, const pointField&); + + //- Correct patches after moving points + virtual void movePoints(PstreamBuffers&, const pointField&); + + //- Initialise the update of the patch topology + virtual void initUpdateMesh(PstreamBuffers&); + + //- Update of the patch topology + virtual void updateMesh(PstreamBuffers&); + +public: + + //- Runtime type information + TypeName("oldCyclic"); + + + // Constructors + + //- Construct from components + oldCyclicPolyPatch + ( + const word& name, + const label size, + const label start, + const label index, + const polyBoundaryMesh& bm + ); + + //- Construct from dictionary + oldCyclicPolyPatch + ( + const word& name, + const dictionary& dict, + const label index, + const polyBoundaryMesh& bm + ); + + //- Construct as copy, resetting the boundary mesh + oldCyclicPolyPatch(const oldCyclicPolyPatch&, const polyBoundaryMesh&); + + //- Construct given the original patch and resetting the + // face list and boundary mesh information + oldCyclicPolyPatch + ( + const oldCyclicPolyPatch& pp, + const polyBoundaryMesh& bm, + const label index, + const label newSize, + const label newStart + ); + + //- Construct and return a clone, resetting the boundary mesh + virtual autoPtr<polyPatch> clone(const polyBoundaryMesh& bm) const + { + return autoPtr<polyPatch>(new oldCyclicPolyPatch(*this, bm)); + } + + //- Construct and return a clone, resetting the face list + // and boundary mesh + virtual autoPtr<polyPatch> clone + ( + const polyBoundaryMesh& bm, + const label index, + const label newSize, + const label newStart + ) const + { + return autoPtr<polyPatch> + ( + new oldCyclicPolyPatch(*this, bm, index, newSize, newStart) + ); + } + + + // Destructor + + virtual ~oldCyclicPolyPatch(); + + + // Member Functions + + // Access + + //- Does this side own the patch ? + virtual bool owner() const + { + notImplemented("oldCyclicPolyPatch::owner()"); + return true; + } + + //- Transform a patch-based position from other side to this side + virtual void transformPosition(pointField& l) const + { + notImplemented("transformPosition(pointField&)"); + } + + //- Calculate the patch geometry + virtual void calcGeometry + ( + const primitivePatch& referPatch, + const UList<point>& thisCtrs, + const UList<point>& thisAreas, + const UList<point>& thisCc, + const UList<point>& nbrCtrs, + const UList<point>& nbrAreas, + const UList<point>& nbrCc + ); + + //- Initialize ordering for primitivePatch. Does not + // refer to *this (except for name() and type() etc.) + virtual void initOrder + ( + PstreamBuffers&, + const primitivePatch& + ) const; + + //- Return new ordering for primitivePatch. + // Ordering is -faceMap: for every face + // index of the new face -rotation:for every new face the clockwise + // shift of the original face. Return false if nothing changes + // (faceMap is identity, rotation is 0), true otherwise. + virtual bool order + ( + PstreamBuffers&, + const primitivePatch&, + labelList& faceMap, + labelList& rotation + ) const; + + //- Write the polyPatch data as a dictionary + virtual void write(Ostream&) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/fields/fvPatchFields/constraint/cyclic/cyclicFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/constraint/cyclic/cyclicFvPatchField.C index 0010ab4a0a0b40b4f2611c509954d9a9ed32f610..c3949a6ac0715bf305a1256a8a98ce1c617f843a 100644 --- a/src/finiteVolume/fields/fvPatchFields/constraint/cyclic/cyclicFvPatchField.C +++ b/src/finiteVolume/fields/fvPatchFields/constraint/cyclic/cyclicFvPatchField.C @@ -171,6 +171,23 @@ tmp<Field<Type> > cyclicFvPatchField<Type>::patchNeighbourField() const } +template<class Type> +const cyclicFvPatchField<Type>& cyclicFvPatchField<Type>::neighbourPatchField() +const +{ + const GeometricField<Type, fvPatchField, volMesh>& fld = + static_cast<const GeometricField<Type, fvPatchField, volMesh>&> + ( + this->internalField() + ); + + return refCast<const cyclicFvPatchField<Type> > + ( + fld.boundaryField()[this->cyclicPatch().neighbPatchID()] + ); +} + + template<class Type> void cyclicFvPatchField<Type>::updateInterfaceMatrix ( diff --git a/src/finiteVolume/fields/fvPatchFields/constraint/cyclic/cyclicFvPatchField.H b/src/finiteVolume/fields/fvPatchFields/constraint/cyclic/cyclicFvPatchField.H index 654bd0831a560a95b6b1e86d0d5f9c8ad53e99e6..198dbab74138aaaf5fc3897316c49cc154b8a970 100644 --- a/src/finiteVolume/fields/fvPatchFields/constraint/cyclic/cyclicFvPatchField.H +++ b/src/finiteVolume/fields/fvPatchFields/constraint/cyclic/cyclicFvPatchField.H @@ -150,9 +150,12 @@ public: // Evaluation functions - //- Return neighbour coupled given internal cell data + //- Return neighbour coupled internal cell data tmp<Field<Type> > patchNeighbourField() const; + //- Return reference to neighbour patchField + const cyclicFvPatchField<Type>& neighbourPatchField() const; + //- Update result field based on interface functionality virtual void updateInterfaceMatrix ( diff --git a/src/finiteVolume/fields/fvPatchFields/derived/fan/fanFvPatchField.H b/src/finiteVolume/fields/fvPatchFields/derived/fan/fanFvPatchField.H index 73014e048a2a17b6336760eab447e39e0e7a80da..31c51c999d4e9139cec0f556a519dec309a83d79 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/fan/fanFvPatchField.H +++ b/src/finiteVolume/fields/fvPatchFields/derived/fan/fanFvPatchField.H @@ -140,7 +140,17 @@ public: //- Return the "jump" across the patch. virtual tmp<Field<Type> > jump() const { - return jump_; + if (this->cyclicPatch().owner()) + { + return jump_; + } + else + { + return refCast<const fanFvPatchField<Type> > + ( + this->neighbourPatchField() + ).jump(); + } } diff --git a/src/parallel/decompose/ptscotchDecomp/ptscotchDecomp.C b/src/parallel/decompose/ptscotchDecomp/ptscotchDecomp.C index 98f231cf4858ce5b40e2c3a443e23ca848641783..ff262c5645d28388a71529f20f6c0a2dfaceed91 100644 --- a/src/parallel/decompose/ptscotchDecomp/ptscotchDecomp.C +++ b/src/parallel/decompose/ptscotchDecomp/ptscotchDecomp.C @@ -180,17 +180,31 @@ Foam::label Foam::ptscotchDecomp::decompose // Info<< "Dumping Scotch graph file to " << str.name() << endl // << "Use this in combination with gpart." << endl; // -// label version = 0; +// // Distributed graph file (.grf) +// label version = 2; // str << version << nl; -// // Numer of vertices -// str << xadj.size()-1 << ' ' << adjncy.size() << nl; +// // Number of files + +// // Number of files (procglbnbr) +// str << Pstream::nProcs(); +// // My file number (procloc) +// str << ' ' << Pstream::myProcNo() << nl; +// +// // Total number of vertices (vertglbnbr) +// str << returnReduce(mesh.nCells(), sumOp<label>()); +// // Total number of connections (edgeglbnbr) +// str << ' ' << returnReduce(xadj[mesh.nCells()], sumOp<label>()) +// << nl; +// // Local number of vertices (vertlocnbr) +// str << mesh.nCells(); +// // Local number of connections (edgelocnbr) +// str << ' ' << xadj[mesh.nCells()] << nl; // // Numbering starts from 0 // label baseval = 0; -// // Has weights? -// label hasEdgeWeights = 0; -// label hasVertexWeights = 0; -// label numericflag = 10*hasEdgeWeights+hasVertexWeights; -// str << baseval << ' ' << numericflag << nl; +// // Start of my global vertices (procdsptab[proclocnum]) +// str << ' ' << globalCells.toGlobal(0); +// 100*hasVertlabels+10*hasEdgeWeights+1*hasVertWeighs +// str << ' ' << "0" << nl; // for (label cellI = 0; cellI < xadj.size()-1; cellI++) // { // label start = xadj[cellI]; diff --git a/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/U b/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/U index 51ef892fb8a5263548b1471887b3702fc8e41b88..f1006ceb5ed5db11c66679186c6c98a424d8190e 100644 --- a/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/U +++ b/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/U @@ -15,47 +15,47 @@ FoamFile } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -dimensions [ 0 1 -1 0 0 0 0 ]; +dimensions [0 1 -1 0 0 0 0]; -internalField uniform ( 0 0 0 ); +internalField uniform (0 0 0); boundaryField { inlet { type pressureInletOutletVelocity; - value uniform ( 0 0 0 ); + value uniform (0 0 0); } outlet1 { type inletOutlet; - inletValue uniform ( 0 0 0 ); - value uniform ( 0 0 0 ); + inletValue uniform (0 0 0); + value uniform (0 0 0); } outlet2 { type inletOutlet; - inletValue uniform ( 0 0 0 ); - value uniform ( 0 0 0 ); + inletValue uniform (0 0 0); + value uniform (0 0 0); } baffles { type fixedValue; - value uniform ( 0 0 0 ); + value uniform (0 0 0); } fan_half0 { type cyclic; } - defaultFaces - { - type fixedValue; - value uniform ( 0 0 0 ); - } fan_half1 { type cyclic; } + defaultFaces + { + type fixedValue; + value uniform (0 0 0); + } } diff --git a/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/epsilon b/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/epsilon index dc1eb9da3ec01e6e20b9eb1bfee53d5a810eeb34..5c6c53664db8773322bca5f71be4360714228dda 100644 --- a/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/epsilon +++ b/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/epsilon @@ -15,7 +15,7 @@ FoamFile } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -dimensions [ 0 2 -3 0 0 0 0 ]; +dimensions [0 2 -3 0 0 0 0]; internalField uniform 1; @@ -42,21 +42,27 @@ boundaryField baffles { type epsilonWallFunction; - value uniform 1; + Cmu 0.09; + kappa 0.41; + E 9.8; + value uniform 0; } fan_half0 { type cyclic; } + fan_half1 + { + type cyclic; + } defaultFaces { type epsilonWallFunction; + Cmu 0.09; + kappa 0.41; + E 9.8; value uniform 1; } - fan_half1 - { - type cyclic; - } } diff --git a/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/k b/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/k index 06aeff0f1f5ab3f291870fd35e0fe6dea2557c93..18cb53d51920f57d6f114259326f42644171e03f 100644 --- a/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/k +++ b/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/k @@ -15,7 +15,7 @@ FoamFile } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -dimensions [ 0 2 -2 0 0 0 0 ]; +dimensions [0 2 -2 0 0 0 0]; internalField uniform 1; @@ -42,21 +42,21 @@ boundaryField baffles { type kqRWallFunction; - value uniform 1; + value uniform 0; } fan_half0 { type cyclic; } + fan_half1 + { + type cyclic; + } defaultFaces { type kqRWallFunction; value uniform 1; } - fan_half1 - { - type cyclic; - } } diff --git a/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/nuTilda b/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/nuTilda index 699a951041d71878bd5f2ac7a250c4eaf8ce4c36..ffc7ac906f4c311a7a4bf9ee078e66a7686c517d 100644 --- a/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/nuTilda +++ b/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/nuTilda @@ -15,7 +15,7 @@ FoamFile } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -dimensions [ 0 2 -1 0 0 0 0 ]; +dimensions [0 2 -1 0 0 0 0]; internalField uniform 0; @@ -41,14 +41,14 @@ boundaryField { type cyclic; } - defaultFaces - { - type zeroGradient; - } fan_half1 { type cyclic; } + defaultFaces + { + type zeroGradient; + } } diff --git a/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/nut b/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/nut index 1a5afb9689fbb662c24a1cce95bdbfe3ba166031..6ed8f42dfc22716594c16f28ca52a8d0d38c29fb 100644 --- a/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/nut +++ b/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/nut @@ -15,7 +15,7 @@ FoamFile } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -dimensions [ 0 2 -1 0 0 0 0 ]; +dimensions [0 2 -1 0 0 0 0]; internalField uniform 0; @@ -39,21 +39,27 @@ boundaryField baffles { type nutkWallFunction; + Cmu 0.09; + kappa 0.41; + E 9.8; value uniform 0; } fan_half0 { type cyclic; } + fan_half1 + { + type cyclic; + } defaultFaces { type nutkWallFunction; + Cmu 0.09; + kappa 0.41; + E 9.8; value uniform 0; } - fan_half1 - { - type cyclic; - } } diff --git a/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/p b/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/p index c77ad857259c08270564e1e72249631d59902d89..66f5c1d712ae70f900e35160f3dc300c688ebb67 100644 --- a/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/p +++ b/tutorials/incompressible/pimpleFoam/t-junction-with-fan/0/p @@ -15,7 +15,7 @@ FoamFile } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -dimensions [ 0 2 -2 0 0 0 0 ]; +dimensions [0 2 -2 0 0 0 0]; internalField uniform 100000; @@ -24,14 +24,12 @@ boundaryField inlet { type timeVaryingTotalPressure; - p0 100040; - outOfBounds clamp; - fileName "$FOAM_CASE/constant/p0vsTime"; - U U; - phi phi; rho none; psi none; gamma 1; + p0 100040; + fileName "$FOAM_CASE/constant/p0vsTime"; + outOfBounds clamp; value uniform 100040; } outlet1 @@ -52,19 +50,19 @@ boundaryField { type fan; patchType cyclic; - f 2 ( 50 -0.1 ); - value $internalField; - } - defaultFaces - { - type zeroGradient; + f 2(100 -0.1); + value uniform 0; } fan_half1 { type fan; patchType cyclic; - f 2 ( 50 -0.1 ); - value $internalField; + f 2(100 -0.1); + value uniform 0; + } + defaultFaces + { + type zeroGradient; } } diff --git a/tutorials/incompressible/pimpleFoam/t-junction-with-fan/system/controlDict b/tutorials/incompressible/pimpleFoam/t-junction-with-fan/system/controlDict index 9dc31d5561fb3c86c93e949d18a3dd5b39d41977..63b26690081d708fb88fc371777da73e5f6f5a7e 100644 --- a/tutorials/incompressible/pimpleFoam/t-junction-with-fan/system/controlDict +++ b/tutorials/incompressible/pimpleFoam/t-junction-with-fan/system/controlDict @@ -28,7 +28,6 @@ endTime 1; deltaT 0.001; writeControl adjustableRunTime; - writeInterval 0.1; purgeWrite 0; @@ -47,7 +46,7 @@ runTimeModifiable true; adjustTimeStep yes; -maxCo 5; +maxCo 3; libs (