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 -------------------------------------------------------------------------------
11 License
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 
35 namespace Foam
36 {
37 
38 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
39 
40 template<class FromPatch, class ToPatch>
41 void 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
98  if (dir_ == intersection::CONTACT_SPHERE)
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 =
130  Foam::mag
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
177  if (dir_ == intersection::CONTACT_SPHERE)
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 
235 template<class FromPatch, class ToPatch>
236 void 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 // ************************************************************************* //
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
List< edge > edgeList
List of edge.
Definition: edgeList.H:32
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
List< labelList > labelListList
List of labelList.
Definition: labelList.H:38
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
int debug
Static debugging option.
vector point
Point is a vector.
Definition: point.H:37
messageStream Info
Information stream (stdout output on master, null elsewhere)
Field< vector > vectorField
Specialisation of Field<T> for vector.
List< label > labelList
A List of labels.
Definition: List.H:62
volScalarField & p
PointHit< point > pointHit
A PointHit with a 3D point.
Definition: pointHit.H:43
Namespace for OpenFOAM.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127