nearestPatchToPatch.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 
26 #include "nearestPatchToPatch.H"
28 #include "boundSphere.H"
29 #include "OFstream.H"
30 #include "OBJstream.H"
31 #include "vtkWritePolyData.H"
32 #include "mathematicalConstants.H"
33 
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
35 
36 namespace Foam
37 {
38 namespace patchToPatches
39 {
42 }
43 }
44 
45 
46 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
47 
49 (
50  const primitiveOldTimePatch& srcPatch,
51  const vectorField& srcPointNormals,
52  const vectorField& srcPointNormals0,
53  const primitiveOldTimePatch& tgtPatch,
54  const label srcFacei,
55  const label tgtFacei
56 )
57 {
58  if
59  (
61  (
62  srcPatch,
63  srcPointNormals,
64  srcPointNormals0,
65  tgtPatch,
66  srcFacei,
67  tgtFacei
68  )
69  )
70  {
71  const scalar dSqr =
72  magSqr
73  (
74  srcPatch.faceCentres()[srcFacei]
75  - tgtPatch.faceCentres()[tgtFacei]
76  );
77 
78  if (dSqr < srcDistances_[srcFacei])
79  {
80  srcDistances_[srcFacei] = dSqr;
81  Swap
82  (
83  srcLocalTgtFaces_[srcFacei].first(),
84  srcLocalTgtFaces_[srcFacei].last()
85  );
86  }
87 
88  if (dSqr < tgtDistances_[tgtFacei])
89  {
90  tgtDistances_[tgtFacei] = dSqr;
91  Swap
92  (
93  tgtLocalSrcFaces_[tgtFacei].first(),
94  tgtLocalSrcFaces_[tgtFacei].last()
95  );
96  }
97 
98  return true;
99  }
100  else
101  {
102  return false;
103  }
104 }
105 
106 
108 (
109  const primitiveOldTimePatch& srcPatch,
110  const vectorField& srcPointNormals,
111  const vectorField& srcPointNormals0,
112  const primitiveOldTimePatch& tgtPatch
113 )
114 {
116  (
117  srcPatch,
118  srcPointNormals,
119  srcPointNormals0,
120  tgtPatch
121  );
122 
123  srcDistances_.resize(srcPatch.size());
124  srcDistances_ = vGreat;
125 
126  tgtDistances_.resize(tgtPatch.size());
127  tgtDistances_ = vGreat;
128 }
129 
130 
132 (
133  const primitiveOldTimePatch& srcPatch,
134  const vectorField& srcPointNormals,
135  const vectorField& srcPointNormals0,
136  const primitiveOldTimePatch& tgtPatch
137 )
138 {
139  const labelList newToOldLocalTgtFace =
141  (
142  srcPatch,
143  srcPointNormals,
144  srcPointNormals0,
145  tgtPatch
146  );
147 
148  tgtDistances_ = List<scalar>(tgtDistances_, newToOldLocalTgtFace);
149 
150  return newToOldLocalTgtFace;
151 }
152 
153 
155 (
156  const primitiveOldTimePatch& tgtPatch
157 )
158 {
159  // Keep only the closest opposing face
160  forAll(srcLocalTgtFaces_, srcFacei)
161  {
162  srcLocalTgtFaces_[srcFacei].resize
163  (
164  min(srcLocalTgtFaces_[srcFacei].size(), 1)
165  );
166  }
167  forAll(tgtLocalSrcFaces_, tgtFacei)
168  {
169  tgtLocalSrcFaces_[tgtFacei].resize
170  (
171  min(tgtLocalSrcFaces_[tgtFacei].size(), 1)
172  );
173  }
174 
175  // Create a list-list of distances to match the addressing
176  List<List<scalar>> tgtDistances(tgtLocalSrcFaces_.size());
177  forAll(tgtLocalSrcFaces_, tgtFacei)
178  {
179  if (!tgtLocalSrcFaces_[tgtFacei].empty())
180  {
181  tgtDistances[tgtFacei].resize(1, tgtDistances_[tgtFacei]);
182  }
183  }
184 
185  // Let the base class reverse distribute the addressing
186  nearby::rDistributeTgt(tgtPatch);
187 
188  // Reverse distribute the distances
190  (
191  tgtPatch.size(),
192  tgtMapPtr_(),
193  tgtDistances
194  );
195 
196  // If there is more than one address, remove all but the closest
197  tgtDistances_.resize(tgtLocalSrcFaces_.size());
198  forAll(tgtLocalSrcFaces_, tgtFacei)
199  {
200  if (tgtLocalSrcFaces_[tgtFacei].size() > 1)
201  {
202  const label i = findMin(tgtDistances[tgtFacei]);
203 
204  const label srcFacei = tgtLocalSrcFaces_[tgtFacei][i];
205 
206  tgtLocalSrcFaces_[tgtFacei].resize(1);
207  tgtLocalSrcFaces_[tgtFacei][0] = srcFacei;
208 
209  tgtDistances_[tgtFacei] = tgtDistances[tgtFacei][i];
210  }
211  }
212 }
213 
214 
216 (
217  const primitiveOldTimePatch& srcPatch,
218  const vectorField& srcPointNormals,
219  const vectorField& srcPointNormals0,
220  const primitiveOldTimePatch& tgtPatch,
221  const transformer& tgtToSrc
222 )
223 {
224  // Keep only the closest opposing face
225  forAll(srcLocalTgtFaces_, srcFacei)
226  {
227  srcLocalTgtFaces_[srcFacei].resize
228  (
229  min(srcLocalTgtFaces_[srcFacei].size(), 1)
230  );
231  }
232  forAll(tgtLocalSrcFaces_, tgtFacei)
233  {
234  tgtLocalSrcFaces_[tgtFacei].resize
235  (
236  min(tgtLocalSrcFaces_[tgtFacei].size(), 1)
237  );
238  }
239 
240  const label nCouples =
242  (
243  srcPatch,
244  srcPointNormals,
245  srcPointNormals0,
246  tgtPatch,
247  tgtToSrc
248  );
249 
250  if (debug)
251  {
252  auto countNonEmpty = [](const List<DynamicList<label>>& ll)
253  {
254  label result = 0;
255 
256  forAll(ll, i)
257  {
258  result += !ll[i].empty();
259  }
260 
261  return returnReduce(result, sumOp<label>());
262  };
263 
264  Info<< indent
265  << "Coupled " << countNonEmpty(srcLocalTgtFaces_)
266  << "/" << returnReduce(srcLocalTgtFaces_.size(), sumOp<label>())
267  << " source faces and " << countNonEmpty(tgtLocalSrcFaces_)
268  << "/" << returnReduce(tgtLocalSrcFaces_.size(), sumOp<label>())
269  << " target faces" << endl;
270  }
271 
272  if (debug && !Pstream::parRun())
273  {
274  auto writeConnections = []
275  (
276  const primitivePatch& patch,
277  const primitivePatch& otherPatch,
278  const bool isSrc,
279  const List<DynamicList<label>>& faceLocalOtherFaces
280  )
281  {
282  const word name =
283  typeName + "_" + (isSrc ? "src" : "tgt") + "Connections";
284 
285  OBJstream obj(name + ".obj");
286 
287  forAll(faceLocalOtherFaces, facei)
288  {
289  const point& p = patch.faceCentres()[facei];
290  forAll(faceLocalOtherFaces[facei], i)
291  {
292  const label otherFacei = faceLocalOtherFaces[facei][i];
293  const point& q = otherPatch.faceCentres()[otherFacei];
294  obj.write(linePointRef(p, q));
295  }
296  }
297  };
298 
299  writeConnections(srcPatch, tgtPatch, true, srcLocalTgtFaces_);
300  writeConnections(tgtPatch, srcPatch, false, tgtLocalSrcFaces_);
301 
302  auto writeNotConnected = []
303  (
304  const primitivePatch& patch,
305  const List<DynamicList<label>>& faceLocalOtherFaces,
306  const bool isSrc
307  )
308  {
309  DynamicList<label> unconnected;
310  forAll(faceLocalOtherFaces, facei)
311  {
312  if (faceLocalOtherFaces[facei].empty())
313  {
314  unconnected.append(facei);
315  }
316  }
317 
318  const word name =
319  typeName + "_" + (isSrc ? "src" : "tgt") + "NotConnected";
320 
322  (
323  name + ".vtk",
324  name,
325  false,
326  patch.localPoints(),
327  labelList(),
328  labelListList(),
329  UIndirectList<face>(patch.localFaces(), unconnected)
330  );
331  };
332 
333  writeNotConnected(srcPatch, srcLocalTgtFaces_, true);
334  writeNotConnected(tgtPatch, tgtLocalSrcFaces_, false);
335  }
336 
337  return nCouples;
338 }
339 
340 
343 {
345  (
346  new List<DynamicList<scalar>>(srcLocalTgtFaces_.size())
347  );
348 
349  List<DynamicList<scalar>>& result = tResult.ref();
350 
351  forAll(srcLocalTgtFaces_, srcFacei)
352  {
353  if (!srcLocalTgtFaces_[srcFacei].empty())
354  {
355  result[srcFacei].resize(1, scalar(1));
356  }
357  }
358 
359  return tResult;
360 }
361 
362 
365 {
367  (
368  new List<DynamicList<scalar>>(tgtLocalSrcFaces_.size())
369  );
370 
371  List<DynamicList<scalar>>& result = tResult.ref();
372 
373  forAll(tgtLocalSrcFaces_, tgtFacei)
374  {
375  if (!tgtLocalSrcFaces_[tgtFacei].empty())
376  {
377  result[tgtFacei].resize(1, scalar(1));
378  }
379  }
380 
381  return tResult;
382 }
383 
384 
385 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
386 
388 :
389  nearby(reverse),
390  srcDistances_(),
391  tgtDistances_()
392 {}
393 
394 
395 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
396 
398 {}
399 
400 
401 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
Macros for easy insertion into run-time selection tables.
Functions for constructing bounding spheres of lists of points.
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Definition: DynamicListI.H:296
void resize(const label)
Alias for setSize(const label)
Definition: ListI.H:138
OFstream which keeps track of vertices.
Definition: OBJstream.H:56
A list of faces which address into the list of points.
const List< FaceType > & localFaces() const
Return patch faces addressing into local point list.
const Field< PointType > & localPoints() const
Return pointField of points in patch.
const Field< PointType > & faceCentres() const
Return face centres for patch.
A List with indirect addressing.
Definition: UIndirectList.H:60
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:399
Class to generate coupling geometry between two primitive patches.
Definition: patchToPatch.H:56
List< DynamicList< label > > tgtLocalSrcFaces_
For each target face, the coupled local source faces.
Definition: patchToPatch.H:73
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
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 single nearby opposite face o...
virtual bool intersectFaces(const primitiveOldTimePatch &srcPatch, const vectorField &srcPointNormals, const vectorField &srcPointNormals0, const primitiveOldTimePatch &tgtPatch, const label srcFacei, const label tgtFacei)
Intersect two faces.
virtual void initialise(const primitiveOldTimePatch &srcPatch, const vectorField &srcPointNormals, const vectorField &srcPointNormals0, const primitiveOldTimePatch &tgtPatch)
Initialisation.
Class to generate patchToPatch coupling geometry. Couples a face to the single nearest opposite face ...
nearest(const bool reverse)
Construct from components.
virtual tmpNrc< List< DynamicList< scalar > > > tgtWeights() const
For each target face, the coupled source weights.
List< scalar > tgtDistances_
For each target face, the distance to its coupled source face.
List< scalar > srcDistances_
For each source face, the distance to its coupled target face.
virtual void rDistributeTgt(const primitiveOldTimePatch &tgtPatch)
Send data that resulted from an intersection between the source.
virtual labelList finaliseLocal(const primitiveOldTimePatch &srcPatch, const vectorField &srcPointNormals, const vectorField &srcPointNormals0, const primitiveOldTimePatch &tgtPatch)
Finalise the intersection locally. Trims the local target patch.
virtual bool intersectFaces(const primitiveOldTimePatch &srcPatch, const vectorField &srcPointNormals, const vectorField &srcPointNormals0, const primitiveOldTimePatch &tgtPatch, const label srcFacei, const label tgtFacei)
Intersect two faces.
virtual void initialise(const primitiveOldTimePatch &srcPatch, const vectorField &srcPointNormals, const vectorField &srcPointNormals0, const primitiveOldTimePatch &tgtPatch)
Initialisation.
virtual tmpNrc< List< DynamicList< scalar > > > srcWeights() const
For each source face, the coupled target weights.
virtual label finalise(const primitiveOldTimePatch &srcPatch, const vectorField &srcPointNormals, const vectorField &srcPointNormals0, const primitiveOldTimePatch &tgtPatch, const transformer &tgtToSrc)
Finalise the intersection.
A class for managing temporary objects without reference counting.
Definition: tmpNrc.H:53
T & ref()
Return non-const reference or generate a fatal error.
Definition: tmpNrcI.H:136
Vector-tensor class used to perform translations, rotations and scaling operations in 3D space.
Definition: transformer.H:84
A class for handling words, derived from string.
Definition: word.H:62
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)
void write(const fileName &file, const word &title, const bool binary, const PointField &points, const VertexList &vertices, const LineList &lines, const FaceList &faces, const wordList &fieldNames, const boolList &fieldIsPointValues, const UPtrList< const Field< label >> &fieldLabelValues #define FieldTypeValuesConstArg(Type, nullArg))
Write VTK polygonal data to a file. Takes a PtrList of fields of labels and.
Namespace for OpenFOAM.
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
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
line< point, const point & > linePointRef
Line using referred points.
Definition: linePointRef.H:45
messageStream Info
void reverse(UList< T > &, const label n)
Definition: UListI.H:334
labelList first(const UList< labelPair > &p)
Definition: patchToPatch.C:39
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:57
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
label findMin(const ListType &, const label start=0)
Find index of min element (and less than given element).
void Swap(T &a, T &b)
Definition: Swap.H:43
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
Ostream & indent(Ostream &os)
Indent stream.
Definition: Ostream.H:221
dimensioned< scalar > magSqr(const dimensioned< Type > &)
volScalarField & p