FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

coupledPolyPatch.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2011 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*---------------------------------------------------------------------------*/
00025 
00026 #include "coupledPolyPatch.H"
00027 #include <OpenFOAM/ListOps.H>
00028 #include <OpenFOAM/transform.H>
00029 #include <OpenFOAM/OFstream.H>
00030 
00031 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00032 
00033 defineTypeNameAndDebug(Foam::coupledPolyPatch, 0);
00034 
00035 template<>
00036 const char* Foam::NamedEnum<Foam::coupledPolyPatch::transformType, 3>::names[] =
00037 {
00038     "unknown",
00039     "rotational",
00040     "translational"
00041 };
00042 
00043 const Foam::NamedEnum<Foam::coupledPolyPatch::transformType, 3>
00044     Foam::coupledPolyPatch::transformTypeNames;
00045 
00046 Foam::scalar Foam::coupledPolyPatch::matchTol = 1E-3;
00047 
00048 
00049 // * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * * //
00050 
00051 void Foam::coupledPolyPatch::writeOBJ(Ostream& os, const point& pt)
00052 {
00053     os << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << endl;
00054 }
00055 
00056 
00057 void Foam::coupledPolyPatch::writeOBJ
00058 (
00059     Ostream& os,
00060     const pointField& points,
00061     const labelList& pointLabels
00062 )
00063 {
00064     forAll(pointLabels, i)
00065     {
00066         writeOBJ(os, points[pointLabels[i]]);
00067     }
00068 }
00069 
00070 
00071 void Foam::coupledPolyPatch::writeOBJ
00072 (
00073     Ostream& os,
00074     const point& p0,
00075     const point& p1,
00076     label& vertI
00077 )
00078 {
00079     writeOBJ(os, p0);
00080     vertI++;
00081 
00082     writeOBJ(os, p1);
00083     vertI++;
00084 
00085     os<< "l " << vertI-1 << ' ' << vertI << nl;
00086 }
00087 
00088 
00089 void Foam::coupledPolyPatch::writeOBJ
00090 (
00091     const fileName& fName,
00092     const UList<face>& faces,
00093     const pointField& points
00094 )
00095 {
00096     OFstream os(fName);
00097 
00098     Map<label> foamToObj(4*faces.size());
00099 
00100     label vertI = 0;
00101 
00102     forAll(faces, i)
00103     {
00104         const face& f = faces[i];
00105 
00106         forAll(f, fp)
00107         {
00108             if (foamToObj.insert(f[fp], vertI))
00109             {
00110                 writeOBJ(os, points[f[fp]]);
00111                 vertI++;
00112             }
00113         }
00114 
00115         os << 'l';
00116         forAll(f, fp)
00117         {
00118             os << ' ' << foamToObj[f[fp]]+1;
00119         }
00120         os << ' ' << foamToObj[f[0]]+1 << nl;
00121     }
00122 }
00123 
00124 
00125 Foam::pointField Foam::coupledPolyPatch::calcFaceCentres
00126 (
00127     const UList<face>& faces,
00128     const pointField& points
00129 )
00130 {
00131     pointField ctrs(faces.size());
00132 
00133     forAll(faces, faceI)
00134     {
00135         ctrs[faceI] = faces[faceI].centre(points);
00136     }
00137 
00138     return ctrs;
00139 }
00140 
00141 
00142 Foam::pointField Foam::coupledPolyPatch::getAnchorPoints
00143 (
00144     const UList<face>& faces,
00145     const pointField& points
00146 )
00147 {
00148     pointField anchors(faces.size());
00149 
00150     forAll(faces, faceI)
00151     {
00152         anchors[faceI] = points[faces[faceI][0]];
00153     }
00154 
00155     return anchors;
00156 }
00157 
00158 
00159 bool Foam::coupledPolyPatch::inPatch
00160 (
00161     const labelList& oldToNew,
00162     const label oldFaceI
00163 ) const
00164 {
00165     label faceI = oldToNew[oldFaceI];
00166 
00167     return faceI >= start() && faceI < start()+size();
00168 }
00169 
00170 
00171 Foam::label Foam::coupledPolyPatch::whichPatch
00172 (
00173     const labelList& patchStarts,
00174     const label faceI
00175 )
00176 {
00177     forAll(patchStarts, patchI)
00178     {
00179         if (patchStarts[patchI] <= faceI)
00180         {
00181             if (patchI == patchStarts.size()-1)
00182             {
00183                 return patchI;
00184             }
00185             else if (patchStarts[patchI+1] > faceI)
00186             {
00187                 return patchI;
00188             }
00189         }
00190     }
00191 
00192     return -1;
00193 }
00194 
00195 
00196 Foam::scalarField Foam::coupledPolyPatch::calcFaceTol
00197 (
00198     const UList<face>& faces,
00199     const pointField& points,
00200     const pointField& faceCentres
00201 )
00202 {
00203     // Calculate typical distance per face
00204     scalarField tols(faces.size());
00205 
00206     forAll(faces, faceI)
00207     {
00208         const point& cc = faceCentres[faceI];
00209 
00210         const face& f = faces[faceI];
00211 
00212         // 1. calculate a typical size of the face. Use maximum distance
00213         //    to face centre
00214         scalar maxLenSqr = -GREAT;
00215         // 2. as measure of truncation error when comparing two coordinates
00216         //    use SMALL * maximum component
00217         scalar maxCmpt = -GREAT;
00218 
00219         forAll(f, fp)
00220         {
00221             const point& pt = points[f[fp]];
00222             maxLenSqr = max(maxLenSqr, magSqr(pt - cc));
00223             maxCmpt = max(maxCmpt, cmptMax(cmptMag(pt)));
00224         }
00225         tols[faceI] = max(SMALL*maxCmpt, matchTol*Foam::sqrt(maxLenSqr));
00226     }
00227     return tols;
00228 }
00229 
00230 
00231 Foam::label Foam::coupledPolyPatch::getRotation
00232 (
00233     const pointField& points,
00234     const face& f,
00235     const point& anchor,
00236     const scalar tol
00237 )
00238 {
00239     label anchorFp = -1;
00240     scalar minDistSqr = GREAT;
00241 
00242     forAll(f, fp)
00243     {
00244         scalar distSqr = magSqr(anchor - points[f[fp]]);
00245 
00246         if (distSqr < minDistSqr)
00247         {
00248             minDistSqr = distSqr;
00249             anchorFp = fp;
00250         }
00251     }
00252 
00253     if (anchorFp == -1 || mag(minDistSqr) > tol)
00254     {
00255         return -1;
00256     }
00257     else
00258     {
00259         // Positive rotation
00260         return (f.size() - anchorFp) % f.size();
00261     }
00262 }
00263 
00264 
00265 void Foam::coupledPolyPatch::calcTransformTensors
00266 (
00267     const vectorField& Cf,
00268     const vectorField& Cr,
00269     const vectorField& nf,
00270     const vectorField& nr,
00271     const scalarField& smallDist,
00272     const scalar absTol,
00273     const transformType transform
00274 ) const
00275 {
00276     if (debug)
00277     {
00278         Pout<< "coupledPolyPatch::calcTransformTensors : " << name() << endl
00279             << "    transform:" << transformTypeNames[transform] << nl
00280             << "    (half)size:" << Cf.size() << nl
00281             << "    absTol:" << absTol << nl
00282             //<< "    smallDist:" << smallDist << nl
00283             << "    sum(mag(nf & nr)):" << sum(mag(nf & nr)) << endl;
00284     }
00285 
00286     // Tolerance calculation.
00287     // - normal calculation: assume absTol is the absolute error in a
00288     // single normal/transformation calculation. Consists both of numerical
00289     // precision (on the order of SMALL and of writing precision
00290     // (from e.g. decomposition)
00291     // Then the overall error of summing the normals is sqrt(size())*absTol
00292     // - separation calculation: pass in from the outside an allowable error.
00293 
00294     if (size() == 0)
00295     {
00296         // Dummy geometry.
00297         separation_.setSize(0);
00298         forwardT_ = I;
00299         reverseT_ = I;
00300     }
00301     else
00302     {
00303         scalar error = absTol*Foam::sqrt(1.0*Cf.size());
00304 
00305         if (debug)
00306         {
00307             Pout<< "    error:" << error << endl;
00308         }
00309 
00310         if
00311         (
00312             transform == ROTATIONAL
00313          || (
00314                 transform != TRANSLATIONAL
00315              && (sum(mag(nf & nr)) < Cf.size()-error)
00316             )
00317         )
00318         {
00319             // Type is rotation or unknown and normals not aligned
00320 
00321             separation_.setSize(0);
00322 
00323             forwardT_.setSize(Cf.size());
00324             reverseT_.setSize(Cf.size());
00325 
00326             forAll (forwardT_, facei)
00327             {
00328                 forwardT_[facei] = rotationTensor(-nr[facei], nf[facei]);
00329                 reverseT_[facei] = rotationTensor(nf[facei], -nr[facei]);
00330             }
00331 
00332             if (debug)
00333             {
00334                 Pout<< "    sum(mag(forwardT_ - forwardT_[0])):"
00335                     << sum(mag(forwardT_ - forwardT_[0]))
00336                     << endl;
00337             }
00338 
00339             if (sum(mag(forwardT_ - forwardT_[0])) < error)
00340             {
00341                 forwardT_.setSize(1);
00342                 reverseT_.setSize(1);
00343 
00344                 if (debug)
00345                 {
00346                     Pout<< "    difference in rotation less than"
00347                         << " local tolerance "
00348                         << error << ". Assuming uniform rotation." << endl;
00349                 }
00350             }
00351         }
00352         else
00353         {
00354             // Translational or unknown and normals aligned.
00355 
00356             forwardT_.setSize(0);
00357             reverseT_.setSize(0);
00358 
00359             separation_ = Cr - Cf;
00360 
00361             // Three situations:
00362             // - separation is zero. No separation.
00363             // - separation is same. Single separation vector.
00364             // - separation differs per face. Separation vectorField.
00365 
00366             // Check for different separation per face
00367             bool sameSeparation = true;
00368 
00369             forAll(separation_, facei)
00370             {
00371                 scalar smallSqr = sqr(smallDist[facei]);
00372 
00373                 if (magSqr(separation_[facei] - separation_[0]) > smallSqr)
00374                 {
00375                     if (debug)
00376                     {
00377                         Pout<< "    separation " << separation_[facei]
00378                             << " at " << facei
00379                             << " differs from separation[0] " << separation_[0]
00380                             << " by more than local tolerance "
00381                             << smallDist[facei]
00382                             << ". Assuming non-uniform separation." << endl;
00383                     }
00384                     sameSeparation = false;
00385                     break;
00386                 }
00387             }
00388 
00389             if (sameSeparation)
00390             {
00391                 // Check for zero separation (at 0 so everywhere)
00392                 if (magSqr(separation_[0]) < sqr(smallDist[0]))
00393                 {
00394                     if (debug)
00395                     {
00396                         Pout<< "    separation " << mag(separation_[0])
00397                             << " less than local tolerance " << smallDist[0]
00398                             << ". Assuming zero separation." << endl;
00399                     }
00400 
00401                     separation_.setSize(0);
00402                 }
00403                 else
00404                 {
00405                     if (debug)
00406                     {
00407                         Pout<< "    separation " << mag(separation_[0])
00408                             << " more than local tolerance " << smallDist[0]
00409                             << ". Assuming uniform separation." << endl;
00410                     }
00411 
00412                     separation_.setSize(1);
00413                 }
00414             }
00415         }
00416     }
00417 
00418     if (debug)
00419     {
00420         Pout<< "    separation_:" << separation_.size() << nl
00421             << "    forwardT size:" << forwardT_.size() << endl;
00422     }
00423 }
00424 
00425 
00426 // * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * * * * * //
00427 
00428 Foam::coupledPolyPatch::coupledPolyPatch
00429 (
00430     const word& name,
00431     const label size,
00432     const label start,
00433     const label index,
00434     const polyBoundaryMesh& bm
00435 )
00436 :
00437     polyPatch(name, size, start, index, bm)
00438 {}
00439 
00440 
00441 Foam::coupledPolyPatch::coupledPolyPatch
00442 (
00443     const word& name,
00444     const dictionary& dict,
00445     const label index,
00446     const polyBoundaryMesh& bm
00447 )
00448 :
00449     polyPatch(name, dict, index, bm)
00450 {}
00451 
00452 
00453 Foam::coupledPolyPatch::coupledPolyPatch
00454 (
00455     const coupledPolyPatch& pp,
00456     const polyBoundaryMesh& bm
00457 )
00458 :
00459     polyPatch(pp, bm)
00460 {}
00461 
00462 
00463 Foam::coupledPolyPatch::coupledPolyPatch
00464 (
00465     const coupledPolyPatch& pp,
00466     const polyBoundaryMesh& bm,
00467     const label index,
00468     const label newSize,
00469     const label newStart
00470 )
00471 :
00472     polyPatch(pp, bm, index, newSize, newStart)
00473 {}
00474 
00475 
00476 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
00477 
00478 Foam::coupledPolyPatch::~coupledPolyPatch()
00479 {}
00480 
00481 
00482 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines