1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 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 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
41 template<class> class FaceList,
46 template <class ToPatch>
47 Foam::List<Foam::objectHit>
48 Foam::PrimitivePatch<Face, FaceList, PointField, PointType>::
51 const ToPatch& targetPatch,
52 const Field<PointType>& projectionDirection,
53 const intersection::algorithm alg,
54 const intersection::direction dir
57 // The current patch is slave, i.e. it is being projected onto the target
59 if (projectionDirection.size() != nPoints())
63 "PrimitivePatch<Face, FaceList, PointField, PointType>::"
64 "projectPoints(const PrimitivePatch& "
65 ", const Field<PointType>&) const"
66 ) << "Projection direction field does not correspond to "
67 << "patch points." << endl
68 << "Size: " << projectionDirection.size()
69 << " Number of points: " << nPoints()
73 const labelList& slavePointOrder = localPointOrder();
75 const labelList& slaveMeshPoints = meshPoints();
78 List<objectHit> result(nPoints());
80 const labelListList& masterFaceFaces = targetPatch.faceFaces();
82 const ToPatch& masterFaces = targetPatch;
84 const Field<PointType>& masterPoints = targetPatch.points();
86 // Estimate face centre of target side
87 Field<PointType> masterFaceCentres(targetPatch.size());
89 forAll (masterFaceCentres, faceI)
91 masterFaceCentres[faceI] =
92 average(masterFaces[faceI].points(masterPoints));
96 // Loop through all points of the slave side. For every point find the
97 // radius for the current contact face. If the contact point falls inside
98 // the face and the radius is smaller than for all neighbouring faces,
99 // the contact is found. If not, visit the neighbour closest to the
100 // calculated contact point. If a single master face is visited more than
101 // twice, initiate n-squared search.
104 label nNSquaredSearches = 0;
106 forAll (slavePointOrder, pointI)
108 // Pick up slave point and direction
109 const label curLocalPointLabel = slavePointOrder[pointI];
111 const PointType& curPoint =
112 points_[slaveMeshPoints[curLocalPointLabel]];
114 const PointType& curProjectionDir =
115 projectionDirection[curLocalPointLabel];
119 boolList visitedTargetFace(targetPatch.size(), false);
120 bool doNSquaredSearch = false;
122 bool foundEligible = false;
124 scalar sqrDistance = GREAT;
126 // Force the full search for the first point to ensure good
130 doNSquaredSearch = true;
137 doNSquaredSearch = false;
139 // Calculate intersection with curFace
140 PointHit<PointType> curHit =
141 masterFaces[curFace].ray
150 visitedTargetFace[curFace] = true;
154 result[curLocalPointLabel] = objectHit(true, curFace);
160 // If a new miss is eligible, it is closer than
161 // any previous eligible miss (due to surface walk)
163 // Only grab the miss if it is eligible
164 if (curHit.eligibleMiss())
166 foundEligible = true;
167 result[curLocalPointLabel] = objectHit(false, curFace);
170 // Find the next likely face for intersection
172 // Calculate the miss point on the plane of the
173 // face. This is cooked (illogical!) for fastest
176 PointType missPlanePoint =
177 curPoint + curProjectionDir*curHit.distance();
179 const labelList& masterNbrs = masterFaceFaces[curFace];
182 magSqr(missPlanePoint - masterFaceCentres[curFace]);
184 forAll (masterNbrs, nbrI)
191 - masterFaceCentres[masterNbrs[nbrI]]
197 curFace = masterNbrs[nbrI];
201 if (visitedTargetFace[curFace])
203 // This face has already been visited.
204 // Execute n-squared search
205 doNSquaredSearch = true;
210 if (debug) Info<< ".";
216 doNSquaredSearch || !foundEligible
223 Info<< "p " << curLocalPointLabel << ": ";
226 result[curLocalPointLabel] = objectHit(false, -1);
227 scalar minDistance = GREAT;
229 forAll (masterFaces, faceI)
231 PointHit<PointType> curHit =
232 masterFaces[faceI].ray
243 result[curLocalPointLabel] = objectHit(true, faceI);
248 else if (curHit.eligibleMiss())
250 // Calculate min distance
252 Foam::mag(curHit.missPoint() - curPoint);
254 if (missDist < minDistance)
256 minDistance = missDist;
258 result[curLocalPointLabel] = objectHit(false, faceI);
266 Info << result[curLocalPointLabel] << nl;
271 if (debug) Info<< "x";
277 Info<< nl << "Executed " << nNSquaredSearches
278 << " n-squared searches out of total of "
279 << nPoints() << endl;
289 template<class> class FaceList,
294 template <class ToPatch>
295 Foam::List<Foam::objectHit>
296 Foam::PrimitivePatch<Face, FaceList, PointField, PointType>::
299 const ToPatch& targetPatch,
300 const Field<PointType>& projectionDirection,
301 const intersection::algorithm alg,
302 const intersection::direction dir
305 // The current patch is slave, i.e. it is being projected onto the target
307 if (projectionDirection.size() != this->size())
311 "labelList PrimitivePatch<Face, FaceList, PointField, PointType>::"
312 "projectFaceCentres(const PrimitivePatch& "
313 ", const Field<PointType>&) const"
314 ) << "Projection direction field does not correspond to patch faces."
315 << endl << "Size: " << projectionDirection.size()
316 << " Number of points: " << this->size()
317 << abort(FatalError);
320 labelList slaveFaceOrder = bandCompression(faceFaces());
322 // calculate master face centres
323 Field<PointType> masterFaceCentres(targetPatch.size());
325 const labelListList& masterFaceFaces = targetPatch.faceFaces();
327 const ToPatch& masterFaces = targetPatch;
329 const typename ToPatch::PointFieldType& masterPoints = targetPatch.points();
331 forAll (masterFaceCentres, faceI)
333 masterFaceCentres[faceI] =
334 masterFaces[faceI].centre(masterPoints);
338 List<objectHit> result(this->size());
340 const PrimitivePatch<Face, FaceList, PointField, PointType>& slaveFaces = *this;
341 const PointField& slaveGlobalPoints = points();
344 // Loop through all points of the slave side. For every point find the
345 // radius for the current contact face. If the contact point falls inside
346 // the face and the radius is smaller than for all neighbouring faces,
347 // the contact is found. If not, visit the neighbour closest to the
348 // calculated contact point. If a single master face is visited more than
349 // twice, initiate n-squared search.
352 label nNSquaredSearches = 0;
354 forAll (slaveFaceOrder, faceI)
356 // pick up slave point and direction
357 const label curLocalFaceLabel = slaveFaceOrder[faceI];
359 const point& curFaceCentre =
360 slaveFaces[curLocalFaceLabel].centre(slaveGlobalPoints);
362 const vector& curProjectionDir =
363 projectionDirection[curLocalFaceLabel];
367 boolList visitedTargetFace(targetPatch.size(), false);
368 bool doNSquaredSearch = false;
370 bool foundEligible = false;
372 scalar sqrDistance = GREAT;
374 // Force the full search for the first point to ensure good
378 doNSquaredSearch = true;
385 doNSquaredSearch = false;
387 // Calculate intersection with curFace
388 PointHit<PointType> curHit =
389 masterFaces[curFace].ray
398 visitedTargetFace[curFace] = true;
402 result[curLocalFaceLabel] = objectHit(true, curFace);
408 // If a new miss is eligible, it is closer than
409 // any previous eligible miss (due to surface walk)
411 // Only grab the miss if it is eligible
412 if (curHit.eligibleMiss())
414 foundEligible = true;
415 result[curLocalFaceLabel] = objectHit(false, curFace);
418 // Find the next likely face for intersection
420 // Calculate the miss point. This is
421 // cooked (illogical!) for fastest surface walk.
423 PointType missPlanePoint =
424 curFaceCentre + curProjectionDir*curHit.distance();
427 magSqr(missPlanePoint - masterFaceCentres[curFace]);
429 const labelList& masterNbrs = masterFaceFaces[curFace];
431 forAll (masterNbrs, nbrI)
438 - masterFaceCentres[masterNbrs[nbrI]]
444 curFace = masterNbrs[nbrI];
448 if (visitedTargetFace[curFace])
450 // This face has already been visited.
451 // Execute n-squared search
452 doNSquaredSearch = true;
457 if (debug) Info<< ".";
461 if (doNSquaredSearch || !foundEligible)
467 Info<< "p " << curLocalFaceLabel << ": ";
470 result[curLocalFaceLabel] = objectHit(false, -1);
471 scalar minDistance = GREAT;
473 forAll (masterFaces, faceI)
475 PointHit<PointType> curHit =
476 masterFaces[faceI].ray
487 result[curLocalFaceLabel] = objectHit(true, faceI);
492 else if (curHit.eligibleMiss())
494 // Calculate min distance
496 Foam::mag(curHit.missPoint() - curFaceCentre);
498 if (missDist < minDistance)
500 minDistance = missDist;
502 result[curLocalFaceLabel] = objectHit(false, faceI);
510 Info << result[curLocalFaceLabel] << nl;
515 if (debug) Info<< "x";
521 Info<< nl << "Executed " << nNSquaredSearches
522 << " n-squared searches out of total of "
523 << this->size() << endl;
530 // ************************************************************************* //