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,
45 template <class ToPatch>
46 Foam::List<Foam::objectHit>
47 Foam::PrimitivePatch<Face, FaceList, PointField, PointType>::
50 const ToPatch& targetPatch,
51 const Field<PointType>& projectionDirection,
52 const intersection::algorithm alg,
53 const intersection::direction dir
56 // The current patch is slave, i.e. it is being projected onto the target
58 if (projectionDirection.size() != nPoints())
62 "PrimitivePatch<Face, FaceList, PointField, PointType>::"
63 "projectPoints(const PrimitivePatch& "
64 ", const Field<PointType>&) const"
65 ) << "Projection direction field does not correspond to "
66 << "patch points." << endl
67 << "Size: " << projectionDirection.size()
68 << " Number of points: " << nPoints()
72 const labelList& slavePointOrder = localPointOrder();
74 const labelList& slaveMeshPoints = meshPoints();
77 List<objectHit> result(nPoints());
79 const labelListList& masterFaceFaces = targetPatch.faceFaces();
81 const ToPatch& masterFaces = targetPatch;
83 const Field<PointType>& masterPoints = targetPatch.points();
85 // Estimate face centre of target side
86 Field<PointType> masterFaceCentres(targetPatch.size());
88 forAll (masterFaceCentres, faceI)
90 masterFaceCentres[faceI] =
91 average(masterFaces[faceI].points(masterPoints));
95 // Loop through all points of the slave side. For every point find the
96 // radius for the current contact face. If the contact point falls inside
97 // the face and the radius is smaller than for all neighbouring faces,
98 // the contact is found. If not, visit the neighbour closest to the
99 // calculated contact point. If a single master face is visited more than
100 // twice, initiate n-squared search.
103 label nNSquaredSearches = 0;
105 forAll (slavePointOrder, pointI)
107 // Pick up slave point and direction
108 const label curLocalPointLabel = slavePointOrder[pointI];
110 const PointType& curPoint =
111 points_[slaveMeshPoints[curLocalPointLabel]];
113 const PointType& curProjectionDir =
114 projectionDirection[curLocalPointLabel];
118 boolList visitedTargetFace(targetPatch.size(), false);
119 bool doNSquaredSearch = false;
121 bool foundEligible = false;
123 scalar sqrDistance = GREAT;
125 // Force the full search for the first point to ensure good
129 doNSquaredSearch = true;
136 doNSquaredSearch = false;
138 // Calculate intersection with curFace
139 PointHit<PointType> curHit =
140 masterFaces[curFace].ray
149 visitedTargetFace[curFace] = true;
153 result[curLocalPointLabel] = objectHit(true, curFace);
159 // If a new miss is eligible, it is closer than
160 // any previous eligible miss (due to surface walk)
162 // Only grab the miss if it is eligible
163 if (curHit.eligibleMiss())
165 foundEligible = true;
166 result[curLocalPointLabel] = objectHit(false, curFace);
169 // Find the next likely face for intersection
171 // Calculate the miss point on the plane of the
172 // face. This is cooked (illogical!) for fastest
175 PointType missPlanePoint =
176 curPoint + curProjectionDir*curHit.distance();
178 const labelList& masterNbrs = masterFaceFaces[curFace];
181 magSqr(missPlanePoint - masterFaceCentres[curFace]);
183 forAll (masterNbrs, nbrI)
190 - masterFaceCentres[masterNbrs[nbrI]]
196 curFace = masterNbrs[nbrI];
200 if (visitedTargetFace[curFace])
202 // This face has already been visited.
203 // Execute n-squared search
204 doNSquaredSearch = true;
209 if (debug) Info<< ".";
215 doNSquaredSearch || !foundEligible
222 Info<< "p " << curLocalPointLabel << ": ";
225 result[curLocalPointLabel] = objectHit(false, -1);
226 scalar minDistance = GREAT;
228 forAll (masterFaces, faceI)
230 PointHit<PointType> curHit =
231 masterFaces[faceI].ray
242 result[curLocalPointLabel] = objectHit(true, faceI);
247 else if (curHit.eligibleMiss())
249 // Calculate min distance
251 Foam::mag(curHit.missPoint() - curPoint);
253 if (missDist < minDistance)
255 minDistance = missDist;
257 result[curLocalPointLabel] = objectHit(false, faceI);
265 Info << result[curLocalPointLabel] << nl;
270 if (debug) Info<< "x";
276 Info<< nl << "Executed " << nNSquaredSearches
277 << " n-squared searches out of total of "
278 << nPoints() << endl;
288 template<class> class FaceList,
292 template <class ToPatch>
293 Foam::List<Foam::objectHit>
294 Foam::PrimitivePatch<Face, FaceList, PointField, PointType>::
297 const ToPatch& targetPatch,
298 const Field<PointType>& projectionDirection,
299 const intersection::algorithm alg,
300 const intersection::direction dir
303 // The current patch is slave, i.e. it is being projected onto the target
305 if (projectionDirection.size() != this->size())
309 "labelList PrimitivePatch<Face, FaceList, PointField, PointType>::"
310 "projectFaceCentres(const PrimitivePatch& "
311 ", const Field<PointType>&) const"
312 ) << "Projection direction field does not correspond to patch faces."
313 << endl << "Size: " << projectionDirection.size()
314 << " Number of points: " << this->size()
315 << abort(FatalError);
318 labelList slaveFaceOrder = bandCompression(faceFaces());
320 // calculate master face centres
321 Field<PointType> masterFaceCentres(targetPatch.size());
323 const labelListList& masterFaceFaces = targetPatch.faceFaces();
325 const ToPatch& masterFaces = targetPatch;
327 const typename ToPatch::PointFieldType& masterPoints = targetPatch.points();
329 forAll (masterFaceCentres, faceI)
331 masterFaceCentres[faceI] =
332 masterFaces[faceI].centre(masterPoints);
336 List<objectHit> result(this->size());
338 const PrimitivePatch<Face, FaceList, PointField, PointType>& slaveFaces = *this;
339 const PointField& slaveGlobalPoints = points();
342 // Loop through all points of the slave side. For every point find the
343 // radius for the current contact face. If the contact point falls inside
344 // the face and the radius is smaller than for all neighbouring faces,
345 // the contact is found. If not, visit the neighbour closest to the
346 // calculated contact point. If a single master face is visited more than
347 // twice, initiate n-squared search.
350 label nNSquaredSearches = 0;
352 forAll (slaveFaceOrder, faceI)
354 // pick up slave point and direction
355 const label curLocalFaceLabel = slaveFaceOrder[faceI];
357 const point& curFaceCentre =
358 slaveFaces[curLocalFaceLabel].centre(slaveGlobalPoints);
360 const vector& curProjectionDir =
361 projectionDirection[curLocalFaceLabel];
365 boolList visitedTargetFace(targetPatch.size(), false);
366 bool doNSquaredSearch = false;
368 bool foundEligible = false;
370 scalar sqrDistance = GREAT;
372 // Force the full search for the first point to ensure good
376 doNSquaredSearch = true;
383 doNSquaredSearch = false;
385 // Calculate intersection with curFace
386 PointHit<PointType> curHit =
387 masterFaces[curFace].ray
396 visitedTargetFace[curFace] = true;
400 result[curLocalFaceLabel] = objectHit(true, curFace);
406 // If a new miss is eligible, it is closer than
407 // any previous eligible miss (due to surface walk)
409 // Only grab the miss if it is eligible
410 if (curHit.eligibleMiss())
412 foundEligible = true;
413 result[curLocalFaceLabel] = objectHit(false, curFace);
416 // Find the next likely face for intersection
418 // Calculate the miss point. This is
419 // cooked (illogical!) for fastest surface walk.
421 PointType missPlanePoint =
422 curFaceCentre + curProjectionDir*curHit.distance();
425 magSqr(missPlanePoint - masterFaceCentres[curFace]);
427 const labelList& masterNbrs = masterFaceFaces[curFace];
429 forAll (masterNbrs, nbrI)
436 - masterFaceCentres[masterNbrs[nbrI]]
442 curFace = masterNbrs[nbrI];
446 if (visitedTargetFace[curFace])
448 // This face has already been visited.
449 // Execute n-squared search
450 doNSquaredSearch = true;
455 if (debug) Info<< ".";
459 if (doNSquaredSearch || !foundEligible)
465 Info<< "p " << curLocalFaceLabel << ": ";
468 result[curLocalFaceLabel] = objectHit(false, -1);
469 scalar minDistance = GREAT;
471 forAll (masterFaces, faceI)
473 PointHit<PointType> curHit =
474 masterFaces[faceI].ray
485 result[curLocalFaceLabel] = objectHit(true, faceI);
490 else if (curHit.eligibleMiss())
492 // Calculate min distance
494 Foam::mag(curHit.missPoint() - curFaceCentre);
496 if (missDist < minDistance)
498 minDistance = missDist;
500 result[curLocalFaceLabel] = objectHit(false, faceI);
508 Info << result[curLocalFaceLabel] << nl;
513 if (debug) Info<< "x";
519 Info<< nl << "Executed " << nNSquaredSearches
520 << " n-squared searches out of total of "
521 << this->size() << endl;
528 // ************************************************************************* //