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

PrimitivePatchProjectPoints.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-2010 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 Description
00025     For every point on the patch find the closest face on the target side.
00026     Return a target face label for each patch point
00027 
00028 \*---------------------------------------------------------------------------*/
00029 
00030 #include <OpenFOAM/boolList.H>
00031 #include <OpenFOAM/PointHit_.H>
00032 #include <OpenFOAM/objectHit.H>
00033 #include <OpenFOAM/bandCompression.H>
00034 
00035 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00036 
00037 template
00038 <
00039     class Face,
00040     template<class> class FaceList,
00041     class PointField,
00042     class PointType
00043 >
00044 template <class ToPatch>
00045 Foam::List<Foam::objectHit>
00046 Foam::PrimitivePatch<Face, FaceList, PointField, PointType>::
00047 projectPoints
00048 (
00049     const ToPatch& targetPatch,
00050     const Field<PointType>& projectionDirection,
00051     const intersection::algorithm alg,
00052     const intersection::direction dir
00053 ) const
00054 {
00055     // The current patch is slave, i.e. it is being projected onto the target
00056 
00057     if (projectionDirection.size() != nPoints())
00058     {
00059         FatalErrorIn
00060         (
00061             "PrimitivePatch<Face, FaceList, PointField, PointType>::"
00062             "projectPoints(const PrimitivePatch& "
00063             ", const Field<PointType>&) const"
00064         )   << "Projection direction field does not correspond to "
00065             << "patch points." << endl
00066             << "Size: " << projectionDirection.size()
00067             << " Number of points: " << nPoints()
00068             << abort(FatalError);
00069     }
00070 
00071     const labelList& slavePointOrder = localPointOrder();
00072 
00073     const labelList& slaveMeshPoints = meshPoints();
00074 
00075     // Result
00076     List<objectHit> result(nPoints());
00077 
00078     const labelListList& masterFaceFaces = targetPatch.faceFaces();
00079 
00080     const ToPatch& masterFaces = targetPatch;
00081 
00082     const Field<PointType>& masterPoints = targetPatch.points();
00083 
00084     // Estimate face centre of target side
00085     Field<PointType> masterFaceCentres(targetPatch.size());
00086 
00087     forAll (masterFaceCentres, faceI)
00088     {
00089         masterFaceCentres[faceI] =
00090             average(masterFaces[faceI].points(masterPoints));
00091     }
00092 
00093     // Algorithm:
00094     // Loop through all points of the slave side. For every point find the
00095     // radius for the current contact face. If the contact point falls inside
00096     // the face and the radius is smaller than for all neighbouring faces,
00097     // the contact is found. If not, visit the neighbour closest to the
00098     // calculated contact point. If a single master face is visited more than
00099     // twice, initiate n-squared search.
00100 
00101     label curFace = 0;
00102     label nNSquaredSearches = 0;
00103 
00104     forAll (slavePointOrder, pointI)
00105     {
00106         // Pick up slave point and direction
00107         const label curLocalPointLabel = slavePointOrder[pointI];
00108 
00109         const PointType& curPoint =
00110             points_[slaveMeshPoints[curLocalPointLabel]];
00111 
00112         const PointType& curProjectionDir =
00113             projectionDirection[curLocalPointLabel];
00114 
00115         bool closer;
00116 
00117         boolList visitedTargetFace(targetPatch.size(), false);
00118         bool doNSquaredSearch = false;
00119 
00120         bool foundEligible = false;
00121 
00122         scalar sqrDistance = GREAT;
00123 
00124         // Force the full search for the first point to ensure good
00125         // starting face
00126         if (pointI == 0)
00127         {
00128             doNSquaredSearch = true;
00129         }
00130         else
00131         {
00132             do
00133             {
00134                 closer = false;
00135                 doNSquaredSearch = false;
00136 
00137                 // Calculate intersection with curFace
00138                 PointHit<PointType> curHit =
00139                     masterFaces[curFace].ray
00140                     (
00141                         curPoint,
00142                         curProjectionDir,
00143                         masterPoints,
00144                         alg,
00145                         dir
00146                     );
00147 
00148                 visitedTargetFace[curFace] = true;
00149 
00150                 if (curHit.hit())
00151                 {
00152                     result[curLocalPointLabel] = objectHit(true, curFace);
00153 
00154                     break;
00155                 }
00156                 else
00157                 {
00158                     // If a new miss is eligible, it is closer than
00159                     // any previous eligible miss (due to surface walk)
00160 
00161                     // Only grab the miss if it is eligible
00162                     if (curHit.eligibleMiss())
00163                     {
00164                         foundEligible = true;
00165                         result[curLocalPointLabel] = objectHit(false, curFace);
00166                     }
00167 
00168                     // Find the next likely face for intersection
00169 
00170                     // Calculate the miss point on the plane of the
00171                     // face.  This is cooked (illogical!) for fastest
00172                     // surface walk.
00173                     //
00174                     PointType missPlanePoint =
00175                         curPoint + curProjectionDir*curHit.distance();
00176 
00177                     const labelList& masterNbrs = masterFaceFaces[curFace];
00178 
00179                     sqrDistance =
00180                         magSqr(missPlanePoint - masterFaceCentres[curFace]);
00181 
00182                     forAll (masterNbrs, nbrI)
00183                     {
00184                         if
00185                         (
00186                             magSqr
00187                             (
00188                                 missPlanePoint
00189                               - masterFaceCentres[masterNbrs[nbrI]]
00190                             )
00191                          <= sqrDistance
00192                         )
00193                         {
00194                             closer = true;
00195                             curFace = masterNbrs[nbrI];
00196                         }
00197                     }
00198 
00199                     if (visitedTargetFace[curFace])
00200                     {
00201                         // This face has already been visited.
00202                         // Execute n-squared search
00203                         doNSquaredSearch = true;
00204                         break;
00205                     }
00206                 }
00207 
00208                 if (debug) Info<< ".";
00209             } while (closer);
00210         }
00211 
00212         if
00213         (
00214             doNSquaredSearch || !foundEligible
00215         )
00216         {
00217             nNSquaredSearches++;
00218 
00219             if (debug)
00220             {
00221                 Info<< "p " << curLocalPointLabel << ": ";
00222             }
00223 
00224             result[curLocalPointLabel] = objectHit(false, -1);
00225             scalar minDistance = GREAT;
00226 
00227             forAll (masterFaces, faceI)
00228             {
00229                 PointHit<PointType> curHit =
00230                     masterFaces[faceI].ray
00231                     (
00232                         curPoint,
00233                         curProjectionDir,
00234                         masterPoints,
00235                         alg,
00236                         dir
00237                     );
00238 
00239                 if (curHit.hit())
00240                 {
00241                     result[curLocalPointLabel] = objectHit(true, faceI);
00242                     curFace = faceI;
00243 
00244                     break;
00245                 }
00246                 else if (curHit.eligibleMiss())
00247                 {
00248                     // Calculate min distance
00249                     scalar missDist =
00250                         Foam::mag(curHit.missPoint() - curPoint);
00251 
00252                     if (missDist < minDistance)
00253                     {
00254                         minDistance = missDist;
00255 
00256                         result[curLocalPointLabel] = objectHit(false, faceI);
00257                         curFace = faceI;
00258                     }
00259                 }
00260             }
00261 
00262             if (debug)
00263             {
00264                 Info << result[curLocalPointLabel] << nl;
00265             }
00266         }
00267         else
00268         {
00269             if (debug) Info<< "x";
00270         }
00271     }
00272 
00273     if (debug)
00274     {
00275         Info<< nl << "Executed " << nNSquaredSearches
00276             << " n-squared searches out of total of "
00277             << nPoints() << endl;
00278     }
00279 
00280     return result;
00281 }
00282 
00283 
00284 template
00285 <
00286     class Face,
00287     template<class> class FaceList,
00288     class PointField,
00289     class PointType
00290 >
00291 template <class ToPatch>
00292 Foam::List<Foam::objectHit>
00293 Foam::PrimitivePatch<Face, FaceList, PointField, PointType>::
00294 projectFaceCentres
00295 (
00296     const ToPatch& targetPatch,
00297     const Field<PointType>& projectionDirection,
00298     const intersection::algorithm alg,
00299     const intersection::direction dir
00300 ) const
00301 {
00302     // The current patch is slave, i.e. it is being projected onto the target
00303 
00304     if (projectionDirection.size() != this->size())
00305     {
00306         FatalErrorIn
00307         (
00308             "labelList PrimitivePatch<Face, FaceList, PointField, PointType>::"
00309             "projectFaceCentres(const PrimitivePatch& "
00310             ", const Field<PointType>&) const"
00311         )   << "Projection direction field does not correspond to patch faces."
00312             << endl << "Size: " << projectionDirection.size()
00313             << " Number of points: " << this->size()
00314             << abort(FatalError);
00315     }
00316 
00317     labelList slaveFaceOrder = bandCompression(faceFaces());
00318 
00319     // calculate master face centres
00320     Field<PointType> masterFaceCentres(targetPatch.size());
00321 
00322     const labelListList& masterFaceFaces = targetPatch.faceFaces();
00323 
00324     const ToPatch& masterFaces = targetPatch;
00325 
00326     const typename ToPatch::PointFieldType& masterPoints = targetPatch.points();
00327 
00328     forAll (masterFaceCentres, faceI)
00329     {
00330         masterFaceCentres[faceI] =
00331             masterFaces[faceI].centre(masterPoints);
00332     }
00333 
00334     // Result
00335     List<objectHit> result(this->size());
00336 
00337     const PrimitivePatch<Face, FaceList, PointField, PointType>& slaveFaces = *this;
00338     const PointField& slaveGlobalPoints = points();
00339 
00340     // Algorithm:
00341     // Loop through all points of the slave side. For every point find the
00342     // radius for the current contact face. If the contact point falls inside
00343     // the face and the radius is smaller than for all neighbouring faces,
00344     // the contact is found. If not, visit the neighbour closest to the
00345     // calculated contact point. If a single master face is visited more than
00346     // twice, initiate n-squared search.
00347 
00348     label curFace = 0;
00349     label nNSquaredSearches = 0;
00350 
00351     forAll (slaveFaceOrder, faceI)
00352     {
00353         // pick up slave point and direction
00354         const label curLocalFaceLabel = slaveFaceOrder[faceI];
00355 
00356         const point& curFaceCentre =
00357             slaveFaces[curLocalFaceLabel].centre(slaveGlobalPoints);
00358 
00359         const vector& curProjectionDir =
00360             projectionDirection[curLocalFaceLabel];
00361 
00362         bool closer;
00363 
00364         boolList visitedTargetFace(targetPatch.size(), false);
00365         bool doNSquaredSearch = false;
00366 
00367         bool foundEligible = false;
00368 
00369         scalar sqrDistance = GREAT;
00370 
00371         // Force the full search for the first point to ensure good
00372         // starting face
00373         if (faceI == 0)
00374         {
00375             doNSquaredSearch = true;
00376         }
00377         else
00378         {
00379             do
00380             {
00381                 closer = false;
00382                 doNSquaredSearch = false;
00383 
00384                 // Calculate intersection with curFace
00385                 PointHit<PointType> curHit =
00386                     masterFaces[curFace].ray
00387                     (
00388                         curFaceCentre,
00389                         curProjectionDir,
00390                         masterPoints,
00391                         alg,
00392                         dir
00393                     );
00394 
00395                 visitedTargetFace[curFace] = true;
00396 
00397                 if (curHit.hit())
00398                 {
00399                     result[curLocalFaceLabel] = objectHit(true, curFace);
00400 
00401                     break;
00402                 }
00403                 else
00404                 {
00405                     // If a new miss is eligible, it is closer than
00406                     // any previous eligible miss (due to surface walk)
00407 
00408                     // Only grab the miss if it is eligible
00409                     if (curHit.eligibleMiss())
00410                     {
00411                         foundEligible = true;
00412                         result[curLocalFaceLabel] = objectHit(false, curFace);
00413                     }
00414 
00415                     // Find the next likely face for intersection
00416 
00417                     // Calculate the miss point.  This is
00418                     // cooked (illogical!) for fastest surface walk.
00419                     //
00420                     PointType missPlanePoint =
00421                         curFaceCentre + curProjectionDir*curHit.distance();
00422 
00423                     sqrDistance =
00424                         magSqr(missPlanePoint - masterFaceCentres[curFace]);
00425 
00426                     const labelList& masterNbrs = masterFaceFaces[curFace];
00427 
00428                     forAll (masterNbrs, nbrI)
00429                     {
00430                         if
00431                         (
00432                             magSqr
00433                             (
00434                                 missPlanePoint
00435                               - masterFaceCentres[masterNbrs[nbrI]]
00436                             )
00437                          <= sqrDistance
00438                         )
00439                         {
00440                             closer = true;
00441                             curFace = masterNbrs[nbrI];
00442                         }
00443                     }
00444 
00445                     if (visitedTargetFace[curFace])
00446                     {
00447                         // This face has already been visited.
00448                         // Execute n-squared search
00449                         doNSquaredSearch = true;
00450                         break;
00451                     }
00452                 }
00453 
00454                 if (debug) Info<< ".";
00455             } while (closer);
00456         }
00457 
00458         if (doNSquaredSearch || !foundEligible)
00459         {
00460             nNSquaredSearches++;
00461 
00462             if (debug)
00463             {
00464                 Info<< "p " << curLocalFaceLabel << ": ";
00465             }
00466 
00467             result[curLocalFaceLabel] = objectHit(false, -1);
00468             scalar minDistance = GREAT;
00469 
00470             forAll (masterFaces, faceI)
00471             {
00472                 PointHit<PointType> curHit =
00473                     masterFaces[faceI].ray
00474                     (
00475                         curFaceCentre,
00476                         curProjectionDir,
00477                         masterPoints,
00478                         alg,
00479                         dir
00480                     );
00481 
00482                 if (curHit.hit())
00483                 {
00484                     result[curLocalFaceLabel] = objectHit(true, faceI);
00485                     curFace = faceI;
00486 
00487                     break;
00488                 }
00489                 else if (curHit.eligibleMiss())
00490                 {
00491                     // Calculate min distance
00492                     scalar missDist =
00493                         Foam::mag(curHit.missPoint() - curFaceCentre);
00494 
00495                     if (missDist < minDistance)
00496                     {
00497                         minDistance = missDist;
00498 
00499                         result[curLocalFaceLabel] = objectHit(false, faceI);
00500                         curFace = faceI;
00501                     }
00502                 }
00503             }
00504 
00505             if (debug)
00506             {
00507                 Info << result[curLocalFaceLabel] << nl;
00508             }
00509         }
00510         else
00511         {
00512             if (debug) Info<< "x";
00513         }
00514     }
00515 
00516     if (debug)
00517     {
00518         Info<< nl << "Executed " << nNSquaredSearches
00519             << " n-squared searches out of total of "
00520             << this->size() << endl;
00521     }
00522 
00523     return result;
00524 }
00525 
00526 
00527 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines