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-2026 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 "OBJstream.H"
29 #include "vtkWritePolyData.H"
30 
31 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
32 
33 namespace Foam
34 {
35 namespace patchToPatches
36 {
39 }
40 }
41 
42 
43 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
44 
46 (
47  const primitiveOldTimePatch& srcPatch,
48  const vectorField& srcPointNormals,
49  const vectorField& srcPointNormals0,
50  const primitiveOldTimePatch& tgtPatch,
51  const label srcFacei,
52  const label tgtFacei
53 )
54 {
55  if
56  (
58  (
59  srcPatch,
60  srcPointNormals,
61  srcPointNormals0,
62  tgtPatch,
63  srcFacei,
64  tgtFacei
65  )
66  )
67  {
68  const scalar dSqr =
69  magSqr
70  (
71  srcPatch.faceCentres()[srcFacei]
72  - tgtPatch.faceCentres()[tgtFacei]
73  );
74 
75  if (dSqr < srcDistances_[srcFacei])
76  {
77  srcDistances_[srcFacei] = dSqr;
78  Swap
79  (
80  srcLocalTgtFaces_[srcFacei].first(),
81  srcLocalTgtFaces_[srcFacei].last()
82  );
83  }
84 
85  if (dSqr < tgtDistances_[tgtFacei])
86  {
87  tgtDistances_[tgtFacei] = dSqr;
88  Swap
89  (
90  tgtLocalSrcFaces_[tgtFacei].first(),
91  tgtLocalSrcFaces_[tgtFacei].last()
92  );
93  }
94 
95  return true;
96  }
97  else
98  {
99  return false;
100  }
101 }
102 
103 
105 (
106  const primitiveOldTimePatch& srcPatch,
107  const vectorField& srcPointNormals,
108  const vectorField& srcPointNormals0,
109  const primitiveOldTimePatch& tgtPatch
110 )
111 {
113  (
114  srcPatch,
115  srcPointNormals,
116  srcPointNormals0,
117  tgtPatch
118  );
119 
120  srcDistances_.resize(srcPatch.size());
121  srcDistances_ = vGreat;
122 
123  tgtDistances_.resize(tgtPatch.size());
124  tgtDistances_ = vGreat;
125 }
126 
127 
129 (
130  const primitiveOldTimePatch& srcPatch,
131  const vectorField& srcPointNormals,
132  const vectorField& srcPointNormals0,
133  const primitiveOldTimePatch& tgtPatch
134 )
135 {
136  const labelList newToOldLocalTgtFace =
138  (
139  srcPatch,
140  srcPointNormals,
141  srcPointNormals0,
142  tgtPatch
143  );
144 
145  tgtDistances_ = List<scalar>(tgtDistances_, newToOldLocalTgtFace);
146 
147  return newToOldLocalTgtFace;
148 }
149 
150 
152 (
153  const primitiveOldTimePatch& tgtPatch
154 )
155 {
156  // Keep only the closest opposing face
157  forAll(srcLocalTgtFaces_, srcFacei)
158  {
159  srcLocalTgtFaces_[srcFacei].resize
160  (
161  min(srcLocalTgtFaces_[srcFacei].size(), 1)
162  );
163  }
164  forAll(tgtLocalSrcFaces_, tgtFacei)
165  {
166  tgtLocalSrcFaces_[tgtFacei].resize
167  (
168  min(tgtLocalSrcFaces_[tgtFacei].size(), 1)
169  );
170  }
171 
172  // Create a list-list of distances to match the addressing
173  List<List<scalar>> tgtDistances(tgtLocalSrcFaces_.size());
174  forAll(tgtLocalSrcFaces_, tgtFacei)
175  {
176  if (!tgtLocalSrcFaces_[tgtFacei].empty())
177  {
178  tgtDistances[tgtFacei].resize(1, tgtDistances_[tgtFacei]);
179  }
180  }
181 
182  // Let the base class reverse distribute the addressing
183  nearby::rDistributeTgt(tgtPatch);
184 
185  // Reverse distribute the distances
187  (
188  tgtPatch.size(),
189  tgtMapPtr_(),
190  tgtDistances
191  );
192 
193  // If there is more than one address, remove all but the closest
194  tgtDistances_.resize(tgtLocalSrcFaces_.size());
195  forAll(tgtLocalSrcFaces_, tgtFacei)
196  {
197  if (tgtLocalSrcFaces_[tgtFacei].size() > 1)
198  {
199  const label i = findMin(tgtDistances[tgtFacei]);
200 
201  const label srcFacei = tgtLocalSrcFaces_[tgtFacei][i];
202 
203  tgtLocalSrcFaces_[tgtFacei].resize(1);
204  tgtLocalSrcFaces_[tgtFacei][0] = srcFacei;
205 
206  tgtDistances_[tgtFacei] = tgtDistances[tgtFacei][i];
207  }
208  }
209 }
210 
211 
213 (
214  const primitiveOldTimePatch& srcPatch,
215  const vectorField& srcPointNormals,
216  const vectorField& srcPointNormals0,
217  const primitiveOldTimePatch& tgtPatch,
218  const transformer& tgtToSrc
219 )
220 {
221  // Keep only the closest opposing face
222  forAll(srcLocalTgtFaces_, srcFacei)
223  {
224  srcLocalTgtFaces_[srcFacei].resize
225  (
226  min(srcLocalTgtFaces_[srcFacei].size(), 1)
227  );
228  }
229  forAll(tgtLocalSrcFaces_, tgtFacei)
230  {
231  tgtLocalSrcFaces_[tgtFacei].resize
232  (
233  min(tgtLocalSrcFaces_[tgtFacei].size(), 1)
234  );
235  }
236 
237  const label nCouples =
239  (
240  srcPatch,
241  srcPointNormals,
242  srcPointNormals0,
243  tgtPatch,
244  tgtToSrc
245  );
246 
247  if (debug)
248  {
249  auto countNonEmpty = [](const List<DynamicList<label>>& ll)
250  {
251  label result = 0;
252 
253  forAll(ll, i)
254  {
255  result += !ll[i].empty();
256  }
257 
258  return returnReduce(result, sumOp<label>());
259  };
260 
261  Info<< indent
262  << "Coupled " << countNonEmpty(srcLocalTgtFaces_)
263  << "/" << returnReduce(srcLocalTgtFaces_.size(), sumOp<label>())
264  << " source faces and " << countNonEmpty(tgtLocalSrcFaces_)
265  << "/" << returnReduce(tgtLocalSrcFaces_.size(), sumOp<label>())
266  << " target faces" << endl;
267  }
268 
269  if (debug && !Pstream::parRun())
270  {
271  auto writeConnections = []
272  (
273  const primitivePatch& patch,
274  const primitivePatch& otherPatch,
275  const bool isSrc,
276  const List<DynamicList<label>>& faceLocalOtherFaces
277  )
278  {
279  const word name =
280  typeName + "_" + (isSrc ? "src" : "tgt") + "Connections";
281 
282  OBJstream obj(name + ".obj");
283 
284  forAll(faceLocalOtherFaces, facei)
285  {
286  const point& p = patch.faceCentres()[facei];
287  forAll(faceLocalOtherFaces[facei], i)
288  {
289  const label otherFacei = faceLocalOtherFaces[facei][i];
290  const point& q = otherPatch.faceCentres()[otherFacei];
291  obj.write(linePointRef(p, q));
292  }
293  }
294  };
295 
296  writeConnections(srcPatch, tgtPatch, true, srcLocalTgtFaces_);
297  writeConnections(tgtPatch, srcPatch, false, tgtLocalSrcFaces_);
298 
299  auto writeNotConnected = []
300  (
301  const primitivePatch& patch,
302  const List<DynamicList<label>>& faceLocalOtherFaces,
303  const bool isSrc
304  )
305  {
306  DynamicList<label> unconnected;
307  forAll(faceLocalOtherFaces, facei)
308  {
309  if (faceLocalOtherFaces[facei].empty())
310  {
311  unconnected.append(facei);
312  }
313  }
314 
315  const word name =
316  typeName + "_" + (isSrc ? "src" : "tgt") + "NotConnected";
317 
319  (
320  name + ".vtk",
321  name,
322  false,
323  patch.localPoints(),
324  labelList(),
325  labelListList(),
326  UIndirectList<face>(patch.localFaces(), unconnected)
327  );
328  };
329 
330  writeNotConnected(srcPatch, srcLocalTgtFaces_, true);
331  writeNotConnected(tgtPatch, tgtLocalSrcFaces_, false);
332  }
333 
334  return nCouples;
335 }
336 
337 
340 {
342  (
343  new List<DynamicList<scalar>>(srcLocalTgtFaces_.size())
344  );
345 
346  List<DynamicList<scalar>>& result = tResult.ref();
347 
348  forAll(srcLocalTgtFaces_, srcFacei)
349  {
350  if (!srcLocalTgtFaces_[srcFacei].empty())
351  {
352  result[srcFacei].resize(1, scalar(1));
353  }
354  }
355 
356  return tResult;
357 }
358 
359 
362 {
364  (
365  new List<DynamicList<scalar>>(tgtLocalSrcFaces_.size())
366  );
367 
368  List<DynamicList<scalar>>& result = tResult.ref();
369 
370  forAll(tgtLocalSrcFaces_, tgtFacei)
371  {
372  if (!tgtLocalSrcFaces_[tgtFacei].empty())
373  {
374  result[tgtFacei].resize(1, scalar(1));
375  }
376  }
377 
378  return tResult;
379 }
380 
381 
382 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
383 
385 :
386  nearby(reverse),
387  srcDistances_(),
388  tgtDistances_()
389 {}
390 
391 
392 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
393 
395 {}
396 
397 
398 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
Macros for easy insertion into run-time selection tables.
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
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:61
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:143
Vector-tensor class used to perform translations, rotations and scaling operations in 3D space.
Definition: transformer.H:84
Template function which returns the un-mangled name of a given type. Useful for types which do not ha...
A class for handling words, derived from string.
Definition: word.H:63
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:288
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
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)
dimensioned< Type > min(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
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
tmp< DimensionedField< scalar, GeoMesh, Field > > magSqr(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
Ostream & indent(Ostream &os)
Indent stream.
Definition: Ostream.H:243
volScalarField & p