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 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
29 #include "objectHit.H"
30 #include "pointHit.H"
31 
32 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
33 
34 namespace Foam
35 {
36 
37 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
38 
39 template<class FromPatch, class ToPatch>
40 scalar PatchToPatchInterpolation<FromPatch, ToPatch>::projectionTol_ = 0.05;
41 
42 
43 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
44 
45 template<class FromPatch, class ToPatch>
46 void PatchToPatchInterpolation<FromPatch, ToPatch>::calcPointAddressing() const
47 {
48  // Calculate pointWeights
49 
50  pointWeightsPtr_ = new FieldField<Field, scalar>(toPatch_.nPoints());
51  FieldField<Field, scalar>& pointWeights = *pointWeightsPtr_;
52 
53  pointDistancePtr_ = new scalarField(toPatch_.nPoints(), GREAT);
54  scalarField& pointDistance = *pointDistancePtr_;
55 
56  const pointField& fromPatchPoints = fromPatch_.localPoints();
57  const List<typename FromPatch::FaceType>& fromPatchFaces =
58  fromPatch_.localFaces();
59 
60  const pointField& toPatchPoints = toPatch_.localPoints();
61  const vectorField& projectionDirection = toPatch_.pointNormals();
62  const edgeList& toPatchEdges = toPatch_.edges();
63  const labelListList& toPatchPointEdges = toPatch_.pointEdges();
64 
65  if (debug)
66  {
67  Info<< "projecting points" << endl;
68  }
69 
70  List<objectHit> proj =
71  toPatch_.projectPoints(fromPatch_, projectionDirection, alg_, dir_);
72 
73  pointAddressingPtr_ = new labelList(proj.size(), -1);
74  labelList& pointAddressing = *pointAddressingPtr_;
75 
76  bool doWeights = false;
77 
78  forAll(pointAddressing, pointi)
79  {
80  doWeights = false;
81 
82  const typename FromPatch::FaceType& hitFace =
83  fromPatchFaces[proj[pointi].hitObject()];
84 
85  point hitPoint = Zero;
86 
87  if (proj[pointi].hit())
88  {
89  // A hit exists
90  doWeights = true;
91 
92  pointAddressing[pointi] = proj[pointi].hitObject();
93 
94  pointHit curHit =
95  hitFace.ray
96  (
97  toPatchPoints[pointi],
98  projectionDirection[pointi],
99  fromPatchPoints,
100  alg_,
101  dir_
102  );
103 
104  // Grab distance to target
105  if (dir_ == intersection::CONTACT_SPHERE)
106  {
107  pointDistance[pointi] =
108  hitFace.contactSphereDiameter
109  (
110  toPatchPoints[pointi],
111  projectionDirection[pointi],
112  fromPatchPoints
113  );
114  }
115  else
116  {
117  pointDistance[pointi] = curHit.distance();
118  }
119 
120  // Grab hit point
121  hitPoint = curHit.hitPoint();
122  }
123  else if (projectionTol_ > SMALL)
124  {
125  // Check for a near miss
126  pointHit ph =
127  hitFace.ray
128  (
129  toPatchPoints[pointi],
130  projectionDirection[pointi],
131  fromPatchPoints,
132  alg_,
133  dir_
134  );
135 
136  scalar dist =
137  Foam::mag
138  (
139  toPatchPoints[pointi]
140  + projectionDirection[pointi]*ph.distance()
141  - ph.missPoint()
142  );
143 
144  // Calculate the local tolerance
145  scalar minEdgeLength = GREAT;
146 
147  // Do shortest edge of hit object
148  edgeList hitFaceEdges =
149  fromPatchFaces[proj[pointi].hitObject()].edges();
150 
151  forAll(hitFaceEdges, edgeI)
152  {
153  minEdgeLength =
154  min
155  (
156  minEdgeLength,
157  hitFaceEdges[edgeI].mag(fromPatchPoints)
158  );
159  }
160 
161  const labelList& curEdges = toPatchPointEdges[pointi];
162 
163  forAll(curEdges, edgeI)
164  {
165  minEdgeLength =
166  min
167  (
168  minEdgeLength,
169  toPatchEdges[curEdges[edgeI]].mag(toPatchPoints)
170  );
171  }
172 
173  if (dist < minEdgeLength*projectionTol_)
174  {
175  // This point is being corrected
176  doWeights = true;
177 
178  pointAddressing[pointi] = proj[pointi].hitObject();
179 
180  // Grab nearest point on face as hit point
181  hitPoint = ph.missPoint();
182 
183  // Grab distance to target
184  if (dir_ == intersection::CONTACT_SPHERE)
185  {
186  pointDistance[pointi] =
187  hitFace.contactSphereDiameter
188  (
189  toPatchPoints[pointi],
190  projectionDirection[pointi],
191  fromPatchPoints
192  );
193  }
194  else
195  {
196  pointDistance[pointi] =
197  (
198  projectionDirection[pointi]
199  /mag(projectionDirection[pointi])
200  )
201  & (hitPoint - toPatchPoints[pointi]);
202  }
203  }
204  }
205 
206  if (doWeights)
207  {
208  // Set interpolation pointWeights
209  pointWeights.set(pointi, new scalarField(hitFace.size()));
210 
211  pointField hitFacePoints = hitFace.points(fromPatchPoints);
212 
213  forAll(hitFacePoints, masterPointi)
214  {
215  pointWeights[pointi][masterPointi] =
216  1.0/
217  (
218  mag
219  (
220  hitFacePoints[masterPointi]
221  - hitPoint
222  )
223  + VSMALL
224  );
225  }
226 
227  pointWeights[pointi] /= sum(pointWeights[pointi]);
228  }
229  else
230  {
231  pointWeights.set(pointi, new scalarField(0));
232  }
233  }
234 }
235 
236 
237 template<class FromPatch, class ToPatch>
238 void PatchToPatchInterpolation<FromPatch, ToPatch>::calcFaceAddressing() const
239 {
240  faceWeightsPtr_ = new FieldField<Field, scalar>(toPatch_.size());
241  FieldField<Field, scalar>& faceWeights = *faceWeightsPtr_;
242 
243  faceDistancePtr_ = new scalarField(toPatch_.size(), GREAT);
244  scalarField& faceDistance = *faceDistancePtr_;
245 
246  if (debug)
247  {
248  Info<< "projecting face centres" << endl;
249  }
250 
251  const pointField& fromPatchPoints = fromPatch_.points();
252  const typename FromPatch::FaceListType& fromPatchFaces = fromPatch_;
253  const labelListList& fromPatchFaceFaces = fromPatch_.faceFaces();
254 
255  vectorField fromPatchFaceCentres(fromPatchFaces.size());
256 
257  forAll(fromPatchFaceCentres, facei)
258  {
259  fromPatchFaceCentres[facei] =
260  fromPatchFaces[facei].centre(fromPatchPoints);
261  }
262 
263  const pointField& toPatchPoints = toPatch_.points();
264  const typename ToPatch::FaceListType& toPatchFaces = toPatch_;
265 
266  const vectorField& projectionDirection = toPatch_.faceNormals();
267 
268  List<objectHit> proj =
269  toPatch_.projectFaceCentres
270  (
271  fromPatch_,
272  projectionDirection,
273  alg_,
274  dir_
275  );
276 
277  faceAddressingPtr_ = new labelList(proj.size(), -1);
278  labelList& faceAddressing = *faceAddressingPtr_;
279 
280  forAll(faceAddressing, facei)
281  {
282  if (proj[facei].hit())
283  {
284  // A hit exists
285  faceAddressing[facei] = proj[facei].hitObject();
286 
287  const typename FromPatch::FaceType& hitFace =
288  fromPatchFaces[faceAddressing[facei]];
289 
290  pointHit curHit =
291  hitFace.ray
292  (
293  toPatchFaces[facei].centre(toPatchPoints),
294  projectionDirection[facei],
295  fromPatchPoints,
296  alg_,
297  dir_
298  );
299 
300  // grab distance to target
301  faceDistance[facei] = curHit.distance();
302 
303  // grab face centre of the hit face
304  const point& hitFaceCentre =
305  fromPatchFaceCentres[faceAddressing[facei]];
306 
307  // grab neighbours of hit face
308  const labelList& neighbours =
309  fromPatchFaceFaces[faceAddressing[facei]];
310 
311  scalar m = mag(curHit.hitPoint() - hitFaceCentre);
312 
313  if
314  (
315  m < directHitTol // Direct hit
316  || neighbours.empty()
317  )
318  {
319  faceWeights.set(facei, new scalarField(1));
320  faceWeights[facei][0] = 1.0;
321  }
322  else
323  {
324  // set interpolation faceWeights
325 
326  // The first coefficient corresponds to the centre face.
327  // The rest is ordered in the same way as the faceFaces list.
328  faceWeights.set(facei, new scalarField(neighbours.size() + 1));
329 
330  faceWeights[facei][0] = 1.0/m;
331 
332  forAll(neighbours, nI)
333  {
334  faceWeights[facei][nI + 1] =
335  1.0/
336  (
337  mag
338  (
339  fromPatchFaceCentres[neighbours[nI]]
340  - curHit.hitPoint()
341  )
342  + VSMALL
343  );
344  }
345  }
346 
347  faceWeights[facei] /= sum(faceWeights[facei]);
348  }
349  else
350  {
351  faceWeights.set(facei, new scalarField(0));
352  }
353  }
354 }
355 
356 
357 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
358 
359 } // End namespace Foam
360 
361 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:74
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.
Definition: zero.H:128
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
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:290
Foam::vectorField
Field< vector > vectorField
Specialisation of Field<T> for vector.
Definition: primitiveFieldsFwd.H:54
objectHit.H
Foam::PointHit::distance
scalar distance() const
Return distance to hit.
Definition: PointHit.H:143
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::intersection::CONTACT_SPHERE
Definition: intersection.H:69
Foam::pointHit
PointHit< point > pointHit
Definition: pointHit.H:43
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