AMIInterpolationParallelOps.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2017 OpenFOAM Foundation
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "AMIInterpolation.H"
29 #include "mergePoints.H"
30 #include "mapDistribute.H"
31 #include "AABBTree.H"
32 
33 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
34 
35 template<class SourcePatch, class TargetPatch>
37 (
38  const SourcePatch& srcPatch,
39  const TargetPatch& tgtPatch
40 ) const
41 {
42  label proci = 0;
43 
44  if (Pstream::parRun())
45  {
46  labelList facesPresentOnProc(Pstream::nProcs(), Zero);
47  if ((srcPatch.size() > 0) || (tgtPatch.size() > 0))
48  {
49  facesPresentOnProc[Pstream::myProcNo()] = 1;
50  }
51  else
52  {
53  facesPresentOnProc[Pstream::myProcNo()] = 0;
54  }
55 
56  Pstream::gatherList(facesPresentOnProc);
57  Pstream::scatterList(facesPresentOnProc);
58 
59  label nHaveFaces = sum(facesPresentOnProc);
60 
61  if (nHaveFaces > 1)
62  {
63  proci = -1;
64  if (debug)
65  {
67  << "AMI split across multiple processors" << endl;
68  }
69  }
70  else if (nHaveFaces == 1)
71  {
72  proci = facesPresentOnProc.find(1);
73  if (debug)
74  {
76  << "AMI local to processor" << proci << endl;
77  }
78  }
79  }
80 
81 
82  // Either not parallel or no faces on any processor
83  return proci;
84 }
85 
86 
87 template<class SourcePatch, class TargetPatch>
90 (
91  const List<treeBoundBoxList>& procBb,
92  const treeBoundBox& bb,
93  boolList& overlaps
94 ) const
95 {
96  overlaps.setSize(procBb.size());
97  overlaps = false;
98 
99  label nOverlaps = 0;
100 
101  forAll(procBb, proci)
102  {
103  const treeBoundBoxList& bbp = procBb[proci];
104 
105  for (const treeBoundBox& tbb: bbp)
106  {
107  if (tbb.overlaps(bb))
108  {
109  overlaps[proci] = true;
110  nOverlaps++;
111  break;
112  }
113  }
114  }
115 
116  return nOverlaps;
117 }
118 
119 
120 template<class SourcePatch, class TargetPatch>
122 (
123  const mapDistribute& map,
124  const TargetPatch& pp,
125  const globalIndex& gi,
126  List<faceList>& faces,
127  List<pointField>& points,
128  List<labelList>& faceIDs
129 ) const
130 {
131  PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
132 
133  for (label domain = 0; domain < Pstream::nProcs(); ++domain)
134  {
135  const labelList& sendElems = map.subMap()[domain];
136 
137  if (domain != Pstream::myProcNo() && sendElems.size())
138  {
139  faceList subFaces(UIndirectList<face>(pp, sendElems));
140  primitivePatch subPatch
141  (
142  SubList<face>(subFaces, subFaces.size()),
143  pp.points()
144  );
145 
146  if (debug & 2)
147  {
148  Pout<< "distributePatches: to processor " << domain
149  << " sending faces " << subPatch.faceCentres() << endl;
150  }
151 
152  UOPstream toDomain(domain, pBufs);
153  toDomain
154  << subPatch.localFaces() << subPatch.localPoints()
155  << gi.toGlobal(sendElems);
156  }
157  }
158 
159  // Start receiving
160  pBufs.finishedSends();
161 
162  faces.setSize(Pstream::nProcs());
163  points.setSize(Pstream::nProcs());
164  faceIDs.setSize(Pstream::nProcs());
165 
166  {
167  // Set up 'send' to myself
168  const labelList& sendElems = map.subMap()[Pstream::myProcNo()];
169  faceList subFaces(UIndirectList<face>(pp, sendElems));
170  primitivePatch subPatch
171  (
172  SubList<face>(subFaces, subFaces.size()),
173  pp.points()
174  );
175 
176  // Receive
177  if (debug & 2)
178  {
179  Pout<< "distributePatches: to processor " << Pstream::myProcNo()
180  << " sending faces " << subPatch.faceCentres() << endl;
181  }
182 
183  faces[Pstream::myProcNo()] = subPatch.localFaces();
184  points[Pstream::myProcNo()] = subPatch.localPoints();
185  faceIDs[Pstream::myProcNo()] = gi.toGlobal(sendElems);
186  }
187 
188  // Consume
189  for (label domain = 0; domain < Pstream::nProcs(); ++domain)
190  {
191  const labelList& recvElems = map.constructMap()[domain];
192 
193  if (domain != Pstream::myProcNo() && recvElems.size())
194  {
195  UIPstream str(domain, pBufs);
196 
197  str >> faces[domain]
198  >> points[domain]
199  >> faceIDs[domain];
200  }
201  }
202 }
203 
204 
205 template<class SourcePatch, class TargetPatch>
208 (
209  const mapDistribute& map,
210  const TargetPatch& tgtPatch,
211  const globalIndex& gi,
212  faceList& tgtFaces,
213  pointField& tgtPoints,
214  labelList& tgtFaceIDs
215 ) const
216 {
217  // Exchange per-processor data
218  List<faceList> allFaces;
219  List<pointField> allPoints;
220  List<labelList> allTgtFaceIDs;
221  distributePatches(map, tgtPatch, gi, allFaces, allPoints, allTgtFaceIDs);
222 
223  // Renumber and flatten
224  label nFaces = 0;
225  label nPoints = 0;
226  forAll(allFaces, proci)
227  {
228  nFaces += allFaces[proci].size();
229  nPoints += allPoints[proci].size();
230  }
231 
232  tgtFaces.setSize(nFaces);
233  tgtPoints.setSize(nPoints);
234  tgtFaceIDs.setSize(nFaces);
235 
236  nFaces = 0;
237  nPoints = 0;
238 
239  // My own data first
240  {
241  const labelList& faceIDs = allTgtFaceIDs[Pstream::myProcNo()];
242  SubList<label>(tgtFaceIDs, faceIDs.size()) = faceIDs;
243 
244  const faceList& fcs = allFaces[Pstream::myProcNo()];
245  for (const face& f : fcs)
246  {
247  face& newF = tgtFaces[nFaces++];
248  newF.setSize(f.size());
249  forAll(f, fp)
250  {
251  newF[fp] = f[fp] + nPoints;
252  }
253  }
254 
255  const pointField& pts = allPoints[Pstream::myProcNo()];
256  for (const point& pt: pts)
257  {
258  tgtPoints[nPoints++] = pt;
259  }
260  }
261 
262 
263  // Other proc data follows
264  forAll(allFaces, proci)
265  {
266  if (proci != Pstream::myProcNo())
267  {
268  const labelList& faceIDs = allTgtFaceIDs[proci];
269  SubList<label>(tgtFaceIDs, faceIDs.size(), nFaces) = faceIDs;
270 
271  const faceList& fcs = allFaces[proci];
272  for (const face& f : fcs)
273  {
274  face& newF = tgtFaces[nFaces++];
275  newF.setSize(f.size());
276  forAll(f, fp)
277  {
278  newF[fp] = f[fp] + nPoints;
279  }
280  }
281 
282  const pointField& pts = allPoints[proci];
283  for (const point& pt: pts)
284  {
285  tgtPoints[nPoints++] = pt;
286  }
287  }
288  }
289 
290  // Merge
291  labelList oldToNew;
292  pointField newTgtPoints;
293  bool hasMerged = mergePoints
294  (
295  tgtPoints,
296  SMALL,
297  false,
298  oldToNew,
299  newTgtPoints
300  );
301 
302  if (hasMerged)
303  {
304  if (debug)
305  {
306  Pout<< "Merged from " << tgtPoints.size()
307  << " down to " << newTgtPoints.size() << " points" << endl;
308  }
309 
310  tgtPoints.transfer(newTgtPoints);
311  for (face& f : tgtFaces)
312  {
313  inplaceRenumber(oldToNew, f);
314  }
315  }
316 }
317 
318 
319 template<class SourcePatch, class TargetPatch>
322 (
323  const SourcePatch& srcPatch,
324  const TargetPatch& tgtPatch
325 ) const
326 {
327  // Get decomposition of patch
328  List<treeBoundBoxList> procBb(Pstream::nProcs());
329 
330  if (srcPatch.size())
331  {
332  procBb[Pstream::myProcNo()] =
333  AABBTree<face>
334  (
335  srcPatch.localFaces(),
336  srcPatch.localPoints(),
337  false
338  ).boundBoxes();
339  }
340  else
341  {
342  procBb[Pstream::myProcNo()] = treeBoundBoxList();
343  }
344 
345  Pstream::gatherList(procBb);
346  Pstream::scatterList(procBb);
347 
348  if (debug)
349  {
350  Info<< "Determining extent of srcPatch per processor:" << nl
351  << "\tproc\tbb" << endl;
352  forAll(procBb, proci)
353  {
354  Info<< '\t' << proci << '\t' << procBb[proci] << endl;
355  }
356  }
357 
358  // Determine which faces of tgtPatch overlaps srcPatch per proc
359  const faceList& faces = tgtPatch.localFaces();
360  const pointField& points = tgtPatch.localPoints();
361 
362  labelListList sendMap;
363 
364  {
365  // Per processor indices into all segments to send
366  List<DynamicList<label>> dynSendMap(Pstream::nProcs());
367 
368  // Work array - whether processor bb overlaps the face bounds
369  boolList procBbOverlaps(Pstream::nProcs());
370 
371  forAll(faces, facei)
372  {
373  if (faces[facei].size())
374  {
375  treeBoundBox faceBb(points, faces[facei]);
376 
377  // Find the processor this face overlaps
378  calcOverlappingProcs(procBb, faceBb, procBbOverlaps);
379 
380  forAll(procBbOverlaps, proci)
381  {
382  if (procBbOverlaps[proci])
383  {
384  dynSendMap[proci].append(facei);
385  }
386  }
387  }
388  }
389 
390  // Convert dynamicList to labelList
391  sendMap.setSize(Pstream::nProcs());
392  forAll(sendMap, proci)
393  {
394  sendMap[proci].transfer(dynSendMap[proci]);
395  }
396  }
397 
398  // Debug printing
399  if (debug)
400  {
401  Pout<< "Of my " << faces.size() << " I need to send to:" << nl
402  << "\tproc\tfaces" << endl;
403  forAll(sendMap, proci)
404  {
405  Pout<< '\t' << proci << '\t' << sendMap[proci].size() << endl;
406  }
407  }
408 
409 
410  // Send over how many faces I need to receive
411  labelListList sendSizes(Pstream::nProcs());
412  sendSizes[Pstream::myProcNo()].setSize(Pstream::nProcs());
413  forAll(sendMap, proci)
414  {
415  sendSizes[Pstream::myProcNo()][proci] = sendMap[proci].size();
416  }
417  Pstream::gatherList(sendSizes);
418  Pstream::scatterList(sendSizes);
419 
420 
421  // Determine order of receiving
422  labelListList constructMap(Pstream::nProcs());
423 
424  // My local segment first
425  constructMap[Pstream::myProcNo()] = identity
426  (
427  sendMap[Pstream::myProcNo()].size()
428  );
429 
430  label segmentI = constructMap[Pstream::myProcNo()].size();
431  forAll(constructMap, proci)
432  {
433  if (proci != Pstream::myProcNo())
434  {
435  // What I need to receive is what other processor is sending to me
436  label nRecv = sendSizes[proci][Pstream::myProcNo()];
437  constructMap[proci].setSize(nRecv);
438 
439  for (label i = 0; i < nRecv; ++i)
440  {
441  constructMap[proci][i] = segmentI++;
442  }
443  }
444  }
445 
447  (
448  segmentI, // size after construction
449  std::move(sendMap),
450  std::move(constructMap)
451  );
452 }
453 
454 
455 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:74
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
InfoInFunction
#define InfoInFunction
Report an information message using Foam::Info.
Definition: messageStream.H:316
Foam::Zero
static constexpr const zero Zero
Global zero.
Definition: zero.H:128
Foam::boolList
List< bool > boolList
A List of bools.
Definition: List.H:72
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::Pout
prefixOSstream Pout
An Ostream wrapper for parallel output to std::cout.
AMIInterpolation.H
Foam::inplaceRenumber
void inplaceRenumber(const labelUList &oldToNew, IntListType &input)
Inplace renumber the values (not the indices) of a list.
Definition: ListOpsTemplates.C:61
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Foam::label
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:62
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
AABBTree.H
Foam::mergePoints
label mergePoints(const PointList &points, const scalar mergeTol, const bool verbose, labelList &pointMap, typename PointList::const_reference origin=PointList::value_type::zero)
Sorts and merges points. All points closer than/equal mergeTol get merged.
Foam::New
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tdf1, const word &name, const dimensionSet &dimensions)
Global function forwards to reuseTmpDimensionedField::New.
Definition: DimensionedFieldReuseFunctions.H:105
Foam::autoPtr< Foam::mapDistribute >
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
Foam::nl
constexpr char nl
Definition: Ostream.H:372
mapDistribute.H
f
labelList f(nPoints)
Foam::faceList
List< face > faceList
A List of faces.
Definition: faceListFwd.H:47
Foam::AMIInterpolation
Interpolation class dealing with transfer of data between two primitive patches with an arbitrary mes...
Definition: AMIInterpolation.H:81
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::identity
labelList identity(const label len, label start=0)
Create identity map of the given length with (map[i] == i)
Definition: labelList.C:38
Foam::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:327
mergePoints.H
Merge points. See below.
Foam::primitivePatch
PrimitivePatch< face, SubList, const pointField & > primitivePatch
Addressing for a faceList slice.
Definition: primitivePatch.H:47
Foam::DelaunayMeshTools::allPoints
tmp< pointField > allPoints(const Triangulation &t)
Extract all points in vertex-index order.
Foam::point
vector point
Point is a vector.
Definition: point.H:43
Foam::List::setSize
void setSize(const label newSize)
Alias for resize(const label)
Definition: ListI.H:146
Foam::treeBoundBoxList
List< treeBoundBox > treeBoundBoxList
List of bounding boxes.
Definition: treeBoundBoxList.H:46