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