1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 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, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "interactionLists.H"
29 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
31 Foam::scalar Foam::interactionLists::transTol = 1e-12;
34 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
36 void Foam::interactionLists::buildCellReferralLists()
38 Info<< nl << "Determining molecule referring schedule" << endl;
40 const referredCellList& refIntL(ril());
42 DynamicList<label> referralProcs;
44 // Run through all referredCells to build list of interacting processors
48 const referredCell& rC(refIntL[rIL]);
50 if (findIndex(referralProcs, rC.sourceProc()) == -1)
52 referralProcs.append(rC.sourceProc());
56 referralProcs.shrink();
58 // Pout << "referralProcs: " << nl << referralProcs << endl;
60 List<DynamicList<label> > cellSendingReferralLists(referralProcs.size());
62 List<DynamicList<DynamicList<label> > >
63 cellReceivingReferralLists(referralProcs.size());
65 // Run through all referredCells again building up send and receive info
69 const referredCell& rC(refIntL[rIL]);
71 label rPI = findIndex(referralProcs, rC.sourceProc());
73 DynamicList<DynamicList<label> >& rRL(cellReceivingReferralLists[rPI]);
75 DynamicList<label>& sRL(cellSendingReferralLists[rPI]);
77 label existingSource = findIndex(sRL, rC.sourceCell());
79 // Check to see if this source cell has already been allocated to
80 // come to this processor. If not, add the source cell to the sending
81 // list and add the current referred cell to the receiving list.
83 // It shouldn't be possible for the sending and receiving lists to be
84 // different lengths, because their append operations happen at the
87 if (existingSource == -1)
89 sRL.append(rC.sourceCell());
93 DynamicList<label> (labelList(1,rIL))
98 rRL[existingSource].append(rIL);
100 rRL[existingSource].shrink();
104 forAll(referralProcs, rPI)
106 DynamicList<DynamicList<label> >& rRL(cellReceivingReferralLists[rPI]);
108 DynamicList<label>& sRL(cellSendingReferralLists[rPI]);
115 // It is assumed that cell exchange is reciprocal, if proc A has cells to
116 // send to proc B, then proc B must have some to send to proc A.
118 cellReceivingReferralLists_.setSize(referralProcs.size());
120 cellSendingReferralLists_.setSize(referralProcs.size());
122 forAll(referralProcs, rPI)
124 DynamicList<DynamicList<label> >& rRL(cellReceivingReferralLists[rPI]);
126 labelListList translLL(rRL.size());
130 translLL[rRLI] = rRL[rRLI];
133 cellReceivingReferralLists_[rPI] = receivingReferralList
140 // Send sendingReferralLists to each interacting processor.
142 forAll(referralProcs, rPI)
145 DynamicList<label>& sRL(cellSendingReferralLists[rPI]);
147 if (referralProcs[rPI] != Pstream::myProcNo())
149 if (Pstream::parRun())
151 OPstream toInteractingProc
157 toInteractingProc << sendingReferralList
166 // Receive sendingReferralLists from each interacting processor.
168 forAll(referralProcs, rPI)
170 if (referralProcs[rPI] != Pstream::myProcNo())
172 if (Pstream::parRun())
174 IPstream fromInteractingProc
180 fromInteractingProc >> cellSendingReferralLists_[rPI];
185 cellSendingReferralLists_[rPI] = sendingReferralList
188 cellSendingReferralLists[rPI]
195 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
198 Foam::interactionLists::interactionLists
200 const polyMesh& mesh,
202 bool pointPointListBuild
206 rCutMaxSqr_(rCutMaxSqr),
207 dil_(*this, pointPointListBuild),
208 ril_(*this, pointPointListBuild),
209 cellSendingReferralLists_(),
210 cellReceivingReferralLists_()
212 buildCellReferralLists();
216 Foam::interactionLists::interactionLists(const polyMesh& mesh)
224 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
226 Foam::interactionLists::~interactionLists()
230 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
232 bool Foam::interactionLists::testPointPointDistance
238 return (magSqr(mesh_.points()[ptI] - mesh_.points()[ptJ]) <= rCutMaxSqr_);
242 bool Foam::interactionLists::testEdgeEdgeDistance
248 const vector& eJs(mesh_.points()[eJ.start()]);
249 const vector& eJe(mesh_.points()[eJ.end()]);
251 return testEdgeEdgeDistance(eI, eJs, eJe);
255 bool Foam::interactionLists::testPointFaceDistance
261 const vector& pointPosition(mesh_.points()[p]);
263 return testPointFaceDistance(pointPosition, faceNo);
267 bool Foam::interactionLists::testPointFaceDistance
270 const referredCell& refCell
273 const vector& pointPosition(mesh_.points()[p]);
275 forAll (refCell.faces(), rCF)
279 testPointFaceDistance
282 refCell.faces()[rCF],
283 refCell.vertexPositions(),
284 refCell.faceCentres()[rCF],
285 refCell.faceAreas()[rCF]
297 bool Foam::interactionLists::testPointFaceDistance
299 const vectorList& pointsToTest,
303 forAll(pointsToTest, pTT)
305 const vector& p(pointsToTest[pTT]);
307 // if any point in the list is in range of the face
308 // then the rest do not need to be tested and
309 // true can be returned
311 if (testPointFaceDistance(p, faceNo))
321 bool Foam::interactionLists::testPointFaceDistance
327 const face& faceToTest(mesh_.faces()[faceNo]);
329 const vector& faceC(mesh_.faceCentres()[faceNo]);
331 const vector& faceA(mesh_.faceAreas()[faceNo]);
333 const vectorList& points(mesh_.points());
335 return testPointFaceDistance
346 bool Foam::interactionLists::testPointFaceDistance
349 const labelList& faceToTest,
350 const vectorList& points,
355 vector faceN(faceA/mag(faceA));
357 scalar perpDist((p - faceC) & faceN);
359 if (magSqr(perpDist) > rCutMaxSqr_)
364 vector pointOnPlane = (p - faceN * perpDist);
366 if (magSqr(faceC - pointOnPlane) < rCutMaxSqr_*1e-8)
368 // If pointOnPlane is very close to the face centre
369 // then defining the local axes will be inaccurate
370 // and it is very likely that pointOnPlane will be
371 // inside the face, so return true if the points
372 // are in range to be safe
374 return (magSqr(pointOnPlane - p) <= rCutMaxSqr_);
377 vector xAxis = (faceC - pointOnPlane)/mag(faceC - pointOnPlane);
380 ((faceC - pointOnPlane) ^ faceN)
381 /mag((faceC - pointOnPlane) ^ faceN);
383 List<vector2D> local2DVertices(faceToTest.size());
385 forAll(faceToTest, fTT)
387 const vector& V(points[faceToTest[fTT]]);
389 if (magSqr(V-p) <= rCutMaxSqr_)
394 local2DVertices[fTT] = vector2D
396 ((V - pointOnPlane) & xAxis),
397 ((V - pointOnPlane) & yAxis)
401 scalar localFaceCx((faceC - pointOnPlane) & xAxis);
403 scalar la_valid = -1;
405 forAll(local2DVertices, fV)
407 const vector2D& va(local2DVertices[fV]);
411 local2DVertices[(fV + 1) % local2DVertices.size()]
414 if (mag(vb.y()-va.y()) > SMALL)
418 va.x() - va.y()*((vb.x() - va.x())/(vb.y() - va.y()))
422 scalar lv = -va.y()/(vb.y() - va.y());
425 if (la >= 0 && la <= 1 && lv >= 0 && lv <= 1)
436 // perpendicular point inside face, nearest point is pointOnPlane;
437 return (magSqr(pointOnPlane-p) <= rCutMaxSqr_);
441 // perpendicular point outside face, nearest point is
442 // on edge that generated la_valid;
445 magSqr(pointOnPlane + la_valid*(faceC - pointOnPlane) - p)
450 // if the algorithm hasn't returned anything by now then something has
453 FatalErrorIn("interactionLists.C") << nl
454 << "point " << p << " to face " << faceToTest
455 << " comparison did not find a nearest point"
456 << " to be inside or outside face."
457 << abort(FatalError);
463 bool Foam::interactionLists::testEdgeEdgeDistance
470 vector a(eI.vec(mesh_.points()));
473 const vector& eIs(mesh_.points()[eI.start()]);
477 vector crossab = a ^ b;
478 scalar magCrossSqr = magSqr(crossab);
480 if (magCrossSqr > VSMALL)
482 // If the edges are parallel then a point-face
483 // search will pick them up
485 scalar s = ((c ^ b) & crossab)/magCrossSqr;
486 scalar t = ((c ^ a) & crossab)/magCrossSqr;
488 // Check for end points outside of range 0..1
489 // If the closest point is outside this range
490 // a point-face search will have found it.
498 && magSqr(eIs + a*s - eJs - b*t) <= rCutMaxSqr_
506 const Foam::labelList Foam::interactionLists::realCellsInRangeOfSegment
508 const labelList& segmentFaces,
509 const labelList& segmentEdges,
510 const labelList& segmentPoints
513 DynamicList<label> realCellsFoundInRange;
515 forAll(segmentFaces, sF)
517 const label f = segmentFaces[sF];
519 forAll (mesh_.points(), p)
521 if (testPointFaceDistance(p, f))
523 const labelList& pCells(mesh_.pointCells()[p]);
527 const label cellI(pCells[pC]);
529 if (findIndex(realCellsFoundInRange, cellI) == -1)
531 realCellsFoundInRange.append(cellI);
538 forAll(segmentPoints, sP)
540 const label p = segmentPoints[sP];
542 forAll(mesh_.faces(), f)
544 if (testPointFaceDistance(p, f))
546 const label cellO(mesh_.faceOwner()[f]);
548 if (findIndex(realCellsFoundInRange, cellO) == -1)
550 realCellsFoundInRange.append(cellO);
553 if (mesh_.isInternalFace(f))
555 // boundary faces will not have neighbour information
557 const label cellN(mesh_.faceNeighbour()[f]);
559 if (findIndex(realCellsFoundInRange, cellN) == -1)
561 realCellsFoundInRange.append(cellN);
568 forAll(segmentEdges, sE)
570 const edge& eJ(mesh_.edges()[segmentEdges[sE]]);
572 forAll (mesh_.edges(), edgeIIndex)
574 const edge& eI(mesh_.edges()[edgeIIndex]);
576 if (testEdgeEdgeDistance(eI, eJ))
578 const labelList& eICells(mesh_.edgeCells()[edgeIIndex]);
582 const label cellI(eICells[eIC]);
584 if (findIndex(realCellsFoundInRange, cellI) == -1)
586 realCellsFoundInRange.append(cellI);
593 return realCellsFoundInRange.shrink();
597 const Foam::labelList Foam::interactionLists::referredCellsInRangeOfSegment
599 const List<referredCell>& referredInteractionList,
600 const labelList& segmentFaces,
601 const labelList& segmentEdges,
602 const labelList& segmentPoints
605 DynamicList<label> referredCellsFoundInRange;
607 forAll(segmentFaces, sF)
609 const label f = segmentFaces[sF];
611 forAll(referredInteractionList, rIL)
613 const vectorList& refCellPoints
614 = referredInteractionList[rIL].vertexPositions();
616 if (testPointFaceDistance(refCellPoints, f))
618 if (findIndex(referredCellsFoundInRange, rIL) == -1)
620 referredCellsFoundInRange.append(rIL);
626 forAll(segmentPoints, sP)
628 const label p = segmentPoints[sP];
630 forAll(referredInteractionList, rIL)
632 const referredCell& refCell(referredInteractionList[rIL]);
634 if (testPointFaceDistance(p, refCell))
636 if (findIndex(referredCellsFoundInRange, rIL) == -1)
638 referredCellsFoundInRange.append(rIL);
644 forAll(segmentEdges, sE)
646 const edge& eI(mesh_.edges()[segmentEdges[sE]]);
648 forAll(referredInteractionList, rIL)
650 const vectorList& refCellPoints
651 = referredInteractionList[rIL].vertexPositions();
653 const edgeList& refCellEdges
654 = referredInteractionList[rIL].edges();
656 forAll(refCellEdges, rCE)
658 const edge& eJ(refCellEdges[rCE]);
665 refCellPoints[eJ.start()],
666 refCellPoints[eJ.end()]
670 if(findIndex(referredCellsFoundInRange, rIL) == -1)
672 referredCellsFoundInRange.append(rIL);
679 return referredCellsFoundInRange.shrink();
683 // ************************************************************************* //