inverseDistancePatchToPatch.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2021-2022 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
27 #include "mathematicalConstants.H"
29 
30 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
31 
32 namespace Foam
33 {
34 namespace patchToPatches
35 {
38 }
39 }
40 
41 
42 // * * * * * * * * * * * Private Static Member Functions * * * * * * * * * * //
43 
44 bool Foam::patchToPatches::inverseDistance::rayHitsFace
45 (
46  const point& p,
47  const vector& r,
48  const face& f,
49  const pointField& ps
50 )
51 {
52  using namespace constant::mathematical;
53 
54  const tensor T = tensor::I - sqr(r);
55 
56  scalar angle = 0;
57 
58  forAll(f, i)
59  {
60  const vector& a = T & (ps[f[i]] - p);
61  const vector& b = T & (ps[f[f.fcIndex(i)]] - p);
62 
63  const scalar meanMagSqrAB = (magSqr(a) + magSqr(b))/2;
64  const scalar geometricMeanMagSqrAB = sqrt(magSqr(a)*magSqr(b));
65 
66  // This indicates that we have hit a point to within round off error
67  if (geometricMeanMagSqrAB < small*meanMagSqrAB) return true;
68 
69  angle -=
70  sign(r & (a ^ b))
71  *acos(min(max(-1, (a & b)/geometricMeanMagSqrAB), +1));
72  }
73 
74  return pi < angle && angle < 3*pi;
75 }
76 
77 
78 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
79 
80 void Foam::patchToPatches::inverseDistance::initialise
81 (
82  const primitiveOldTimePatch& srcPatch,
83  const vectorField& srcPointNormals,
84  const vectorField& srcPointNormals0,
85  const primitiveOldTimePatch& tgtPatch
86 )
87 {
89  (
90  srcPatch,
91  srcPointNormals,
92  srcPointNormals0,
93  tgtPatch
94  );
95 
96  srcWeights_.resize(srcPatch.size());
97  forAll(srcWeights_, i)
98  {
99  srcWeights_[i].clear();
100  }
101 
102  tgtWeights_.resize(tgtPatch.size());
103  forAll(tgtWeights_, i)
104  {
105  tgtWeights_[i].clear();
106  }
107 }
108 
109 
110 void Foam::patchToPatches::inverseDistance::generateWeights
111 (
112  const primitiveOldTimePatch& srcPatch,
113  const primitiveOldTimePatch& tgtPatch
114 )
115 {
116  auto generate = []
117  (
118  const primitiveOldTimePatch& patch,
119  const primitiveOldTimePatch& otherPatch,
120  const bool reverse,
121  List<DynamicList<label>>& otherFaces,
122  List<DynamicList<scalar>>& weights
123  )
124  {
125  forAll(otherFaces, facei)
126  {
127  if (otherFaces[facei].empty()) continue;
128 
129  label otherFacei = -1;
130 
131  // Find the other face that "contains" this face's centre
132  forAll(otherFaces[facei], i)
133  {
134  if
135  (
136  rayHitsFace
137  (
138  patch.faceCentres()[facei],
139  (reverse ? -1 : +1)*patch.faceNormals()[facei],
140  otherPatch[otherFaces[facei][i]],
141  otherPatch.points()
142  )
143  )
144  {
145  otherFacei = otherFaces[facei][i];
146  break;
147  }
148  }
149 
150  const point& c = patch.faceCentres()[facei];
151 
152  // If the above failed, find the closest
153  if (otherFacei == -1)
154  {
155  scalar minDistSqr = vGreat;
156 
157  forAll(otherFaces[facei], i)
158  {
159  const point& otherC =
160  otherPatch.faceCentres()[otherFaces[facei][i]];
161  const scalar distSqr = magSqr(c - otherC);
162  if (distSqr < minDistSqr)
163  {
164  minDistSqr = distSqr;
165  otherFacei = otherFaces[facei][i];
166  }
167  }
168  }
169 
170  // Remove all faces
171  otherFaces[facei].clear();
172 
173  // Add the found face and all its neighbours
174  const point& otherC = otherPatch.faceCentres()[otherFacei];
175  otherFaces[facei].append(otherFacei);
176  weights[facei].append(1/(mag(c - otherC) + rootVSmall));
177 
178  forAll(otherPatch.faceFaces()[otherFacei], i)
179  {
180  const label otherFacej = otherPatch.faceFaces()[otherFacei][i];
181 
182  const point& otherC = otherPatch.faceCentres()[otherFacej];
183  otherFaces[facei].append(otherFacej);
184  weights[facei].append(1/(mag(c - otherC) + rootVSmall));
185  }
186  }
187  };
188 
189  generate(srcPatch, tgtPatch, reverse_, srcLocalTgtFaces_, srcWeights_);
190  generate(tgtPatch, srcPatch, reverse_, tgtLocalSrcFaces_, tgtWeights_);
191 }
192 
193 
194 Foam::labelList Foam::patchToPatches::inverseDistance::finaliseLocal
195 (
196  const primitiveOldTimePatch& srcPatch,
197  const vectorField& srcPointNormals,
198  const vectorField& srcPointNormals0,
199  const primitiveOldTimePatch& tgtPatch
200 )
201 {
202  // Transfer weight addressing into actual addressing
203  generateWeights(srcPatch, tgtPatch);
204 
205  const labelList newToOldLocalTgtFace =
207  (
208  srcPatch,
209  srcPointNormals,
210  srcPointNormals0,
211  tgtPatch
212  );
213 
214  tgtWeights_ = List<DynamicList<scalar>>(tgtWeights_, newToOldLocalTgtFace);
215 
216  return newToOldLocalTgtFace;
217 }
218 
219 
220 void Foam::patchToPatches::inverseDistance::rDistributeTgt
221 (
222  const primitiveOldTimePatch& tgtPatch
223 )
224 {
225  // Let the base class reverse distribute the addressing
226  nearby::rDistributeTgt(tgtPatch);
227 
228  // Reverse distribute the weights
230  (
231  tgtPatch.size(),
232  tgtMapPtr_(),
233  tgtWeights_
234  );
235 }
236 
237 
238 Foam::label Foam::patchToPatches::inverseDistance::finalise
239 (
240  const primitiveOldTimePatch& srcPatch,
241  const vectorField& srcPointNormals,
242  const vectorField& srcPointNormals0,
243  const primitiveOldTimePatch& tgtPatch,
244  const transformer& tgtToSrc
245 )
246 {
247  const label nCouples =
249  (
250  srcPatch,
251  srcPointNormals,
252  srcPointNormals0,
253  tgtPatch,
254  tgtToSrc
255  );
256 
257  // Transfer weight addressing into actual addressing (if not done in the
258  // finaliseLocal method above)
259  if (isSingleProcess())
260  {
261  generateWeights(srcPatch, tgtPatch);
262  }
263 
264  // Normalise the weights
265  forAll(srcWeights_, srcFacei)
266  {
267  const scalar w = sum(srcWeights_[srcFacei]);
268  forAll(srcWeights_[srcFacei], i)
269  {
270  srcWeights_[srcFacei][i] /= max(w, vSmall);
271  }
272  }
273  forAll(tgtWeights_, tgtFacei)
274  {
275  const scalar w = sum(tgtWeights_[tgtFacei]);
276  forAll(tgtWeights_[tgtFacei], i)
277  {
278  tgtWeights_[tgtFacei][i] /= max(w, vSmall);
279  }
280  }
281 
282  if (debug)
283  {
284  auto histogram = [](const List<DynamicList<label>>& ll)
285  {
286  labelList result;
287  forAll(ll, i)
288  {
289  result.setSize(max(result.size(), ll[i].size() + 1), 0);
290  result[ll[i].size()] ++;
291  }
292 
293  result.resize(returnReduce(result.size(), maxOp<label>()), 0);
294 
295  Pstream::listCombineGather(result, plusEqOp<label>());
297 
298  return result;
299  };
300 
301  Info<< indent
302  << "Number of source faces by number of target connections = "
303  << histogram(srcLocalTgtFaces_) << nl
304  << indent
305  << "Number of target faces by number of source connections = "
306  << histogram(tgtLocalSrcFaces_) << endl;
307  }
308 
309  return nCouples;
310 }
311 
312 
314 Foam::patchToPatches::inverseDistance::srcWeights() const
315 {
316  return srcWeights_;
317 }
318 
319 
321 Foam::patchToPatches::inverseDistance::tgtWeights() const
322 {
323  return tgtWeights_;
324 }
325 
326 
327 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
328 
330 :
331  nearby(reverse),
332  srcWeights_(),
333  tgtWeights_()
334 {}
335 
336 
337 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
338 
340 {}
341 
342 
343 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
Macros for easy insertion into run-time selection tables.
static void listCombineGather(const List< commsStruct > &comms, List< T > &Value, const CombineOp &cop, const int tag, const label comm)
static void listCombineScatter(const List< commsStruct > &comms, List< T > &Value, const int tag, const label comm)
Scatter data. Reverse of combineGather.
static const Tensor I
Definition: Tensor.H:83
Class to generate coupling geometry between two primitive patches.
Definition: patchToPatch.H:56
const bool reverse_
Flag to indicate that the two patches are co-directional and.
Definition: patchToPatch.H:63
tmp< Field< Type > > tgtToSrc(const Field< Type > &tgtFld) const
Interpolate a target patch field to the source with no left.
List< DynamicList< label > > tgtLocalSrcFaces_
For each target face, the coupled local source faces.
Definition: patchToPatch.H:73
bool isSingleProcess() const
Is this intersection on a single process?
Definition: patchToPatchI.H:43
virtual void rDistributeTgt(const primitiveOldTimePatch &tgtPatch)
Send data that resulted from an intersection between the source.
Definition: patchToPatch.C:724
virtual labelList finaliseLocal(const primitiveOldTimePatch &srcPatch, const vectorField &srcPointNormals, const vectorField &srcPointNormals0, const primitiveOldTimePatch &tgtPatch)
Finalise the intersection locally. Trims the local target patch.
Definition: patchToPatch.C:662
List< DynamicList< label > > srcLocalTgtFaces_
For each source face, the coupled local target faces.
Definition: patchToPatch.H:70
bool reverse() const
Flag to indicate that the two patches are co-directional and.
Definition: patchToPatchI.H:31
autoPtr< distributionMap > tgtMapPtr_
Map from target patch faces to source-local target patch faces.
Definition: patchToPatch.H:79
virtual label finalise(const primitiveOldTimePatch &srcPatch, const vectorField &srcPointNormals, const vectorField &srcPointNormals0, const primitiveOldTimePatch &tgtPatch, const transformer &tgtToSrc)
Finalising.
Definition: patchToPatch.C:737
Class to generate patchToPatch coupling geometry. Couples a face to the opposite face onto which its ...
inverseDistance(const bool reverse)
Construct from components.
Class to generate patchToPatch coupling geometry. Couples a face to the single nearby opposite face o...
virtual void initialise(const primitiveOldTimePatch &srcPatch, const vectorField &srcPointNormals, const vectorField &srcPointNormals0, const primitiveOldTimePatch &tgtPatch)
Initialisation.
A class for managing temporary objects without reference counting.
Definition: tmpNrc.H:53
volScalarField & b
Definition: createFields.H:27
const dimensionedScalar c
Speed of light in a vacuum.
static void rDistributeListList(const label size, const distributionMap &map, List< List< Type >> &data)
Reverse distribute a list-list given the map.
addToRunTimeSelectionTable(patchToPatch, intersection, bool)
defineTypeNameAndDebug(intersection, 0)
Namespace for OpenFOAM.
List< label > labelList
A List of labels.
Definition: labelList.H:56
dimensionedScalar sign(const dimensionedScalar &ds)
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Tensor< scalar > tensor
Tensor of scalars.
Definition: tensor.H:51
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
messageStream Info
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
vector point
Point is a vector.
Definition: point.H:41
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
dimensionedScalar sqrt(const dimensionedScalar &ds)
PrimitiveOldTimePatch< SubList< face >, const pointField & > primitiveOldTimePatch
Addressing for a faceList slice.
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
dimensioned< scalar > mag(const dimensioned< Type > &)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
Field< vector > vectorField
Specialisation of Field<T> for vector.
Ostream & indent(Ostream &os)
Indent stream.
Definition: Ostream.H:221
static const char nl
Definition: Ostream.H:260
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
dimensioned< scalar > magSqr(const dimensioned< Type > &)
dimensionedScalar acos(const dimensionedScalar &ds)
labelList f(nPoints)
volScalarField & p