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

interactionLists.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) 2008-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 \*---------------------------------------------------------------------------*/
00025 
00026 #include "interactionLists.H"
00027 
00028 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00029 
00030 Foam::scalar Foam::interactionLists::transTol = 1e-12;
00031 
00032 
00033 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00034 
00035 void Foam::interactionLists::buildCellReferralLists()
00036 {
00037     Info<< nl << "Determining molecule referring schedule" << endl;
00038 
00039     const referredCellList& refIntL(ril());
00040 
00041     DynamicList<label> referralProcs;
00042 
00043     // Run through all referredCells to build list of interacting processors
00044 
00045     forAll(refIntL, rIL)
00046     {
00047         const referredCell& rC(refIntL[rIL]);
00048 
00049         if (findIndex(referralProcs, rC.sourceProc()) == -1)
00050         {
00051             referralProcs.append(rC.sourceProc());
00052         }
00053     }
00054 
00055     referralProcs.shrink();
00056 
00057 //     Pout << "referralProcs: " << nl << referralProcs << endl;
00058 
00059     List<DynamicList<label> > cellSendingReferralLists(referralProcs.size());
00060 
00061     // Use autoPtr to help GCC compilers (< 4.3) which suffer from core
00062     // language defect 391, i.e. require a copy-ctor to be present when passing
00063     // a temporary as an rvalue.
00064     List<DynamicList<autoPtr<DynamicList<label> > > >
00065         cellReceivingReferralLists(referralProcs.size());
00066 
00067     // Run through all referredCells again building up send and receive info
00068 
00069     forAll(refIntL, rIL)
00070     {
00071         const referredCell& rC(refIntL[rIL]);
00072 
00073         label rPI = findIndex(referralProcs, rC.sourceProc());
00074 
00075         DynamicList<autoPtr<DynamicList<label> > >& rRL(cellReceivingReferralLists[rPI]);
00076 
00077         DynamicList<label>& sRL(cellSendingReferralLists[rPI]);
00078 
00079         label existingSource = findIndex(sRL, rC.sourceCell());
00080 
00081         // Check to see if this source cell has already been allocated to
00082         // come to this processor.  If not, add the source cell to the sending
00083         // list and add the current referred cell to the receiving list.
00084 
00085         // It shouldn't be possible for the sending and receiving lists to be
00086         // different lengths, because their append operations happen at the
00087         // same time.
00088 
00089         if (existingSource == -1)
00090         {
00091             sRL.append(rC.sourceCell());
00092 
00093             rRL.append
00094             (
00095                 autoPtr<DynamicList<label> >(new DynamicList<label> (labelList(1,rIL)))
00096             );
00097         }
00098         else
00099         {
00100             rRL[existingSource]->append(rIL);
00101 
00102             rRL[existingSource]->shrink();
00103         }
00104     }
00105 
00106     forAll(referralProcs, rPI)
00107     {
00108         DynamicList<autoPtr<DynamicList<label> > >& rRL(cellReceivingReferralLists[rPI]);
00109 
00110         DynamicList<label>& sRL(cellSendingReferralLists[rPI]);
00111 
00112         sRL.shrink();
00113 
00114         rRL.shrink();
00115     }
00116 
00117     // It is assumed that cell exchange is reciprocal, if proc A has cells to
00118     // send to proc B, then proc B must have some to send to proc A.
00119 
00120     cellReceivingReferralLists_.setSize(referralProcs.size());
00121 
00122     cellSendingReferralLists_.setSize(referralProcs.size());
00123 
00124     forAll(referralProcs, rPI)
00125     {
00126         DynamicList<autoPtr<DynamicList<label> > >& rRL(cellReceivingReferralLists[rPI]);
00127 
00128         labelListList translLL(rRL.size());
00129 
00130         forAll(rRL, rRLI)
00131         {
00132             translLL[rRLI] = rRL[rRLI]();
00133         }
00134 
00135         cellReceivingReferralLists_[rPI] = receivingReferralList
00136         (
00137             referralProcs[rPI],
00138             translLL
00139         );
00140     }
00141 
00142     // Send sendingReferralLists to each interacting processor.
00143 
00144     forAll(referralProcs, rPI)
00145     {
00146 
00147         DynamicList<label>& sRL(cellSendingReferralLists[rPI]);
00148 
00149         if (referralProcs[rPI] != Pstream::myProcNo())
00150         {
00151             if (Pstream::parRun())
00152             {
00153                 OPstream toInteractingProc
00154                 (
00155                     Pstream::blocking,
00156                     referralProcs[rPI]
00157                 );
00158 
00159                 toInteractingProc << sendingReferralList
00160                 (
00161                     Pstream::myProcNo(),
00162                     sRL
00163                 );
00164             }
00165         }
00166     }
00167 
00168     // Receive sendingReferralLists from each interacting processor.
00169 
00170     forAll(referralProcs, rPI)
00171     {
00172         if (referralProcs[rPI] != Pstream::myProcNo())
00173         {
00174             if (Pstream::parRun())
00175             {
00176                 IPstream fromInteractingProc
00177                 (
00178                     Pstream::blocking,
00179                     referralProcs[rPI]
00180                 );
00181 
00182                 fromInteractingProc >> cellSendingReferralLists_[rPI];
00183             }
00184         }
00185         else
00186         {
00187             cellSendingReferralLists_[rPI] = sendingReferralList
00188             (
00189                 Pstream::myProcNo(),
00190                 cellSendingReferralLists[rPI]
00191             );
00192         }
00193     }
00194 }
00195 
00196 
00197 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00198 
00199 
00200 Foam::interactionLists::interactionLists
00201 (
00202     const polyMesh& mesh,
00203     scalar rCutMaxSqr,
00204     bool pointPointListBuild
00205 )
00206 :
00207     mesh_(mesh),
00208     rCutMaxSqr_(rCutMaxSqr),
00209     dil_(*this, pointPointListBuild),
00210     ril_(*this, pointPointListBuild),
00211     cellSendingReferralLists_(),
00212     cellReceivingReferralLists_()
00213 {
00214     buildCellReferralLists();
00215 }
00216 
00217 
00218 Foam::interactionLists::interactionLists(const polyMesh& mesh)
00219 :
00220     mesh_(mesh),
00221     dil_(*this),
00222     ril_(*this)
00223 {}
00224 
00225 
00226 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
00227 
00228 Foam::interactionLists::~interactionLists()
00229 {}
00230 
00231 
00232 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00233 
00234 bool Foam::interactionLists::testPointPointDistance
00235 (
00236     const label ptI,
00237     const label ptJ
00238 ) const
00239 {
00240     return (magSqr(mesh_.points()[ptI] - mesh_.points()[ptJ]) <= rCutMaxSqr_);
00241 }
00242 
00243 
00244 bool Foam::interactionLists::testEdgeEdgeDistance
00245 (
00246     const edge& eI,
00247     const edge& eJ
00248 ) const
00249 {
00250     const vector& eJs(mesh_.points()[eJ.start()]);
00251     const vector& eJe(mesh_.points()[eJ.end()]);
00252 
00253     return testEdgeEdgeDistance(eI, eJs, eJe);
00254 }
00255 
00256 
00257 bool Foam::interactionLists::testPointFaceDistance
00258 (
00259     const label p,
00260     const label faceNo
00261 ) const
00262 {
00263     const vector& pointPosition(mesh_.points()[p]);
00264 
00265     return testPointFaceDistance(pointPosition, faceNo);
00266 }
00267 
00268 
00269 bool Foam::interactionLists::testPointFaceDistance
00270 (
00271     const label p,
00272     const referredCell& refCell
00273 ) const
00274 {
00275     const vector& pointPosition(mesh_.points()[p]);
00276 
00277     forAll (refCell.faces(), rCF)
00278     {
00279         if
00280         (
00281             testPointFaceDistance
00282             (
00283                 pointPosition,
00284                 refCell.faces()[rCF],
00285                 refCell.vertexPositions(),
00286                 refCell.faceCentres()[rCF],
00287                 refCell.faceAreas()[rCF]
00288             )
00289         )
00290         {
00291             return true;
00292         }
00293     }
00294 
00295     return false;
00296 }
00297 
00298 
00299 bool Foam::interactionLists::testPointFaceDistance
00300 (
00301     const vectorList& pointsToTest,
00302     const label faceNo
00303 ) const
00304 {
00305     forAll(pointsToTest, pTT)
00306     {
00307         const vector& p(pointsToTest[pTT]);
00308 
00309         // if any point in the list is in range of the face
00310         // then the rest do not need to be tested and
00311         // true can be returned
00312 
00313         if (testPointFaceDistance(p, faceNo))
00314         {
00315             return true;
00316         }
00317     }
00318 
00319     return false;
00320 }
00321 
00322 
00323 bool Foam::interactionLists::testPointFaceDistance
00324 (
00325     const vector& p,
00326     const label faceNo
00327 ) const
00328 {
00329     const face& faceToTest(mesh_.faces()[faceNo]);
00330 
00331     const vector& faceC(mesh_.faceCentres()[faceNo]);
00332 
00333     const vector& faceA(mesh_.faceAreas()[faceNo]);
00334 
00335     const vectorList& points(mesh_.points());
00336 
00337     return testPointFaceDistance
00338     (
00339         p,
00340         faceToTest,
00341         points,
00342         faceC,
00343         faceA
00344     );
00345 }
00346 
00347 
00348 bool Foam::interactionLists::testPointFaceDistance
00349 (
00350     const vector& p,
00351     const labelList& faceToTest,
00352     const vectorList& points,
00353     const vector& faceC,
00354     const vector& faceA
00355 ) const
00356 {
00357     vector faceN(faceA/mag(faceA));
00358 
00359     scalar perpDist((p - faceC) & faceN);
00360 
00361     if (magSqr(perpDist) > rCutMaxSqr_)
00362     {
00363         return false;
00364     }
00365 
00366     vector pointOnPlane = (p - faceN * perpDist);
00367 
00368     if (magSqr(faceC - pointOnPlane) < rCutMaxSqr_*1e-8)
00369     {
00370         // If pointOnPlane is very close to the face centre
00371         // then defining the local axes will be inaccurate
00372         // and it is very likely that pointOnPlane will be
00373         // inside the face, so return true if the points
00374         // are in range to be safe
00375 
00376         return (magSqr(pointOnPlane - p) <= rCutMaxSqr_);
00377     }
00378 
00379     vector xAxis = (faceC - pointOnPlane)/mag(faceC - pointOnPlane);
00380 
00381     vector yAxis =
00382         ((faceC - pointOnPlane) ^ faceN)
00383        /mag((faceC - pointOnPlane) ^ faceN);
00384 
00385     List<vector2D> local2DVertices(faceToTest.size());
00386 
00387     forAll(faceToTest, fTT)
00388     {
00389         const vector& V(points[faceToTest[fTT]]);
00390 
00391         if (magSqr(V-p) <= rCutMaxSqr_)
00392         {
00393             return true;
00394         }
00395 
00396         local2DVertices[fTT] = vector2D
00397         (
00398             ((V - pointOnPlane) & xAxis),
00399             ((V - pointOnPlane) & yAxis)
00400         );
00401     }
00402 
00403     scalar localFaceCx((faceC - pointOnPlane) & xAxis);
00404 
00405     scalar la_valid = -1;
00406 
00407     forAll(local2DVertices, fV)
00408     {
00409         const vector2D& va(local2DVertices[fV]);
00410 
00411         const vector2D& vb
00412         (
00413             local2DVertices[(fV + 1) % local2DVertices.size()]
00414         );
00415 
00416         if (mag(vb.y()-va.y()) > SMALL)
00417         {
00418             scalar la =
00419                 (
00420                     va.x() - va.y()*((vb.x() - va.x())/(vb.y() - va.y()))
00421                 )
00422                /localFaceCx;
00423 
00424             scalar lv = -va.y()/(vb.y() - va.y());
00425 
00426 
00427             if (la >= 0 && la <= 1 && lv >= 0 && lv <= 1)
00428             {
00429                 la_valid = la;
00430 
00431                 break;
00432             }
00433         }
00434     }
00435 
00436     if (la_valid < 0)
00437     {
00438         // perpendicular point inside face, nearest point is pointOnPlane;
00439         return (magSqr(pointOnPlane-p) <= rCutMaxSqr_);
00440     }
00441     else
00442     {
00443         // perpendicular point outside face, nearest point is
00444         // on edge that generated la_valid;
00445         return
00446         (
00447             magSqr(pointOnPlane + la_valid*(faceC - pointOnPlane) - p)
00448          <= rCutMaxSqr_
00449         );
00450     }
00451 
00452     // if the algorithm hasn't returned anything by now then something has
00453     // gone wrong.
00454 
00455     FatalErrorIn("interactionLists.C") << nl
00456         << "point " << p << " to face " << faceToTest
00457         << " comparison did not find a nearest point"
00458         << " to be inside or outside face."
00459         << abort(FatalError);
00460 
00461     return false;
00462 }
00463 
00464 
00465 bool Foam::interactionLists::testEdgeEdgeDistance
00466 (
00467     const edge& eI,
00468     const vector& eJs,
00469     const vector& eJe
00470 ) const
00471 {
00472     vector a(eI.vec(mesh_.points()));
00473     vector b(eJe - eJs);
00474 
00475     const vector& eIs(mesh_.points()[eI.start()]);
00476 
00477     vector c(eJs - eIs);
00478 
00479     vector crossab = a ^ b;
00480     scalar magCrossSqr = magSqr(crossab);
00481 
00482     if (magCrossSqr > VSMALL)
00483     {
00484         // If the edges are parallel then a point-face
00485         // search will pick them up
00486 
00487         scalar s = ((c ^ b) & crossab)/magCrossSqr;
00488         scalar t = ((c ^ a) & crossab)/magCrossSqr;
00489 
00490         // Check for end points outside of range 0..1
00491         // If the closest point is outside this range
00492         // a point-face search will have found it.
00493 
00494         return
00495         (
00496             s >= 0
00497          && s <= 1
00498          && t >= 0
00499          && t <= 1
00500          && magSqr(eIs + a*s - eJs - b*t) <= rCutMaxSqr_
00501         );
00502     }
00503 
00504     return false;
00505 }
00506 
00507 
00508 const Foam::labelList Foam::interactionLists::realCellsInRangeOfSegment
00509 (
00510     const labelList& segmentFaces,
00511     const labelList& segmentEdges,
00512     const labelList& segmentPoints
00513 ) const
00514 {
00515     DynamicList<label> realCellsFoundInRange;
00516 
00517     forAll(segmentFaces, sF)
00518     {
00519         const label f = segmentFaces[sF];
00520 
00521         forAll (mesh_.points(), p)
00522         {
00523             if (testPointFaceDistance(p, f))
00524             {
00525                 const labelList& pCells(mesh_.pointCells()[p]);
00526 
00527                 forAll(pCells, pC)
00528                 {
00529                     const label cellI(pCells[pC]);
00530 
00531                     if (findIndex(realCellsFoundInRange, cellI) == -1)
00532                     {
00533                         realCellsFoundInRange.append(cellI);
00534                     }
00535                 }
00536             }
00537         }
00538     }
00539 
00540     forAll(segmentPoints, sP)
00541     {
00542         const label p = segmentPoints[sP];
00543 
00544         forAll(mesh_.faces(), f)
00545         {
00546             if (testPointFaceDistance(p, f))
00547             {
00548                 const label cellO(mesh_.faceOwner()[f]);
00549 
00550                 if (findIndex(realCellsFoundInRange, cellO) == -1)
00551                 {
00552                     realCellsFoundInRange.append(cellO);
00553                 }
00554 
00555                 if (mesh_.isInternalFace(f))
00556                 {
00557                     // boundary faces will not have neighbour information
00558 
00559                     const label cellN(mesh_.faceNeighbour()[f]);
00560 
00561                     if (findIndex(realCellsFoundInRange, cellN) == -1)
00562                     {
00563                         realCellsFoundInRange.append(cellN);
00564                     }
00565                 }
00566             }
00567         }
00568     }
00569 
00570     forAll(segmentEdges, sE)
00571     {
00572         const edge& eJ(mesh_.edges()[segmentEdges[sE]]);
00573 
00574         forAll (mesh_.edges(), edgeIIndex)
00575         {
00576             const edge& eI(mesh_.edges()[edgeIIndex]);
00577 
00578             if (testEdgeEdgeDistance(eI, eJ))
00579             {
00580                 const labelList& eICells(mesh_.edgeCells()[edgeIIndex]);
00581 
00582                 forAll(eICells, eIC)
00583                 {
00584                     const label cellI(eICells[eIC]);
00585 
00586                     if (findIndex(realCellsFoundInRange, cellI) == -1)
00587                     {
00588                         realCellsFoundInRange.append(cellI);
00589                     }
00590                 }
00591             }
00592         }
00593     }
00594 
00595     return realCellsFoundInRange.shrink();
00596 }
00597 
00598 
00599 const Foam::labelList Foam::interactionLists::referredCellsInRangeOfSegment
00600 (
00601     const List<referredCell>& referredInteractionList,
00602     const labelList& segmentFaces,
00603     const labelList& segmentEdges,
00604     const labelList& segmentPoints
00605 ) const
00606 {
00607     DynamicList<label> referredCellsFoundInRange;
00608 
00609     forAll(segmentFaces, sF)
00610     {
00611         const label f = segmentFaces[sF];
00612 
00613         forAll(referredInteractionList, rIL)
00614         {
00615             const vectorList& refCellPoints
00616                 = referredInteractionList[rIL].vertexPositions();
00617 
00618             if (testPointFaceDistance(refCellPoints, f))
00619             {
00620                 if (findIndex(referredCellsFoundInRange, rIL) == -1)
00621                 {
00622                     referredCellsFoundInRange.append(rIL);
00623                 }
00624             }
00625         }
00626     }
00627 
00628     forAll(segmentPoints, sP)
00629     {
00630         const label p = segmentPoints[sP];
00631 
00632         forAll(referredInteractionList, rIL)
00633         {
00634             const referredCell& refCell(referredInteractionList[rIL]);
00635 
00636             if (testPointFaceDistance(p, refCell))
00637             {
00638                 if (findIndex(referredCellsFoundInRange, rIL) == -1)
00639                 {
00640                     referredCellsFoundInRange.append(rIL);
00641                 }
00642             }
00643         }
00644     }
00645 
00646     forAll(segmentEdges, sE)
00647     {
00648         const edge& eI(mesh_.edges()[segmentEdges[sE]]);
00649 
00650         forAll(referredInteractionList, rIL)
00651         {
00652             const vectorList& refCellPoints
00653                 = referredInteractionList[rIL].vertexPositions();
00654 
00655             const edgeList& refCellEdges
00656                 = referredInteractionList[rIL].edges();
00657 
00658             forAll(refCellEdges, rCE)
00659             {
00660                 const edge& eJ(refCellEdges[rCE]);
00661 
00662                 if
00663                 (
00664                     testEdgeEdgeDistance
00665                     (
00666                         eI,
00667                         refCellPoints[eJ.start()],
00668                         refCellPoints[eJ.end()]
00669                     )
00670                 )
00671                 {
00672                     if(findIndex(referredCellsFoundInRange, rIL) == -1)
00673                     {
00674                         referredCellsFoundInRange.append(rIL);
00675                     }
00676                 }
00677             }
00678         }
00679     }
00680 
00681     return referredCellsFoundInRange.shrink();
00682 }
00683 
00684 
00685 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines