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-------------------------------------------------------------------------------
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// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
39
40template<class FromPatch, class ToPatch>
41scalar PatchToPatchInterpolation<FromPatch, ToPatch>::projectionTol_ = 0.05;
42
43
44// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
45
46template<class FromPatch, class ToPatch>
47void 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
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 =
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
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
238template<class FromPatch, class ToPatch>
239void 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// ************************************************************************* //
Namespace for OpenFOAM.
List< label > labelList
A List of labels.
Definition: List.H:66
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
messageStream Info
Information stream (stdout output on master, null elsewhere)
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
vector point
Point is a vector.
Definition: point.H:43
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
PointHit< point > pointHit
A PointIndexHit for 3D points.
Definition: pointHit.H:44
Field< vector > vectorField
Specialisation of Field<T> for vector.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
List< edge > edgeList
A List of edges.
Definition: edgeList.H:63
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333