1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
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
13 the Free Software Foundation, either version 3 of the License, or
14 (at your 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, see <http://www.gnu.org/licenses/>.
25 For every point on the patch find the closest face on the target side.
26 Return a target face label for each patch point
28 \*---------------------------------------------------------------------------*/
32 #include "objectHit.H"
33 #include "bandCompression.H"
35 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
40 template<class> class FaceList,
44 template <class ToPatch>
45 Foam::List<Foam::objectHit>
46 Foam::PrimitivePatch<Face, FaceList, PointField, PointType>::
49 const ToPatch& targetPatch,
50 const Field<PointType>& projectionDirection,
51 const intersection::algorithm alg,
52 const intersection::direction dir
55 // The current patch is slave, i.e. it is being projected onto the target
57 if (projectionDirection.size() != nPoints())
61 "PrimitivePatch<Face, FaceList, PointField, PointType>::"
62 "projectPoints(const PrimitivePatch& "
63 ", const Field<PointType>&) const"
64 ) << "Projection direction field does not correspond to "
65 << "patch points." << endl
66 << "Size: " << projectionDirection.size()
67 << " Number of points: " << nPoints()
71 const labelList& slavePointOrder = localPointOrder();
73 const labelList& slaveMeshPoints = meshPoints();
76 List<objectHit> result(nPoints());
78 const labelListList& masterFaceFaces = targetPatch.faceFaces();
80 const ToPatch& masterFaces = targetPatch;
82 const Field<PointType>& masterPoints = targetPatch.points();
84 // Estimate face centre of target side
85 Field<PointType> masterFaceCentres(targetPatch.size());
87 forAll(masterFaceCentres, faceI)
89 masterFaceCentres[faceI] =
90 average(masterFaces[faceI].points(masterPoints));
94 // Loop through all points of the slave side. For every point find the
95 // radius for the current contact face. If the contact point falls inside
96 // the face and the radius is smaller than for all neighbouring faces,
97 // the contact is found. If not, visit the neighbour closest to the
98 // calculated contact point. If a single master face is visited more than
99 // twice, initiate n-squared search.
102 label nNSquaredSearches = 0;
104 forAll(slavePointOrder, pointI)
106 // Pick up slave point and direction
107 const label curLocalPointLabel = slavePointOrder[pointI];
109 const PointType& curPoint =
110 points_[slaveMeshPoints[curLocalPointLabel]];
112 const PointType& curProjectionDir =
113 projectionDirection[curLocalPointLabel];
117 boolList visitedTargetFace(targetPatch.size(), false);
118 bool doNSquaredSearch = false;
120 bool foundEligible = false;
122 scalar sqrDistance = GREAT;
124 // Force the full search for the first point to ensure good
128 doNSquaredSearch = true;
135 doNSquaredSearch = false;
137 // Calculate intersection with curFace
138 PointHit<PointType> curHit =
139 masterFaces[curFace].ray
148 visitedTargetFace[curFace] = true;
152 result[curLocalPointLabel] = objectHit(true, curFace);
158 // If a new miss is eligible, it is closer than
159 // any previous eligible miss (due to surface walk)
161 // Only grab the miss if it is eligible
162 if (curHit.eligibleMiss())
164 foundEligible = true;
165 result[curLocalPointLabel] = objectHit(false, curFace);
168 // Find the next likely face for intersection
170 // Calculate the miss point on the plane of the
171 // face. This is cooked (illogical!) for fastest
174 PointType missPlanePoint =
175 curPoint + curProjectionDir*curHit.distance();
177 const labelList& masterNbrs = masterFaceFaces[curFace];
180 magSqr(missPlanePoint - masterFaceCentres[curFace]);
182 forAll(masterNbrs, nbrI)
189 - masterFaceCentres[masterNbrs[nbrI]]
195 curFace = masterNbrs[nbrI];
199 if (visitedTargetFace[curFace])
201 // This face has already been visited.
202 // Execute n-squared search
203 doNSquaredSearch = true;
208 if (debug) Info<< ".";
214 doNSquaredSearch || !foundEligible
221 Info<< "p " << curLocalPointLabel << ": ";
224 result[curLocalPointLabel] = objectHit(false, -1);
225 scalar minDistance = GREAT;
227 forAll(masterFaces, faceI)
229 PointHit<PointType> curHit =
230 masterFaces[faceI].ray
241 result[curLocalPointLabel] = objectHit(true, faceI);
246 else if (curHit.eligibleMiss())
248 // Calculate min distance
250 Foam::mag(curHit.missPoint() - curPoint);
252 if (missDist < minDistance)
254 minDistance = missDist;
256 result[curLocalPointLabel] = objectHit(false, faceI);
264 Info<< result[curLocalPointLabel] << nl;
269 if (debug) Info<< "x";
275 Info<< nl << "Executed " << nNSquaredSearches
276 << " n-squared searches out of total of "
277 << nPoints() << endl;
287 template<class> class FaceList,
291 template <class ToPatch>
292 Foam::List<Foam::objectHit>
293 Foam::PrimitivePatch<Face, FaceList, PointField, PointType>::
296 const ToPatch& targetPatch,
297 const Field<PointType>& projectionDirection,
298 const intersection::algorithm alg,
299 const intersection::direction dir
302 // The current patch is slave, i.e. it is being projected onto the target
304 if (projectionDirection.size() != this->size())
308 "labelList PrimitivePatch<Face, FaceList, PointField, PointType>::"
309 "projectFaceCentres(const PrimitivePatch& "
310 ", const Field<PointType>&) const"
311 ) << "Projection direction field does not correspond to patch faces."
312 << endl << "Size: " << projectionDirection.size()
313 << " Number of points: " << this->size()
314 << abort(FatalError);
317 labelList slaveFaceOrder = bandCompression(faceFaces());
319 // calculate master face centres
320 Field<PointType> masterFaceCentres(targetPatch.size());
322 const labelListList& masterFaceFaces = targetPatch.faceFaces();
324 const ToPatch& masterFaces = targetPatch;
326 const typename ToPatch::PointFieldType& masterPoints = targetPatch.points();
328 forAll(masterFaceCentres, faceI)
330 masterFaceCentres[faceI] =
331 masterFaces[faceI].centre(masterPoints);
335 List<objectHit> result(this->size());
337 const PrimitivePatch<Face, FaceList, PointField, PointType>& slaveFaces =
340 const PointField& slaveGlobalPoints = points();
343 // Loop through all points of the slave side. For every point find the
344 // radius for the current contact face. If the contact point falls inside
345 // the face and the radius is smaller than for all neighbouring faces,
346 // the contact is found. If not, visit the neighbour closest to the
347 // calculated contact point. If a single master face is visited more than
348 // twice, initiate n-squared search.
351 label nNSquaredSearches = 0;
353 forAll(slaveFaceOrder, faceI)
355 // pick up slave point and direction
356 const label curLocalFaceLabel = slaveFaceOrder[faceI];
358 const point& curFaceCentre =
359 slaveFaces[curLocalFaceLabel].centre(slaveGlobalPoints);
361 const vector& curProjectionDir =
362 projectionDirection[curLocalFaceLabel];
366 boolList visitedTargetFace(targetPatch.size(), false);
367 bool doNSquaredSearch = false;
369 bool foundEligible = false;
371 scalar sqrDistance = GREAT;
373 // Force the full search for the first point to ensure good
377 doNSquaredSearch = true;
384 doNSquaredSearch = false;
386 // Calculate intersection with curFace
387 PointHit<PointType> curHit =
388 masterFaces[curFace].ray
397 visitedTargetFace[curFace] = true;
401 result[curLocalFaceLabel] = objectHit(true, curFace);
407 // If a new miss is eligible, it is closer than
408 // any previous eligible miss (due to surface walk)
410 // Only grab the miss if it is eligible
411 if (curHit.eligibleMiss())
413 foundEligible = true;
414 result[curLocalFaceLabel] = objectHit(false, curFace);
417 // Find the next likely face for intersection
419 // Calculate the miss point. This is
420 // cooked (illogical!) for fastest surface walk.
422 PointType missPlanePoint =
423 curFaceCentre + curProjectionDir*curHit.distance();
426 magSqr(missPlanePoint - masterFaceCentres[curFace]);
428 const labelList& masterNbrs = masterFaceFaces[curFace];
430 forAll(masterNbrs, nbrI)
437 - masterFaceCentres[masterNbrs[nbrI]]
443 curFace = masterNbrs[nbrI];
447 if (visitedTargetFace[curFace])
449 // This face has already been visited.
450 // Execute n-squared search
451 doNSquaredSearch = true;
456 if (debug) Info<< ".";
460 if (doNSquaredSearch || !foundEligible)
466 Info<< "p " << curLocalFaceLabel << ": ";
469 result[curLocalFaceLabel] = objectHit(false, -1);
470 scalar minDistance = GREAT;
472 forAll(masterFaces, faceI)
474 PointHit<PointType> curHit =
475 masterFaces[faceI].ray
486 result[curLocalFaceLabel] = objectHit(true, faceI);
491 else if (curHit.eligibleMiss())
493 // Calculate min distance
495 Foam::mag(curHit.missPoint() - curFaceCentre);
497 if (missDist < minDistance)
499 minDistance = missDist;
501 result[curLocalFaceLabel] = objectHit(false, faceI);
509 Info<< result[curLocalFaceLabel] << nl;
514 if (debug) Info<< "x";
520 Info<< nl << "Executed " << nNSquaredSearches
521 << " n-squared searches out of total of "
522 << this->size() << endl;
529 // ************************************************************************* //