1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2010-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 "globalIndexAndTransform.H"
27 #include "cyclicPolyPatch.H"
29 // * * * * * * * * * * * * Private Static Data Members * * * * * * * * * * * //
31 defineTypeNameAndDebug(Foam::globalIndexAndTransform, 0);
33 const Foam::label Foam::globalIndexAndTransform::base_ = 32;
36 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
38 Foam::label Foam::globalIndexAndTransform::matchTransform
40 const List<vectorTensorTransform>& refTransforms,
41 label& matchedRefTransformI,
42 const vectorTensorTransform& testTransform,
47 matchedRefTransformI = -1;
49 forAll(refTransforms, i)
51 const vectorTensorTransform& refTransform = refTransforms[i];
53 scalar maxVectorMag = sqrt
55 max(magSqr(testTransform.t()), magSqr(refTransform.t()))
58 // Test the difference between vector parts to see if it is
59 // less than tolerance times the larger vector part magnitude.
62 mag(refTransform.t() - testTransform.t())
63 /(maxVectorMag + VSMALL)
66 // Test the difference between tensor parts to see if it is
67 // less than the tolerance. sqrt(3.0) factor used to scale
68 // differnces as this is magnitude of a rotation tensor. If
69 // neither transform has a rotation, then the test is not
72 scalar tensorDiff = 0;
74 if (refTransform.hasR() || testTransform.hasR())
77 mag(refTransform.R() - testTransform.R())
82 // ...Diff result is < 1 if the test part matches the ref part
85 if (vectorDiff < 1 && tensorDiff < 1)
87 matchedRefTransformI = i;
94 // Test the inverse transform differences too
97 mag(refTransform.t() + testTransform.t())
98 /(maxVectorMag + VSMALL)
103 if (refTransform.hasR() || testTransform.hasR())
106 mag(refTransform.R() - testTransform.R().T())
111 if (vectorDiff < 1 && tensorDiff < 1)
113 matchedRefTransformI = i;
124 void Foam::globalIndexAndTransform::determineTransforms()
126 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
128 transforms_ = List<vectorTensorTransform>(6);
129 scalarField maxTol(6);
133 label dummyMatch = -1;
135 forAll(patches, patchI)
137 const polyPatch& pp = patches[patchI];
139 // Note: special check for unordered cyclics. These are in fact
140 // transform bcs and should probably be split off.
143 isA<coupledPolyPatch>(pp)
145 isA<cyclicPolyPatch>(pp)
147 refCast<const cyclicPolyPatch>(pp).transform()
148 == cyclicPolyPatch::NOORDERING
153 const coupledPolyPatch& cpp = refCast<const coupledPolyPatch>(pp);
157 const vectorField& sepVecs = cpp.separation();
161 const vector& sepVec = sepVecs[sVI];
163 if (mag(sepVec) > SMALL)
165 vectorTensorTransform transform(sepVec);
174 cpp.matchTolerance(),
183 "void Foam::globalIndexAndTransform::"
184 "determineTransforms()"
185 ) << "More than six unsigned transforms"
186 << " detected:" << nl << transforms_
189 transforms_[nextTrans] = transform;
190 maxTol[nextTrans++] = cpp.matchTolerance();
195 else if (!cpp.parallel())
197 const tensorField& transTensors = cpp.reverseT();
199 forAll(transTensors, tTI)
201 const tensor& transT = transTensors[tTI];
203 if (mag(transT - I) > SMALL)
205 vectorTensorTransform transform(transT);
214 cpp.matchTolerance(),
223 "void Foam::globalIndexAndTransform::"
224 "determineTransforms()"
225 ) << "More than six unsigned transforms"
226 << " detected:" << nl << transforms_
229 transforms_[nextTrans] = transform;
230 maxTol[nextTrans++] = cpp.matchTolerance();
239 // Collect transforms on master
241 List<List<vectorTensorTransform> > allTransforms(Pstream::nProcs());
242 allTransforms[Pstream::myProcNo()] = transforms_;
243 Pstream::gatherList(allTransforms);
245 // Collect matching tolerance on master
246 List<scalarField> allTols(Pstream::nProcs());
247 allTols[Pstream::myProcNo()] = maxTol;
248 Pstream::gatherList(allTols);
250 if (Pstream::master())
252 transforms_ = List<vectorTensorTransform>(3);
256 forAll(allTransforms, procI)
258 const List<vectorTensorTransform>& procTransVecs =
259 allTransforms[procI];
261 forAll(procTransVecs, pSVI)
263 const vectorTensorTransform& transform = procTransVecs[pSVI];
265 if (mag(transform.t()) > SMALL || transform.hasR())
274 allTols[procI][pSVI],
279 transforms_[nextTrans++] = transform;
286 "void Foam::globalIndexAndTransform::"
287 "determineTransforms()"
289 << "More than three independent basic "
290 << "transforms detected:" << nl
299 transforms_.setSize(nextTrans);
302 Pstream::scatter(transforms_);
304 if (transforms_.size() > 3)
308 "void globalIndexAndTransform::determineTransforms()"
309 ) << "More than three independent basic "
310 << "transforms detected:" << nl
312 << "This is not a space filling tiling and will probably"
313 << " give problems for e.g. lagrangian tracking or interpolation"
319 void Foam::globalIndexAndTransform::determineTransformPermutations()
321 label nTransformPermutations = pow(3, transforms_.size());
323 transformPermutations_.setSize(nTransformPermutations);
325 forAll(transformPermutations_, tPI)
327 vectorTensorTransform transform;
329 label transformIndex = tPI;
331 // Invert the ternary index encoding using repeated division by
334 forAll(transforms_, b)
336 const label w = (transformIndex % 3) - 1;
342 transform &= transforms_[b];
346 transform &= inv(transforms_[b]);
350 transformPermutations_[tPI] = transform;
354 // Encode index for 0 sign
355 labelList permutationIndices(nIndependentTransforms(), 0);
356 nullTransformIndex_ = encodeTransformIndex(permutationIndices);
360 void Foam::globalIndexAndTransform::determinePatchTransformSign()
362 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
364 patchTransformSign_.setSize(patches.size(), Pair<label>(-1, 0));
366 label matchTransI = -1;
368 forAll(patches, patchI)
370 const polyPatch& pp = patches[patchI];
372 // Pout<< nl << patchI << " " << pp.name() << endl;
374 // Note: special check for unordered cyclics. These are in fact
375 // transform bcs and should probably be split off.
378 isA<coupledPolyPatch>(pp)
380 isA<cyclicPolyPatch>(pp)
382 refCast<const cyclicPolyPatch>(pp).transform()
383 == cyclicPolyPatch::NOORDERING
388 const coupledPolyPatch& cpp =
389 refCast<const coupledPolyPatch>(pp);
393 const vectorField& sepVecs = cpp.separation();
395 // Pout<< "sepVecs " << sepVecs << endl;
397 // This loop is implicitly expecting only a single
398 // value for separation()
401 const vector& sepVec = sepVecs[sVI];
403 if (mag(sepVec) > SMALL)
405 vectorTensorTransform t(sepVec);
407 label sign = matchTransform
412 cpp.matchTolerance(),
416 // Pout<< sign << " " << matchTransI << endl;
418 // List<label> permutation(transforms_.size(), 0);
420 // permutation[matchTransI] = sign;
422 // Pout<< encodeTransformIndex(permutation) << nl
423 // << transformPermutations_
425 // encodeTransformIndex(permutation)
429 patchTransformSign_[patchI] =
430 Pair<label>(matchTransI, sign);
435 else if (!cpp.parallel())
437 const tensorField& transTensors = cpp.reverseT();
439 // Pout<< "transTensors " << transTensors << endl;
441 // This loop is implicitly expecting only a single
442 // value for reverseT()
443 forAll(transTensors, tTI)
445 const tensor& transT = transTensors[tTI];
447 if (mag(transT - I) > SMALL)
449 vectorTensorTransform t(transT);
451 label sign = matchTransform
456 cpp.matchTolerance(),
460 // Pout<< sign << " " << matchTransI << endl;
462 // List<label> permutation(transforms_.size(), 0);
464 // permutation[matchTransI] = sign;
466 // Pout<< encodeTransformIndex(permutation) << nl
467 // << transformPermutations_
469 // encodeTransformIndex(permutation)
473 patchTransformSign_[patchI] =
474 Pair<label>(matchTransI, sign);
481 // Pout<< patchTransformSign_ << endl;
485 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
487 Foam::globalIndexAndTransform::globalIndexAndTransform
494 transformPermutations_(),
495 patchTransformSign_()
497 determineTransforms();
499 determineTransformPermutations();
501 determinePatchTransformSign();
503 if (debug && transforms_.size() > 0)
505 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
507 Info<< "Determined global transforms :" << endl;
508 Info<< "\t\ttranslation\trotation" << endl;
509 forAll(transforms_, i)
511 Info<< '\t' << i << '\t';
512 const vectorTensorTransform& trafo = transforms_[i];
515 Info<< trafo.t() << '\t' << trafo.R();
519 Info<< trafo.t() << '\t' << "---";
526 Info<< "\tpatch\ttransform\tsign" << endl;
527 forAll(patchTransformSign_, patchI)
529 if (patchTransformSign_[patchI].first() != -1)
531 Info<< '\t' << patches[patchI].name()
532 << '\t' << patchTransformSign_[patchI].first()
533 << '\t' << patchTransformSign_[patchI].second()
540 Info<< "Permutations of transformations:" << endl
541 << "\t\ttranslation\trotation" << endl;
542 forAll(transformPermutations_, i)
544 Info<< '\t' << i << '\t';
545 const vectorTensorTransform& trafo = transformPermutations_[i];
548 Info<< trafo.t() << '\t' << trafo.R();
552 Info<< trafo.t() << '\t' << "---";
556 Info<< "nullTransformIndex:" << nullTransformIndex() << endl
562 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
564 Foam::globalIndexAndTransform::~globalIndexAndTransform()
568 // ************************************************************************* //