patchToPatchTools.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) 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 "patchToPatchTools.H"
27 
28 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
29 
31 (
32  const label srcSize,
33  const label tgtSize
34 )
35 {
36  label result = 0;
37 
38  if (Pstream::parRun())
39  {
40  boolList procHasElements(Pstream::nProcs(), false);
41 
42  if (srcSize > 0 || tgtSize > 0)
43  {
44  procHasElements[Pstream::myProcNo()] = true;
45  }
46 
47  Pstream::gatherList(procHasElements);
48  Pstream::scatterList(procHasElements);
49 
50  const label nProcsHaveElements = count(procHasElements, true);
51 
52  if (nProcsHaveElements == 0)
53  {
54  result = 0;
55  }
56 
57  if (nProcsHaveElements == 1)
58  {
59  result = findIndex(procHasElements, true);
60  }
61 
62  if (nProcsHaveElements > 1)
63  {
64  result = -1;
65  }
66  }
67 
68  return result;
69 }
70 
71 
74 (
76 )
77 {
78  // Communicate the size of all the transfers
79  labelListList transferSizes(Pstream::nProcs());
80  transferSizes[Pstream::myProcNo()].setSize(Pstream::nProcs());
81  forAll(procSendIndices, proci)
82  {
83  transferSizes[Pstream::myProcNo()][proci] =
84  procSendIndices[proci].size();
85  }
86  Pstream::gatherList(transferSizes);
87  Pstream::scatterList(transferSizes);
88 
89  // Determine order of receiving
90  labelListList constructMap(Pstream::nProcs());
91  label index = constructMap[Pstream::myProcNo()].size();
92  forAll(constructMap, proci)
93  {
94  const label n = transferSizes[proci][Pstream::myProcNo()];
95  constructMap[proci].setSize(n);
96 
97  for (label i = 0; i < n; i ++)
98  {
99  constructMap[proci][i] = index ++;
100  }
101  }
102 
103  // Construct and return the map
104  return
106  (
107  new distributionMap
108  (
109  index,
111  move(constructMap)
112  )
113  );
114 }
115 
116 
118 (
119  const distributionMap& map
120 )
121 {
122  static const label thisProci = Pstream::myProcNo();
123 
124  // Exchange per-processor data
125  List<labelList> procLocalFaceis(Pstream::nProcs());
126  {
127  PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
128 
129  // Send
130  for (label proci = 0; proci < Pstream::nProcs(); proci++)
131  {
132  const labelList& sendFaceis = map.subMap()[proci];
133 
134  if (proci != thisProci && sendFaceis.size())
135  {
136  UOPstream(proci, pBufs)() << sendFaceis;
137  }
138  }
139 
140  pBufs.finishedSends();
141 
142  // Map local data
143  {
144  const labelList& sendFaceis = map.subMap()[thisProci];
145 
146  procLocalFaceis[thisProci] = sendFaceis;
147  }
148 
149  // Receive remote data
150  for (label proci = 0; proci < Pstream::nProcs(); proci++)
151  {
152  if (proci != thisProci && map.constructMap()[proci].size())
153  {
154  UIPstream(proci, pBufs)() >> procLocalFaceis[proci];
155  }
156  }
157  }
158 
159  // Allocate
160  List<remote> localProcFaces;
161  {
162  label nLocalFaces = 0;
163  forAll(procLocalFaceis, proci)
164  {
165  nLocalFaces += procLocalFaceis[proci].size();
166  }
167  localProcFaces.setSize(nLocalFaces);
168  }
169 
170  // Construct the result
171  label localFacei = 0;
172  forAll(procLocalFaceis, proci)
173  {
174  const labelList& fis = procLocalFaceis[proci];
175  forAll(fis, i)
176  {
177  localProcFaces[localFacei] = {proci, fis[i]};
178  localFacei ++;
179  }
180  }
181 
182  return localProcFaces;
183 }
184 
185 
187 (
188  const labelListList& tgtLocalSrcFaces,
189  const List<remote>& localTgtProcFaces
190 )
191 {
192  // Send a source face to a proc if target face on that proc intersects it
193  List<labelHashSet> resultDyn(Pstream::nProcs());
194  forAll(tgtLocalSrcFaces, tgtFacei)
195  {
196  const label tgtProci = localTgtProcFaces[tgtFacei].proci;
197 
198  forAll(tgtLocalSrcFaces[tgtFacei], i)
199  {
200  const label srcFacei = tgtLocalSrcFaces[tgtFacei][i];
201 
202  resultDyn[tgtProci].insert(srcFacei);
203  }
204  }
205 
206  // Transfer to non-dynamic storage
207  labelListList result(Pstream::nProcs());
208  forAll(result, proci)
209  {
210  result[proci] = resultDyn[proci].toc();
211  }
212 
213  return result;
214 }
215 
216 
218 (
219  const List<DynamicList<label>>& tgtLocalSrcFaces,
220  const List<remote>& localTgtProcFaces
221 )
222 {
223  return
225  (
226  labelListList(tgtLocalSrcFaces),
227  localTgtProcFaces
228  );
229 }
230 
231 
233 (
234  const boolList& oldIsUsed,
235  distributionMap& map,
236  labelList& oldToNew,
237  labelList& newToOld
238 )
239 {
240  // Create re-indexing
241  oldToNew.resize(oldIsUsed.size());
242  newToOld.resize(count(oldIsUsed, true));
243 
244  oldToNew = -1;
245  newToOld = -1;
246 
247  label newi = 0;
248  forAll(oldIsUsed, oldi)
249  {
250  if (oldIsUsed[oldi])
251  {
252  oldToNew[oldi] = newi;
253  newToOld[newi] = oldi;
254  ++ newi;
255  }
256  }
257 
258  // Per-processor used list for construction
259  List<boolList> allOldIsUsed(Pstream::nProcs());
260  forAll(map.constructMap(), proci)
261  {
262  allOldIsUsed[proci] =
263  UIndirectList<bool>(oldIsUsed, map.constructMap()[proci]);
264  }
265 
266  // Communicate to form a per-processor used list for subsetting
267  List<boolList> allSubOldIsUsed(Pstream::nProcs());
268  Pstream::exchange<boolList, bool>(allOldIsUsed, allSubOldIsUsed);
269 
270  // Subset the sub map
271  forAll(map.subMap(), proci)
272  {
273  label newi = 0;
274  forAll(map.subMap()[proci], oldi)
275  {
276  if (allSubOldIsUsed[proci][oldi])
277  {
278  map.subMap()[proci][newi ++] =
279  map.subMap()[proci][oldi];
280  }
281  }
282  map.subMap()[proci].resize(newi);
283  }
284 
285  // Subset and renumber the construct map
286  forAll(map.constructMap(), proci)
287  {
288  label newi = 0;
289  forAll(map.constructMap()[proci], oldi)
290  {
291  if (allOldIsUsed[proci][oldi])
292  {
293  map.constructMap()[proci][newi ++] =
294  oldToNew[map.constructMap()[proci][oldi]];
295  }
296  }
297  map.constructMap()[proci].resize(newi);
298  }
299 }
300 
301 
303 (
304  const labelListList& indices,
305  const List<remote>& indexToProcIndex
306 )
307 {
308  List<List<remote>> result(indices.size());
309 
310  forAll(indices, thisFacei)
311  {
312  result[thisFacei].resize(indices[thisFacei].size());
313 
314  forAll(indices[thisFacei], i)
315  {
316  result[thisFacei][i] =
317  isNull(indexToProcIndex)
318  ? remote(Pstream::myProcNo(), indices[thisFacei][i])
319  : indexToProcIndex[indices[thisFacei][i]];
320  }
321  }
322 
323  return result;
324 }
325 
326 
328 (
329  const List<DynamicList<label>>& indices,
330  const List<remote>& indexToProcIndex
331 )
332 {
333  return
335  (
336  labelListList(indices),
337  indexToProcIndex
338  );
339 }
340 
341 
343 (
344  const label tgtSize,
345  const distributionMap& tgtMap,
346  const List<remote>& localSrcProcFaces,
347  labelListList& tgtLocalSrcFaces
348 )
349 {
350  // Create a map from source procFace to local source face
351  HashTable<label, remote, Hash<remote>> srcProcFaceToLocal;
352  forAll(localSrcProcFaces, localSrcFacei)
353  {
354  srcProcFaceToLocal.insert
355  (
356  localSrcProcFaces[localSrcFacei],
357  localSrcFacei
358  );
359  }
360 
361  // Collect the source procFaces on the target and convert to local
362  // source face addressing
363  List<List<remote>> tgtSrcProcFaces = localToRemote(tgtLocalSrcFaces);
364 
365  rDistributeListList(tgtSize, tgtMap, tgtSrcProcFaces);
366 
367  tgtLocalSrcFaces.resize(tgtSize);
368  forAll(tgtSrcProcFaces, tgtFacei)
369  {
370  tgtLocalSrcFaces[tgtFacei].resize(tgtSrcProcFaces[tgtFacei].size());
371 
372  forAll(tgtSrcProcFaces[tgtFacei], i)
373  {
374  tgtLocalSrcFaces[tgtFacei][i] =
375  srcProcFaceToLocal[tgtSrcProcFaces[tgtFacei][i]];
376  }
377  }
378 }
379 
380 
382 (
383  const label tgtSize,
384  const distributionMap& tgtMap,
385  const List<remote>& localSrcProcFaces,
386  List<DynamicList<label>>& tgtLocalSrcFaces
387 )
388 {
389  labelListList tTgtLocalSrcFaces;
390  transferListList(tTgtLocalSrcFaces, tgtLocalSrcFaces);
392  (
393  tgtSize,
394  tgtMap,
395  localSrcProcFaces,
396  tTgtLocalSrcFaces
397  );
398  transferListList(tgtLocalSrcFaces, tTgtLocalSrcFaces);
399 }
400 
401 
402 // ************************************************************************* //
label n
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
An STL-conforming hash table.
Definition: HashTable.H:127
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
Definition: HashTableI.H:80
void resize(const label)
Alias for setSize(const label)
Definition: ListI.H:138
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
void setSize(const label)
Reset size of List.
Definition: List.C:281
Buffers for inter-processor communications streams (UOPstream, UIPstream).
void finishedSends(const bool block=true)
Mark all sends as having been done. This will start receives.
Input inter-processor communications stream operating on external buffer.
Definition: UIPstream.H:57
A List with indirect addressing.
Definition: UIndirectList.H:60
Output inter-processor communications stream operating on external buffer.
Definition: UOPstream.H:58
const labelListList & constructMap() const
From subsetted data to new reconstructed data.
const labelListList & subMap() const
From subsetted data back to original data.
Class containing processor-to-processor mapping information.
Struct for keeping processor, element (cell, face, point) index.
Definition: remote.H:57
label singleProcess(const label srcSize, const label tgtSize)
Determine whether this intersection is confined to a single processor or.
autoPtr< distributionMap > constructDistributionMap(const labelListList &procSendIndices)
Turn a list of send-to-processor indices into a distribution map.
List< remote > distributeAddressing(const distributionMap &map)
Construct local addressing from the given distribution map. The result is a.
void rDistributeTgtAddressing(const label tgtSize, const distributionMap &tgtMap, const List< remote > &localSrcProcFaces, labelListList &tgtLocalSrcFaces)
Reverse distribute a set of target addressing.
static void rDistributeListList(const label size, const distributionMap &map, List< List< Type >> &data)
Reverse distribute a list-list given the map.
labelListList procSendIndices(const labelListList &tgtLocalSrcFaces, const List< remote > &localTgtProcFaces)
Given a local intersection addressing, determine what elements need sending.
void trimDistributionMap(const boolList &oldIsUsed, distributionMap &map, labelList &oldToNew, labelList &newToOld)
Trim unused elements from a distribution map. Return the map and maps.
List< List< remote > > localToRemote(const labelListList &indices, const List< remote > &indexToProcIndex=NullObjectRef< List< remote >>())
Map local to remote indices.
static void transferListList(List< SubListA > &a, List< SubListB > &b)
Transfer list-list b into list-list a.
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
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:57
bool isNull(const T &t)
Return true if t is a reference to the nullObject of type T.
Definition: nullObjectI.H:52
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
label count(const ListType &l, typename ListType::const_reference x)
Count the number of occurrences of a value in a list.