Loading...
Searching...
No Matches
PrimitivePatchProjectPoints.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2011-2016 OpenFOAM Foundation
9 Copyright (C) 2020-2022 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27Description
28 For every point on the patch find the closest face on the target side.
29 Return a target face label for each patch point
30
31\*---------------------------------------------------------------------------*/
32
33#include "boolList.H"
34#include "pointHit.H"
35#include "objectHit.H"
36#include "bandCompression.H"
38// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
39
40template<class FaceList, class PointField>
41template<class ToPatch>
44(
45 const ToPatch& targetPatch,
46 const Field
47 <
49 >& projectionDirection,
52) const
53{
54 // The current patch is slave, i.e. it is being projected onto the target
55
56 if (projectionDirection.size() != nPoints())
57 {
59 << "Projection direction field does not correspond to "
60 << "patch points." << endl
61 << "Size: " << projectionDirection.size()
62 << " Number of points: " << nPoints()
63 << abort(FatalError);
64 }
65
66 const labelList& slavePointOrder = localPointOrder();
67
68 const labelList& slaveMeshPoints = meshPoints();
69
70 // Result
71 List<objectHit> result(nPoints());
72
73 const labelListList& masterFaceFaces = targetPatch.faceFaces();
74
75 const ToPatch& masterFaces = targetPatch;
76
77 const Field<point_type>& masterPoints = targetPatch.points();
78
79 // Estimate face centre of target side
80 Field<point_type> masterFaceCentres(targetPatch.size());
81
82 forAll(masterFaceCentres, facei)
83 {
84 masterFaceCentres[facei] =
85 average(masterFaces[facei].points(masterPoints));
86 }
87
88 // Algorithm:
89 // Loop through all points of the slave side. For every point find the
90 // radius for the current contact face. If the contact point falls inside
91 // the face and the radius is smaller than for all neighbouring faces,
92 // the contact is found. If not, visit the neighbour closest to the
93 // calculated contact point. If a single master face is visited more than
94 // twice, initiate n-squared search.
95
96 label curFace = 0;
97 label nNSquaredSearches = 0;
98
99 forAll(slavePointOrder, pointi)
100 {
101 // Pick up slave point and direction
102 const label curLocalPointLabel = slavePointOrder[pointi];
103
104 const point_type& curPoint =
105 points_[slaveMeshPoints[curLocalPointLabel]];
106
107 const point_type& curProjectionDir =
108 projectionDirection[curLocalPointLabel];
109
110 bool closer;
111
112 boolList visitedTargetFace(targetPatch.size(), false);
113 bool doNSquaredSearch = false;
114
115 bool foundEligible = false;
116
117 scalar sqrDistance = GREAT;
118
119 // Force the full search for the first point to ensure good
120 // starting face
121 if (pointi == 0)
122 {
123 doNSquaredSearch = true;
124 }
125 else
126 {
127 do
128 {
129 closer = false;
130 doNSquaredSearch = false;
131
132 // Calculate intersection with curFace
133 PointHit<point_type> curHit =
134 masterFaces[curFace].ray
135 (
136 curPoint,
137 curProjectionDir,
138 masterPoints,
139 alg,
140 dir
141 );
142
143 visitedTargetFace[curFace] = true;
144
145 if (curHit.hit())
146 {
147 result[curLocalPointLabel] = objectHit(true, curFace);
148
149 break;
150 }
151 else
152 {
153 // If a new miss is eligible, it is closer than
154 // any previous eligible miss (due to surface walk)
155
156 // Only grab the miss if it is eligible
157 if (curHit.eligibleMiss())
158 {
159 foundEligible = true;
160 result[curLocalPointLabel] = objectHit(false, curFace);
161 }
162
163 // Find the next likely face for intersection
164
165 // Calculate the miss point on the plane of the
166 // face. This is cooked (illogical!) for fastest
167 // surface walk.
168 //
169 point_type missPlanePoint =
170 curPoint + curProjectionDir*curHit.distance();
171
172 const labelList& masterNbrs = masterFaceFaces[curFace];
173
174 sqrDistance =
175 magSqr(missPlanePoint - masterFaceCentres[curFace]);
176
177 forAll(masterNbrs, nbrI)
178 {
179 if
180 (
181 magSqr
182 (
183 missPlanePoint
184 - masterFaceCentres[masterNbrs[nbrI]]
185 )
186 <= sqrDistance
187 )
188 {
189 closer = true;
190 curFace = masterNbrs[nbrI];
191 }
192 }
193
194 if (visitedTargetFace[curFace])
195 {
196 // This face has already been visited.
197 // Execute n-squared search
198 doNSquaredSearch = true;
199 break;
200 }
201 }
202
203 DebugInfo << '.';
204 } while (closer);
205 }
206
207 if
208 (
209 doNSquaredSearch || !foundEligible
210 )
211 {
212 nNSquaredSearches++;
213
214 DebugInfo << "p " << curLocalPointLabel << ": ";
215
216 result[curLocalPointLabel] = objectHit(false, -1);
217 scalar minDistance = GREAT;
218
219 forAll(masterFaces, facei)
220 {
221 PointHit<point_type> curHit =
222 masterFaces[facei].ray
223 (
224 curPoint,
225 curProjectionDir,
226 masterPoints,
227 alg,
228 dir
229 );
230
231 if (curHit.hit())
232 {
233 result[curLocalPointLabel] = objectHit(true, facei);
234 curFace = facei;
235
236 break;
237 }
238 else if (curHit.eligibleMiss())
239 {
240 // Calculate min distance
241 scalar missDist = curHit.point().dist(curPoint);
242
243 if (missDist < minDistance)
244 {
245 minDistance = missDist;
246
247 result[curLocalPointLabel] = objectHit(false, facei);
248 curFace = facei;
249 }
250 }
251 }
252
253 DebugInfo << result[curLocalPointLabel] << nl;
254 }
255 else
256 {
257 DebugInfo << 'x';
258 }
259 }
260
262 << nl << "Executed " << nNSquaredSearches
263 << " n-squared searches out of total of "
264 << nPoints() << endl;
265
266 return result;
268
269
270template<class FaceList, class PointField>
271template<class ToPatch>
274(
275 const ToPatch& targetPatch,
276 const Field
277 <
279 >& projectionDirection,
280 const intersection::algorithm alg,
282) const
283{
284 // The current patch is slave, i.e. it is being projected onto the target
285
286 if (projectionDirection.size() != this->size())
287 {
289 << "Projection direction field does not correspond to patch faces."
290 << endl << "Size: " << projectionDirection.size()
291 << " Number of points: " << this->size()
292 << abort(FatalError);
293 }
294
295 labelList slaveFaceOrder = meshTools::bandCompression(faceFaces());
296
297 // calculate master face centres
298 Field<point_type> masterFaceCentres(targetPatch.size());
299
300 const labelListList& masterFaceFaces = targetPatch.faceFaces();
301
302 const ToPatch& masterFaces = targetPatch;
303
304 const typename ToPatch::PointFieldType& masterPoints = targetPatch.points();
305
306 forAll(masterFaceCentres, facei)
307 {
308 masterFaceCentres[facei] =
309 masterFaces[facei].centre(masterPoints);
310 }
311
312 // Result
313 List<objectHit> result(this->size());
314
315 const PrimitivePatch<FaceList, PointField>& slaveFaces = *this;
316
317 const PointField& slaveGlobalPoints = points();
318
319 // Algorithm:
320 // Loop through all points of the slave side. For every point find the
321 // radius for the current contact face. If the contact point falls inside
322 // the face and the radius is smaller than for all neighbouring faces,
323 // the contact is found. If not, visit the neighbour closest to the
324 // calculated contact point. If a single master face is visited more than
325 // twice, initiate n-squared search.
326
327 label curFace = 0;
328 label nNSquaredSearches = 0;
329
330 forAll(slaveFaceOrder, facei)
331 {
332 // pick up slave point and direction
333 const label curLocalFaceLabel = slaveFaceOrder[facei];
334
335 const point& curFaceCentre =
336 slaveFaces[curLocalFaceLabel].centre(slaveGlobalPoints);
337
338 const vector& curProjectionDir =
339 projectionDirection[curLocalFaceLabel];
340
341 bool closer;
342
343 boolList visitedTargetFace(targetPatch.size(), false);
344 bool doNSquaredSearch = false;
345
346 bool foundEligible = false;
347
348 scalar sqrDistance = GREAT;
349
350 // Force the full search for the first point to ensure good
351 // starting face
352 if (facei == 0)
353 {
354 doNSquaredSearch = true;
355 }
356 else
357 {
358 do
359 {
360 closer = false;
361 doNSquaredSearch = false;
362
363 // Calculate intersection with curFace
364 PointHit<point_type> curHit =
365 masterFaces[curFace].ray
366 (
367 curFaceCentre,
368 curProjectionDir,
369 masterPoints,
370 alg,
371 dir
372 );
373
374 visitedTargetFace[curFace] = true;
375
376 if (curHit.hit())
377 {
378 result[curLocalFaceLabel] = objectHit(true, curFace);
379
380 break;
381 }
382 else
383 {
384 // If a new miss is eligible, it is closer than
385 // any previous eligible miss (due to surface walk)
386
387 // Only grab the miss if it is eligible
388 if (curHit.eligibleMiss())
389 {
390 foundEligible = true;
391 result[curLocalFaceLabel] = objectHit(false, curFace);
392 }
393
394 // Find the next likely face for intersection
395
396 // Calculate the miss point. This is
397 // cooked (illogical!) for fastest surface walk.
398 //
399 point_type missPlanePoint =
400 curFaceCentre + curProjectionDir*curHit.distance();
401
402 sqrDistance =
403 magSqr(missPlanePoint - masterFaceCentres[curFace]);
404
405 const labelList& masterNbrs = masterFaceFaces[curFace];
406
407 forAll(masterNbrs, nbrI)
408 {
409 if
410 (
411 magSqr
412 (
413 missPlanePoint
414 - masterFaceCentres[masterNbrs[nbrI]]
415 )
416 <= sqrDistance
417 )
418 {
419 closer = true;
420 curFace = masterNbrs[nbrI];
421 }
422 }
423
424 if (visitedTargetFace[curFace])
425 {
426 // This face has already been visited.
427 // Execute n-squared search
428 doNSquaredSearch = true;
429 break;
430 }
431 }
432
433 DebugInfo << '.';
434 } while (closer);
435 }
436
437 if (doNSquaredSearch || !foundEligible)
438 {
439 nNSquaredSearches++;
440
441 DebugInfo << "p " << curLocalFaceLabel << ": ";
442
443 result[curLocalFaceLabel] = objectHit(false, -1);
444 scalar minDistance = GREAT;
445
446 forAll(masterFaces, facei)
447 {
448 PointHit<point_type> curHit =
449 masterFaces[facei].ray
450 (
451 curFaceCentre,
452 curProjectionDir,
453 masterPoints,
454 alg,
455 dir
456 );
457
458 if (curHit.hit())
459 {
460 result[curLocalFaceLabel] = objectHit(true, facei);
461 curFace = facei;
462
463 break;
464 }
465 else if (curHit.eligibleMiss())
466 {
467 // Calculate min distance
468 scalar missDist = curHit.point().dist(curFaceCentre);
469
470 if (missDist < minDistance)
471 {
472 minDistance = missDist;
473
474 result[curLocalFaceLabel] = objectHit(false, facei);
475 curFace = facei;
476 }
477 }
478 }
479
480 DebugInfo << result[curLocalFaceLabel] << nl;
481 }
482 else
483 {
484 DebugInfo << 'x';
485 }
486 }
487
489 << nl
490 << "Executed " << nNSquaredSearches
491 << " n-squared searches out of total of "
492 << this->size() << endl;
493
494 return result;
495}
496
497
498// ************************************************************************* //
The bandCompression function renumbers the addressing such that the band of the matrix is reduced....
Generic templated field type that is much like a Foam::List except that it is expected to hold numeri...
Definition Field.H:172
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
Describes the interaction of a object and a (templated) point. It carries the info of a successful hi...
Definition pointHit.H:60
bool eligibleMiss() const noexcept
Is this an eligible miss.
Definition pointHit.H:153
scalar distance() const noexcept
Return distance to hit.
Definition pointHit.H:169
bool hit() const noexcept
Is there a hit.
Definition pointHit.H:145
const point_type & point() const noexcept
Return the point, no checks.
Definition pointHit.H:161
List< objectHit > projectFaceCentres(const ToPatch &targetPatch, const Field< point_type > &projectionDirection, const intersection::algorithm=intersection::FULL_RAY, const intersection::direction=intersection::VECTOR) const
Project vertices of patch onto another patch.
PrimitivePatch(const List< face > &faces, const const pointField &points)
std::remove_reference< PointField >::type::value_type point_type
The point type.
List< objectHit > projectPoints(const ToPatch &targetPatch, const Field< point_type > &projectionDirection, const intersection::algorithm=intersection::FULL_RAY, const intersection::direction=intersection::VECTOR) const
Project vertices of patch onto another patch.
void size(const label n)
Definition UList.H:118
const Vector< Cmpt > & centre(const Foam::UList< Vector< Cmpt > > &) const noexcept
Return this (for point which is a typedef to Vector<scalar>).
Definition VectorI.H:67
This class describes a combination of target object index and success flag. Behaves somewhat like std...
Definition objectHit.H:49
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
const pointField & points
label nPoints
#define DebugInfo
Report an information message using Foam::Info.
labelList bandCompression(const polyMesh &mesh)
Renumber (mesh) addressing to reduce the band of the mesh connectivity, using the Cuthill-McKee algor...
List< labelList > labelListList
List of labelList.
Definition labelList.H:38
List< label > labelList
A List of labels.
Definition List.H:62
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
errorManip< error > abort(error &err)
Definition errorManip.H:139
vector point
Point is a vector.
Definition point.H:37
List< bool > boolList
A List of bools.
Definition List.H:60
GeometricField< Type, pointPatchField, pointMesh > PointField
A point field for a given type.
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
Vector< scalar > vector
Definition vector.H:57
dimensioned< Type > average(const DimensionedField< Type, GeoMesh > &f1, const label comm)
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299