1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2008 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 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
26 For every point on the patch find the closest face on the target side.
27 Return a target face label for each patch point
29 \*---------------------------------------------------------------------------*/
33 #include "objectHit.H"
34 #include "bandCompression.H"
36 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
41 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
46 template<class> class FaceList,
51 template <class ToPatch>
52 List<objectHit> PrimitivePatch<Face, FaceList, PointField, PointType>::
55 const ToPatch& targetPatch,
56 const Field<PointType>& projectionDirection,
57 const intersection::algorithm alg,
58 const intersection::direction dir
61 // The current patch is slave, i.e. it is being projected onto the target
64 if (projectionDirection.size() != nPoints())
68 "PrimitivePatch<Face, FaceList, PointField, PointType>::"
69 "projectPoints(const PrimitivePatch& "
70 ", const Field<PointType>&) const"
71 ) << "Projection direction field does not correspond to "
72 << "patch points." << endl
73 << "Size: " << projectionDirection.size()
74 << " Number of points: " << nPoints()
78 const labelList& slavePointOrder = localPointOrder();
80 const labelList& slaveMeshPoints = meshPoints();
83 List<objectHit> result(nPoints());
85 const labelListList& masterFaceFaces = targetPatch.faceFaces();
87 const ToPatch& masterFaces = targetPatch;
89 const Field<PointType>& masterPoints = targetPatch.points();
91 // Estimate face centre of target side
92 Field<PointType> masterFaceCentres(targetPatch.size());
94 forAll (masterFaceCentres, faceI)
96 masterFaceCentres[faceI] =
97 average(masterFaces[faceI].points(masterPoints));
101 // Loop through all points of the slave side. For every point find the
102 // radius for the current contact face. If the contact point falls inside
103 // the face and the radius is smaller than for all neighbouring faces,
104 // the contact is found. If not, visit the neighbour closest to the
105 // calculated contact point. If a single master face is visited more than
106 // twice, initiate n-squared search.
109 label nNSquaredSearches = 0;
111 forAll (slavePointOrder, pointI)
113 // Pick up slave point and direction
114 const label curLocalPointLabel = slavePointOrder[pointI];
116 const PointType& curPoint =
117 points_[slaveMeshPoints[curLocalPointLabel]];
119 const PointType& curProjectionDir =
120 projectionDirection[curLocalPointLabel];
124 boolList visitedTargetFace(targetPatch.size(), false);
125 bool doNSquaredSearch = false;
127 bool foundEligible = false;
129 scalar sqrDistance = GREAT;
131 // Force the full search for the first point to ensure good
135 doNSquaredSearch = true;
142 doNSquaredSearch = false;
144 // Calculate intersection with curFace
145 PointHit<PointType> curHit =
146 masterFaces[curFace].ray
155 visitedTargetFace[curFace] = true;
159 result[curLocalPointLabel] = objectHit(true, curFace);
165 // If a new miss is eligible, it is closer than
166 // any previous eligible miss (due to surface walk)
168 // Only grab the miss if it is eligible
169 if (curHit.eligibleMiss())
171 foundEligible = true;
172 result[curLocalPointLabel] = objectHit(false, curFace);
175 // Find the next likely face for intersection
177 // Calculate the miss point on the plane of the
178 // face. This is cooked (illogical!) for fastest
181 PointType missPlanePoint =
182 curPoint + curProjectionDir*curHit.distance();
184 const labelList& masterNbrs = masterFaceFaces[curFace];
187 magSqr(missPlanePoint - masterFaceCentres[curFace]);
189 forAll (masterNbrs, nbrI)
196 - masterFaceCentres[masterNbrs[nbrI]]
202 curFace = masterNbrs[nbrI];
206 if (visitedTargetFace[curFace])
208 // This face has already been visited.
209 // Execute n-squared search
210 doNSquaredSearch = true;
215 if (debug) Info<< ".";
221 doNSquaredSearch || !foundEligible
228 Info<< "p " << curLocalPointLabel << ": ";
231 result[curLocalPointLabel] = objectHit(false, -1);
232 scalar minDistance = GREAT;
234 forAll (masterFaces, faceI)
236 PointHit<PointType> curHit =
237 masterFaces[faceI].ray
248 result[curLocalPointLabel] = objectHit(true, faceI);
253 else if (curHit.eligibleMiss())
255 // Calculate min distance
257 Foam::mag(curHit.missPoint() - curPoint);
259 if (missDist < minDistance)
261 minDistance = missDist;
263 result[curLocalPointLabel] = objectHit(false, faceI);
271 Info << result[curLocalPointLabel] << nl;
276 if (debug) Info<< "x";
282 Info<< nl << "Executed " << nNSquaredSearches
283 << " n-squared searches out of total of "
284 << nPoints() << endl;
294 template<class> class FaceList,
299 template <class ToPatch>
300 List<objectHit> PrimitivePatch<Face, FaceList, PointField, PointType>::
303 const ToPatch& targetPatch,
304 const Field<PointType>& projectionDirection,
305 const intersection::algorithm alg,
306 const intersection::direction dir
309 // The current patch is slave, i.e. it is being projected onto the target
312 if (projectionDirection.size() != this->size())
316 "labelList PrimitivePatch<Face, FaceList, PointField, PointType>::"
317 "projectFaceCentres(const PrimitivePatch& "
318 ", const Field<PointType>&) const"
319 ) << "Projection direction field does not correspond to patch faces."
320 << endl << "Size: " << projectionDirection.size()
321 << " Number of points: " << this->size()
322 << abort(FatalError);
325 labelList slaveFaceOrder = bandCompression(faceFaces());
327 // calculate master face centres
328 Field<PointType> masterFaceCentres(targetPatch.size());
330 const labelListList& masterFaceFaces = targetPatch.faceFaces();
332 const ToPatch& masterFaces = targetPatch;
334 const typename ToPatch::PointFieldType& masterPoints = targetPatch.points();
336 forAll (masterFaceCentres, faceI)
338 masterFaceCentres[faceI] =
339 masterFaces[faceI].centre(masterPoints);
343 List<objectHit> result(this->size());
345 const PrimitivePatch<Face, FaceList, PointField, PointType>& slaveFaces = *this;
346 const PointField& slaveGlobalPoints = points();
349 // Loop through all points of the slave side. For every point find the
350 // radius for the current contact face. If the contact point falls inside
351 // the face and the radius is smaller than for all neighbouring faces,
352 // the contact is found. If not, visit the neighbour closest to the
353 // calculated contact point. If a single master face is visited more than
354 // twice, initiate n-squared search.
357 label nNSquaredSearches = 0;
359 forAll (slaveFaceOrder, faceI)
361 // pick up slave point and direction
362 const label curLocalFaceLabel = slaveFaceOrder[faceI];
364 const point& curFaceCentre =
365 slaveFaces[curLocalFaceLabel].centre(slaveGlobalPoints);
367 const vector& curProjectionDir =
368 projectionDirection[curLocalFaceLabel];
372 boolList visitedTargetFace(targetPatch.size(), false);
373 bool doNSquaredSearch = false;
375 bool foundEligible = false;
377 scalar sqrDistance = GREAT;
379 // Force the full search for the first point to ensure good
383 doNSquaredSearch = true;
390 doNSquaredSearch = false;
392 // Calculate intersection with curFace
393 PointHit<PointType> curHit =
394 masterFaces[curFace].ray
403 visitedTargetFace[curFace] = true;
407 result[curLocalFaceLabel] = objectHit(true, curFace);
413 // If a new miss is eligible, it is closer than
414 // any previous eligible miss (due to surface walk)
416 // Only grab the miss if it is eligible
417 if (curHit.eligibleMiss())
419 foundEligible = true;
420 result[curLocalFaceLabel] = objectHit(false, curFace);
423 // Find the next likely face for intersection
425 // Calculate the miss point. This is
426 // cooked (illogical!) for fastest surface walk.
428 PointType missPlanePoint =
429 curFaceCentre + curProjectionDir*curHit.distance();
432 magSqr(missPlanePoint - masterFaceCentres[curFace]);
434 const labelList& masterNbrs = masterFaceFaces[curFace];
436 forAll (masterNbrs, nbrI)
443 - masterFaceCentres[masterNbrs[nbrI]]
449 curFace = masterNbrs[nbrI];
453 if (visitedTargetFace[curFace])
455 // This face has already been visited.
456 // Execute n-squared search
457 doNSquaredSearch = true;
462 if (debug) Info<< ".";
466 if (doNSquaredSearch || !foundEligible)
472 Info<< "p " << curLocalFaceLabel << ": ";
475 result[curLocalFaceLabel] = objectHit(false, -1);
476 scalar minDistance = GREAT;
478 forAll (masterFaces, faceI)
480 PointHit<PointType> curHit =
481 masterFaces[faceI].ray
492 result[curLocalFaceLabel] = objectHit(true, faceI);
497 else if (curHit.eligibleMiss())
499 // Calculate min distance
501 Foam::mag(curHit.missPoint() - curFaceCentre);
503 if (missDist < minDistance)
505 minDistance = missDist;
507 result[curLocalFaceLabel] = objectHit(false, faceI);
515 Info << result[curLocalFaceLabel] << nl;
520 if (debug) Info<< "x";
526 Info<< nl << "Executed " << nNSquaredSearches
527 << " n-squared searches out of total of "
528 << this->size() << endl;
535 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
537 } // End namespace Foam
539 // ************************************************************************* //