patchToPatchParallelOps.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) 2011-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 "patchToPatch.H"
27 #include "treeBoundBoxList.H"
30 
31 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
32 
34 (
35  const primitiveOldTimePatch& srcPatch,
36  const primitiveOldTimePatch& tgtPatch
37 )
38 {
39  singleProcess_ = 0;
40 
41  if (Pstream::parRun())
42  {
43  boolList procHasFaces(Pstream::nProcs(), false);
44 
45  if ((srcPatch.size() > 0) || (tgtPatch.size() > 0))
46  {
47  procHasFaces[Pstream::myProcNo()] = true;
48  }
49 
50  Pstream::gatherList(procHasFaces);
51  Pstream::scatterList(procHasFaces);
52 
53  const label nProcsHaveFaces = count(procHasFaces, true);
54 
55  if (nProcsHaveFaces == 0)
56  {
57  singleProcess_ = 0;
58  }
59  if (nProcsHaveFaces == 1)
60  {
61  singleProcess_ = findIndex(procHasFaces, true);
62  }
63  if (nProcsHaveFaces > 1)
64  {
65  singleProcess_ = -1;
66  }
67  }
68 }
69 
70 
72 (
73  const primitiveOldTimePatch& srcPatch,
74  const vectorField& srcPointNormals,
75  const vectorField& srcPointNormals0,
76  const primitiveOldTimePatch& tgtPatch
77 ) const
78 {
79  // Get the bound boxes for the source patch. Just a single box for now.
80  List<treeBoundBoxList> srcPatchProcBbs(Pstream::nProcs());
81  if (srcPatch.size())
82  {
83  srcPatchProcBbs[Pstream::myProcNo()] =
85  (
86  1,
87  srcBox(srcPatch, srcPointNormals, srcPointNormals0)
88  );
89  }
90  else
91  {
92  srcPatchProcBbs[Pstream::myProcNo()] = treeBoundBoxList();
93  }
94 
95  // Distribute the boxes
96  Pstream::gatherList(srcPatchProcBbs);
97  Pstream::scatterList(srcPatchProcBbs);
98 
99  // Send a target face to a process if it overlaps the source patch box
100  // for that process
101  List<DynamicList<label>> resultDyn(Pstream::nProcs());
102  forAll(tgtPatch, tgtFacei)
103  {
104  const treeBoundBox tgtFaceBb = tgtBox(tgtPatch, tgtFacei);
105  forAll(srcPatchProcBbs, proci)
106  {
107  forAll(srcPatchProcBbs[proci], bbi)
108  {
109  if (srcPatchProcBbs[proci][bbi].overlaps(tgtFaceBb))
110  {
111  resultDyn[proci].append(tgtFacei);
112  break;
113  }
114  }
115  }
116  }
117 
118  // Transfer to non-dynamic storage
119  labelListList result(Pstream::nProcs());
120  forAll(result, proci)
121  {
122  result[proci].transfer(resultDyn[proci]);
123  }
124 
125  return result;
126 }
127 
128 
130 {
131  // Send a source face to a proc if target face on that proc intersects it
132  List<labelHashSet> resultDyn(Pstream::nProcs());
133  forAll(tgtLocalSrcFaces_, tgtFacei)
134  {
135  const label tgtProci = localTgtProcFacesPtr_()[tgtFacei].proci;
136 
137  forAll(tgtLocalSrcFaces_[tgtFacei], i)
138  {
139  const label srcFacei = tgtLocalSrcFaces_[tgtFacei][i];
140 
141  resultDyn[tgtProci].insert(srcFacei);
142  }
143  }
144 
145  // Transfer to non-dynamic storage
146  labelListList result(Pstream::nProcs());
147  forAll(result, proci)
148  {
149  result[proci] = resultDyn[proci].toc();
150  }
151 
152  return result;
153 }
154 
155 
157 (
158  labelListList&& sendFaces
159 ) const
160 {
161  // Figure out how many target faces are to be received
162  labelList nReceiveFaces(Pstream::nProcs());
163  {
164  labelListList nSendFaces(Pstream::nProcs());
165 
166  nSendFaces[Pstream::myProcNo()].setSize(Pstream::nProcs());
167  forAll(sendFaces, proci)
168  {
169  nSendFaces[Pstream::myProcNo()][proci] =
170  sendFaces[proci].size();
171  }
172 
173  Pstream::gatherList(nSendFaces);
174  Pstream::scatterList(nSendFaces);
175 
176  forAll(sendFaces, proci)
177  {
178  nReceiveFaces[proci] =
179  nSendFaces[proci][Pstream::myProcNo()];
180  }
181  }
182 
183  // Determine order of receiving
184  labelListList receiveFaces(Pstream::nProcs());
185 
186  // Local faces first
187  receiveFaces[Pstream::myProcNo()] =
188  identity(sendFaces[Pstream::myProcNo()].size());
189 
190  // Remote faces next
191  label localFacei = receiveFaces[Pstream::myProcNo()].size();
192  forAll(receiveFaces, proci)
193  {
194  if (proci != Pstream::myProcNo())
195  {
196  const label n = nReceiveFaces[proci];
197  receiveFaces[proci].setSize(n);
198  for (label i = 0; i < n; i ++)
199  {
200  receiveFaces[proci][i] = localFacei ++;
201  }
202  }
203  }
204 
205  // Construct and return the map
206  return
208  (
209  localFacei,
210  move(sendFaces),
211  move(receiveFaces)
212  );
213 }
214 
215 
217 (
218  const distributionMap& map,
219  List<procFace>& localProcFaces
220 ) const
221 {
222  static const label thisProci = Pstream::myProcNo();
223 
224  // Exchange per-processor data
225  List<labelList> procLocalFaceis(Pstream::nProcs());
226  {
228 
229  // Send
230  for (label proci = 0; proci < Pstream::nProcs(); proci++)
231  {
232  const labelList& sendFaces = map.subMap()[proci];
233 
234  if (proci != thisProci && sendFaces.size())
235  {
236  UOPstream(proci, pBufs)() << sendFaces;
237  }
238  }
239 
240  pBufs.finishedSends();
241 
242  // Map local data
243  {
244  const labelList& sendFaces = map.subMap()[thisProci];
245 
246  procLocalFaceis[thisProci] = sendFaces;
247  }
248 
249  // Receive remote data
250  for (label proci = 0; proci < Pstream::nProcs(); proci++)
251  {
252  const labelList& receiveNewFaces = map.constructMap()[proci];
253 
254  if (proci != thisProci && receiveNewFaces.size())
255  {
256  UIPstream(proci, pBufs)() >> procLocalFaceis[proci];
257  }
258  }
259  }
260 
261  // Allocate
262  {
263  label nLocalFaces = 0;
264  forAll(procLocalFaceis, proci)
265  {
266  nLocalFaces += procLocalFaceis[proci].size();
267  }
268  localProcFaces.setSize(nLocalFaces);
269  }
270 
271  // Renumber and flatten
272  label localTgtFacei = 0;
273 
274  // Local data first
275  {
276  const labelList& fis = procLocalFaceis[thisProci];
277  forAll(fis, i)
278  {
279  localProcFaces[localTgtFacei] = {thisProci, fis[i]};
280  localTgtFacei ++;
281  }
282  }
283 
284  // Remote data after
285  forAll(procLocalFaceis, proci)
286  {
287  if (proci != thisProci)
288  {
289  const labelList& fis = procLocalFaceis[proci];
290  forAll(fis, i)
291  {
292  localProcFaces[localTgtFacei] = {proci, fis[i]};
293  localTgtFacei ++;
294  }
295  }
296  }
297 }
298 
299 
302 (
303  const distributionMap& map,
304  const primitiveOldTimePatch& patch,
305  List<procFace>& localProcFaces
306 ) const
307 {
308  static const label thisProci = Pstream::myProcNo();
309 
310  // Exchange per-processor data
311  List<labelList> procLocalFaceis(Pstream::nProcs());
312  List<faceList> procLocalFaces(Pstream::nProcs());
313  List<pointField> procLocalPoints(Pstream::nProcs());
314  List<pointField> procLocalPoints0(Pstream::nProcs());
315  {
317 
318  // Send
319  for (label proci = 0; proci < Pstream::nProcs(); proci++)
320  {
321  const labelList& sendTgtFaces = map.subMap()[proci];
322 
323  if (proci != thisProci && sendTgtFaces.size())
324  {
326  (
327  UIndirectList<face>(patch, sendTgtFaces),
328  patch.points(),
329  patch.points0()
330  );
331 
332  UOPstream(proci, pBufs)()
333  << sendTgtFaces
334  << subPatch.localFaces()
335  << subPatch.localPoints()
336  << (patch.has0() ? subPatch.localPoints0() : pointField());
337  }
338  }
339 
340  pBufs.finishedSends();
341 
342  // Map local data
343  {
344  const labelList& sendTgtFaces = map.subMap()[thisProci];
345 
347  (
348  UIndirectList<face>(patch, sendTgtFaces),
349  patch.points(),
350  patch.points0()
351  );
352 
353  procLocalFaceis[thisProci] = sendTgtFaces;
354  procLocalFaces[thisProci] = subPatch.localFaces();
355  procLocalPoints[thisProci] = subPatch.localPoints();
356  if (patch.has0())
357  {
358  procLocalPoints0[thisProci] = subPatch.localPoints0();
359  }
360  }
361 
362  // Receive remote data
363  for (label proci = 0; proci < Pstream::nProcs(); proci++)
364  {
365  const labelList& receiveNewTgtFaces = map.constructMap()[proci];
366 
367  if (proci != thisProci && receiveNewTgtFaces.size())
368  {
369  UIPstream(proci, pBufs)()
370  >> procLocalFaceis[proci]
371  >> procLocalFaces[proci]
372  >> procLocalPoints[proci]
373  >> procLocalPoints0[proci];
374  }
375  }
376  }
377 
378  // Allocate
379  faceList localTgtFaces;
380  pointField localTgtPoints;
381  pointField localTgtPoints0;
382  {
383  label nLocalFaces = 0, nLocalPoints = 0;
384  forAll(procLocalFaceis, proci)
385  {
386  nLocalFaces += procLocalFaces[proci].size();
387  nLocalPoints += procLocalPoints[proci].size();
388  }
389  localProcFaces.setSize(nLocalFaces);
390  localTgtFaces.setSize(nLocalFaces);
391  localTgtPoints.setSize(nLocalPoints);
392  if (patch.has0())
393  {
394  localTgtPoints0.setSize(nLocalPoints);
395  }
396  }
397 
398  // Renumber and flatten
399  label localTgtFacei = 0, localTgtPointi = 0;
400 
401  // Local data first
402  {
403  const labelList& fis = procLocalFaceis[thisProci];
404  const faceList& fs = procLocalFaces[thisProci];
405  forAll(fis, i)
406  {
407  localProcFaces[localTgtFacei] = {thisProci, fis[i]};
408  localTgtFaces[localTgtFacei] = face(fs[i] + localTgtPointi);
409  localTgtFacei ++;
410  }
411 
412  const pointField& ps = procLocalPoints[thisProci];
413  const pointField& ps0 = procLocalPoints0[thisProci];
414  forAll(ps, i)
415  {
416  localTgtPoints[localTgtPointi] = ps[i];
417  if (patch.has0())
418  {
419  localTgtPoints0[localTgtPointi] = ps0[i];
420  }
421  localTgtPointi ++;
422  }
423  }
424 
425  // Remote data after
426  forAll(procLocalFaces, proci)
427  {
428  if (proci != thisProci)
429  {
430  const labelList& fis = procLocalFaceis[proci];
431  const faceList& fs = procLocalFaces[proci];
432  forAll(fis, i)
433  {
434  localProcFaces[localTgtFacei] = {proci, fis[i]};
435  localTgtFaces[localTgtFacei] = face(fs[i] + localTgtPointi);
436  localTgtFacei ++;
437  }
438 
439  const pointField& ps = procLocalPoints[proci];
440  const pointField& ps0 = procLocalPoints0[proci];
441  forAll(ps, i)
442  {
443  localTgtPoints[localTgtPointi] = ps[i];
444  if (patch.has0())
445  {
446  localTgtPoints0[localTgtPointi] = ps0[i];
447  }
448  localTgtPointi ++;
449  }
450  }
451  }
452 
453  return
454  patch.has0()
456  (
457  localTgtFaces,
458  localTgtPoints,
459  localTgtPoints0
460  )
462  (
463  localTgtFaces,
464  localTgtPoints
465  );
466 }
467 
468 
469 // ************************************************************************* //
static void scatterList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Scatter data. Reverse of gatherList.
List< treeBoundBox > treeBoundBoxList
List of bounding boxes.
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
void finishedSends(const bool block=true)
Mark all sends as having been done. This will start receives.
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:429
label count(const ListType &l, typename ListType::const_reference x)
Count the number of occurrences of a value in a list.
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
const labelListList & constructMap() const
From subsetted data to new reconstructed data.
const labelListList & subMap() const
From subsetted data back to original data.
bool has0() const
Return whether or not old-time geometry is available.
Input inter-processor communications stream operating on external buffer.
Definition: UIPstream.H:53
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:178
const Field< PointType > & points0() const
Return reference to old-time global points.
const Field< PointType > & points() const
Return reference to global points.
distributionMap patchDistributionMap(labelListList &&sendFaces) const
Create a distribution map from a list-list of faces to be sent.
Output inter-processor communications stream operating on external buffer.
Definition: UOPstream.H:54
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
Buffers for inter-processor communications streams (UOPstream, UIPstream).
labelListList srcPatchSendFaces() const
Determine which source faces need to be sent to the target.
void setSize(const label)
Reset size of List.
Definition: List.C:281
Class containing processor-to-processor mapping information.
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:411
void calcSingleProcess(const primitiveOldTimePatch &srcPatch, const primitiveOldTimePatch &tgtPatch)
Determine whether or not the intersection of the given patches.
A List with indirect addressing.
Definition: fvMatrix.H:106
List< DynamicList< label > > tgtLocalSrcFaces_
For each target face, the coupled local source faces.
Definition: patchToPatch.H:118
Standard boundBox + extra functionality for use in octree.
Definition: treeBoundBox.H:87
label n
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Definition: List.C:342
autoPtr< List< procFace > > localTgtProcFacesPtr_
When running in parallel, a map from local target face index to.
Definition: patchToPatch.H:112
void distributePatch(const distributionMap &map, List< procFace > &localProcFaces) const
Distribute a patch given its distribution map. Just generate.
labelListList tgtPatchSendFaces(const primitiveOldTimePatch &srcPatch, const vectorField &srcPointNormals, const vectorField &srcPointNormals0, const primitiveOldTimePatch &tgtPatch) const
Determine which target faces need to be sent to the source.