Loading...
Searching...
No Matches
CalcPatchToPatchWeights.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
27\*---------------------------------------------------------------------------*/
28
30#include "objectHit.H"
31#include "pointHit.H"
32
33// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
34
35namespace Foam
36{
37
38// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
39
40template<class FromPatch, class ToPatch>
41void PatchToPatchInterpolation<FromPatch, ToPatch>::calcPointAddressing() const
42{
43 // Calculate pointWeights
44
45 pointWeightsPtr_.reset(new FieldField<Field, scalar>(toPatch_.nPoints()));
46 auto& pointWeights = *pointWeightsPtr_;
47
48 pointDistancePtr_.reset(new scalarField(toPatch_.nPoints(), GREAT));
49 auto& pointDistance = *pointDistancePtr_;
50
51 const pointField& fromPatchPoints = fromPatch_.localPoints();
52 const auto& fromPatchFaces = fromPatch_.localFaces();
53
54 const pointField& toPatchPoints = toPatch_.localPoints();
55 const vectorField& projectionDirection = toPatch_.pointNormals();
56 const edgeList& toPatchEdges = toPatch_.edges();
57 const labelListList& toPatchPointEdges = toPatch_.pointEdges();
58
59 if (debug)
60 {
61 Info<< "projecting points" << endl;
62 }
63
64 List<objectHit> proj =
65 toPatch_.projectPoints(fromPatch_, projectionDirection, alg_, dir_);
66
67 pointAddressingPtr_.reset(new labelList(proj.size(), -1));
68 auto& pointAddressing = *pointAddressingPtr_;
69
70 bool doWeights = false;
71
72 forAll(pointAddressing, pointi)
73 {
74 doWeights = false;
75
76 const auto& hitFace = fromPatchFaces[proj[pointi].hitObject()];
77
78 point hitPoint = Zero;
79
80 if (proj[pointi].hit())
81 {
82 // A hit exists
83 doWeights = true;
84
85 pointAddressing[pointi] = proj[pointi].hitObject();
86
87 pointHit curHit =
88 hitFace.ray
89 (
90 toPatchPoints[pointi],
91 projectionDirection[pointi],
92 fromPatchPoints,
93 alg_,
94 dir_
95 );
96
97 // Grab distance to target
99 {
100 pointDistance[pointi] =
101 hitFace.contactSphereDiameter
102 (
103 toPatchPoints[pointi],
104 projectionDirection[pointi],
105 fromPatchPoints
106 );
107 }
108 else
109 {
110 pointDistance[pointi] = curHit.distance();
111 }
112
113 // Grab hit point
114 hitPoint = curHit.hitPoint();
115 }
116 else if (projectionTol_ > SMALL)
117 {
118 // Check for a near miss
119 pointHit ph =
120 hitFace.ray
121 (
122 toPatchPoints[pointi],
123 projectionDirection[pointi],
124 fromPatchPoints,
125 alg_,
126 dir_
127 );
128
129 scalar dist =
131 (
132 toPatchPoints[pointi]
133 + projectionDirection[pointi]*ph.distance()
134 - ph.missPoint()
135 );
136
137 // Calculate the local tolerance
138 scalar minEdgeLength = GREAT;
139
140 // Do shortest edge of hit object
141 edgeList hitFaceEdges =
142 fromPatchFaces[proj[pointi].hitObject()].edges();
143
144 forAll(hitFaceEdges, edgeI)
145 {
146 minEdgeLength =
147 min
148 (
149 minEdgeLength,
150 hitFaceEdges[edgeI].mag(fromPatchPoints)
151 );
152 }
153
154 const labelList& curEdges = toPatchPointEdges[pointi];
155
156 forAll(curEdges, edgeI)
157 {
158 minEdgeLength =
159 min
160 (
161 minEdgeLength,
162 toPatchEdges[curEdges[edgeI]].mag(toPatchPoints)
163 );
164 }
165
166 if (dist < minEdgeLength*projectionTol_)
167 {
168 // This point is being corrected
169 doWeights = true;
170
171 pointAddressing[pointi] = proj[pointi].hitObject();
172
173 // Grab nearest point on face as hit point
174 hitPoint = ph.missPoint();
175
176 // Grab distance to target
178 {
179 pointDistance[pointi] =
180 hitFace.contactSphereDiameter
181 (
182 toPatchPoints[pointi],
183 projectionDirection[pointi],
184 fromPatchPoints
185 );
186 }
187 else
188 {
189 pointDistance[pointi] =
190 (
191 projectionDirection[pointi]
192 /mag(projectionDirection[pointi])
193 )
194 & (hitPoint - toPatchPoints[pointi]);
195 }
196 }
197 }
198
199 if (doWeights)
200 {
201 // Set interpolation pointWeights
202 const pointField hitFacePoints
203 (
204 hitFace.points(fromPatchPoints)
205 );
206
207 auto& pointiWeights =
208 pointWeights.emplace_set(pointi, hitFacePoints.size());
209
210 scalar sumWeight = 0;
211
212 forAll(hitFacePoints, masterPointi)
213 {
214 const point& p = hitFacePoints[masterPointi];
215
216 const scalar w =
217 (
218 1.0 / (hitPoint.dist(p) + VSMALL)
219 );
220
221 pointiWeights[masterPointi] = w;
222 sumWeight += w;
223 }
224
225 pointiWeights /= sumWeight;
226 }
227 else
228 {
229 pointWeights.emplace_set(pointi);
230 }
231 }
232}
233
234
235template<class FromPatch, class ToPatch>
236void PatchToPatchInterpolation<FromPatch, ToPatch>::calcFaceAddressing() const
237{
238 faceWeightsPtr_.reset(new FieldField<Field, scalar>(toPatch_.size()));
239 auto& faceWeights = *faceWeightsPtr_;
240
241 faceDistancePtr_.reset(new scalarField(toPatch_.size(), GREAT));
242 auto& faceDistance = *faceDistancePtr_;
243
244 if (debug)
245 {
246 Info<< "projecting face centres" << endl;
247 }
248
249 const pointField& fromPatchPoints = fromPatch_.points();
250 const auto& fromPatchFaces = fromPatch_;
251 const labelListList& fromPatchFaceFaces = fromPatch_.faceFaces();
252
253 vectorField fromPatchFaceCentres(fromPatchFaces.size());
254
255 forAll(fromPatchFaceCentres, facei)
256 {
257 fromPatchFaceCentres[facei] =
258 fromPatchFaces[facei].centre(fromPatchPoints);
259 }
260
261 const pointField& toPatchPoints = toPatch_.points();
262 const auto& toPatchFaces = toPatch_;
263
264 const vectorField& projectionDirection = toPatch_.faceNormals();
265
266 List<objectHit> proj =
267 toPatch_.projectFaceCentres
268 (
269 fromPatch_,
270 projectionDirection,
271 alg_,
272 dir_
273 );
274
275 faceAddressingPtr_.reset(new labelList(proj.size(), -1));
276 auto& faceAddressing = *faceAddressingPtr_;
277
278 forAll(faceAddressing, facei)
279 {
280 if (proj[facei].hit())
281 {
282 // A hit exists
283 faceAddressing[facei] = proj[facei].hitObject();
284
285 const auto& hitFace = fromPatchFaces[faceAddressing[facei]];
286
287 pointHit curHit =
288 hitFace.ray
289 (
290 toPatchFaces[facei].centre(toPatchPoints),
291 projectionDirection[facei],
292 fromPatchPoints,
293 alg_,
294 dir_
295 );
296
297 // grab distance to target
298 faceDistance[facei] = curHit.distance();
299
300 // grab face centre of the hit face
301 const point& hitFaceCentre =
302 fromPatchFaceCentres[faceAddressing[facei]];
303
304 // grab neighbours of hit face
305 const labelList& neighbours =
306 fromPatchFaceFaces[faceAddressing[facei]];
307
308 const point& hitPoint = curHit.hitPoint();
309
310 scalar m = hitPoint.dist(hitFaceCentre);
311
312 if
313 (
314 m < directHitTol // Direct hit
315 || neighbours.empty()
316 )
317 {
318 auto& faceiWeights = faceWeights.emplace_set(facei, 1);
319 faceiWeights[0] = 1.0;
320 }
321 else
322 {
323 // set interpolation faceWeights
324
325 // The first coefficient corresponds to the centre face.
326 // The rest is ordered in the same way as the faceFaces list.
327
328 auto& faceiWeights =
329 faceWeights.emplace_set(facei, neighbours.size() + 1);
330
331 faceiWeights[0] = 1.0/m;
332
333 scalar sumWeight = faceiWeights[0];
334
335 forAll(neighbours, nbri)
336 {
337 const point& p = fromPatchFaceCentres[neighbours[nbri]];
338
339 const scalar w =
340 (
341 1.0 / (hitPoint.dist(p) + VSMALL)
342 );
343
344 faceWeights[nbri+1] = w;
345 sumWeight += w;
346 }
347
348 faceiWeights /= sumWeight;
349 }
350 }
351 else
352 {
353 faceWeights.emplace_set(facei);
354 }
355 }
356}
357
358
359// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
360
361} // End namespace Foam
362
363// ************************************************************************* //
A field of fields is a PtrList of fields with reference counting.
Definition FieldField.H:77
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
volScalarField & p
Namespace for handling debugging switches.
Definition debug.C:45
Namespace for OpenFOAM.
List< edge > edgeList
List of edge.
Definition edgeList.H:32
List< labelList > labelListList
List of labelList.
Definition labelList.H:38
PointHit< point > pointHit
A PointHit with a 3D point.
Definition pointHit.H:51
List< label > labelList
A List of labels.
Definition List.H:62
messageStream Info
Information stream (stdout output on master, null elsewhere).
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:26
Field< vector > vectorField
Specialisation of Field<T> for vector.
vector point
Point is a vector.
Definition point.H:37
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
vectorField pointField
pointField is a vectorField.
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299