/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation \\/ 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 . \*---------------------------------------------------------------------------*/ #include "globalIndexAndTransform.H" #include "cyclicPolyPatch.H" // * * * * * * * * * * * * Private Static Data Members * * * * * * * * * * * // defineTypeNameAndDebug(Foam::globalIndexAndTransform, 0); const Foam::label Foam::globalIndexAndTransform::base_ = 32; // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // Foam::label Foam::globalIndexAndTransform::matchTransform ( const List& refTransforms, label& matchedRefTransformI, const vectorTensorTransform& testTransform, scalar tolerance, bool checkBothSigns ) const { matchedRefTransformI = -1; forAll(refTransforms, i) { const vectorTensorTransform& refTransform = refTransforms[i]; scalar maxVectorMag = sqrt ( max(magSqr(testTransform.t()), magSqr(refTransform.t())) ); // Test the difference between vector parts to see if it is // less than tolerance times the larger vector part magnitude. scalar vectorDiff = mag(refTransform.t() - testTransform.t()) /(maxVectorMag + VSMALL) /tolerance; // Test the difference between tensor parts to see if it is // less than the tolerance. sqrt(3.0) factor used to scale // differnces as this is magnitude of a rotation tensor. If // neither transform has a rotation, then the test is not // necessary. scalar tensorDiff = 0; if (refTransform.hasR() || testTransform.hasR()) { tensorDiff = mag(refTransform.R() - testTransform.R()) /sqrt(3.0) /tolerance; } // ...Diff result is < 1 if the test part matches the ref part // within tolerance if (vectorDiff < 1 && tensorDiff < 1) { matchedRefTransformI = i; return +1; } if (checkBothSigns) { // Test the inverse transform differences too vectorDiff = mag(refTransform.t() + testTransform.t()) /(maxVectorMag + VSMALL) /tolerance; tensorDiff = 0; if (refTransform.hasR() || testTransform.hasR()) { tensorDiff = mag(refTransform.R() - testTransform.R().T()) /sqrt(3.0) /tolerance; } if (vectorDiff < 1 && tensorDiff < 1) { matchedRefTransformI = i; return -1; } } } return 0; } void Foam::globalIndexAndTransform::determineTransforms() { const polyBoundaryMesh& patches = mesh_.boundaryMesh(); transforms_ = List(6); scalarField maxTol(6); label nextTrans = 0; label dummyMatch = -1; forAll(patches, patchI) { const polyPatch& pp = patches[patchI]; // Note: special check for unordered cyclics. These are in fact // transform bcs and should probably be split off. if ( isA(pp) && !( isA(pp) && ( refCast(pp).transform() == cyclicPolyPatch::NOORDERING ) ) ) { const coupledPolyPatch& cpp = refCast(pp); if (cpp.separated()) { const vectorField& sepVecs = cpp.separation(); forAll(sepVecs, sVI) { const vector& sepVec = sepVecs[sVI]; if (mag(sepVec) > SMALL) { vectorTensorTransform transform(sepVec); if ( matchTransform ( transforms_, dummyMatch, transform, cpp.matchTolerance(), false ) == 0 ) { if (nextTrans == 6) { FatalErrorIn ( "void Foam::globalIndexAndTransform::" "determineTransforms()" ) << "More than six unsigned transforms" << " detected:" << nl << transforms_ << exit(FatalError); } transforms_[nextTrans] = transform; maxTol[nextTrans++] = cpp.matchTolerance(); } } } } else if (!cpp.parallel()) { const tensorField& transTensors = cpp.reverseT(); forAll(transTensors, tTI) { const tensor& transT = transTensors[tTI]; if (mag(transT - I) > SMALL) { vectorTensorTransform transform(transT); if ( matchTransform ( transforms_, dummyMatch, transform, cpp.matchTolerance(), false ) == 0 ) { if (nextTrans == 6) { FatalErrorIn ( "void Foam::globalIndexAndTransform::" "determineTransforms()" ) << "More than six unsigned transforms" << " detected:" << nl << transforms_ << exit(FatalError); } transforms_[nextTrans] = transform; maxTol[nextTrans++] = cpp.matchTolerance(); } } } } } } // Collect transforms on master List > allTransforms(Pstream::nProcs()); allTransforms[Pstream::myProcNo()] = transforms_; Pstream::gatherList(allTransforms); // Collect matching tolerance on master List allTols(Pstream::nProcs()); allTols[Pstream::myProcNo()] = maxTol; Pstream::gatherList(allTols); if (Pstream::master()) { transforms_ = List(3); label nextTrans = 0; forAll(allTransforms, procI) { const List& procTransVecs = allTransforms[procI]; forAll(procTransVecs, pSVI) { const vectorTensorTransform& transform = procTransVecs[pSVI]; if (mag(transform.t()) > SMALL || transform.hasR()) { if ( matchTransform ( transforms_, dummyMatch, transform, allTols[procI][pSVI], true ) == 0 ) { transforms_[nextTrans++] = transform; } if (nextTrans > 3) { FatalErrorIn ( "void Foam::globalIndexAndTransform::" "determineTransforms()" ) << "More than three independent basic " << "transforms detected:" << nl << allTransforms << transforms_ << exit(FatalError); } } } } transforms_.setSize(nextTrans); } Pstream::scatter(transforms_); if (transforms_.size() > 3) { WarningIn ( "void globalIndexAndTransform::determineTransforms()" ) << "More than three independent basic " << "transforms detected:" << nl << transforms_ << nl << "This is not a space filling tiling and will probably" << " give problems for e.g. lagrangian tracking or interpolation" << endl; } } void Foam::globalIndexAndTransform::determineTransformPermutations() { label nTransformPermutations = pow(label(3), transforms_.size()); transformPermutations_.setSize(nTransformPermutations); forAll(transformPermutations_, tPI) { vectorTensorTransform transform; label transformIndex = tPI; // Invert the ternary index encoding using repeated division by // three forAll(transforms_, b) { const label w = (transformIndex % 3) - 1; transformIndex /= 3; if (w > 0) { transform &= transforms_[b]; } else if (w < 0) { transform &= inv(transforms_[b]); } } transformPermutations_[tPI] = transform; } // Encode index for 0 sign labelList permutationIndices(nIndependentTransforms(), 0); nullTransformIndex_ = encodeTransformIndex(permutationIndices); } void Foam::globalIndexAndTransform::determinePatchTransformSign() { const polyBoundaryMesh& patches = mesh_.boundaryMesh(); patchTransformSign_.setSize(patches.size(), Pair