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 | Copyright (C) 2011-2014 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 "AMIInterpolation.H"
27 #include "mergePoints.H"
28 #include "mapDistribute.H"
29 #include "AABBTree.H"
30 
31 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
32 
33 template<class SourcePatch, class TargetPatch>
35 (
36  const SourcePatch& srcPatch,
37  const TargetPatch& tgtPatch
38 ) const
39 {
40  label procI = 0;
41 
42  if (Pstream::parRun())
43  {
44  List<label> facesPresentOnProc(Pstream::nProcs(), 0);
45  if ((srcPatch.size() > 0) || (tgtPatch.size() > 0))
46  {
47  facesPresentOnProc[Pstream::myProcNo()] = 1;
48  }
49  else
50  {
51  facesPresentOnProc[Pstream::myProcNo()] = 0;
52  }
53 
54  Pstream::gatherList(facesPresentOnProc);
55  Pstream::scatterList(facesPresentOnProc);
56 
57  label nHaveFaces = sum(facesPresentOnProc);
58 
59  if (nHaveFaces > 1)
60  {
61  procI = -1;
62  if (debug)
63  {
64  Info<< "AMIInterpolation::calcDistribution: "
65  << "AMI split across multiple processors" << endl;
66  }
67  }
68  else if (nHaveFaces == 1)
69  {
70  procI = findIndex(facesPresentOnProc, 1);
71  if (debug)
72  {
73  Info<< "AMIInterpolation::calcDistribution: "
74  << "AMI local to processor" << procI << endl;
75  }
76  }
77  }
78 
79 
80  // Either not parallel or no faces on any processor
81  return procI;
82 }
83 
84 
85 template<class SourcePatch, class TargetPatch>
88 (
89  const List<treeBoundBoxList>& procBb,
90  const treeBoundBox& bb,
91  boolList& overlaps
92 ) const
93 {
94  overlaps.setSize(procBb.size());
95  overlaps = false;
96 
97  label nOverlaps = 0;
98 
99  forAll(procBb, procI)
100  {
101  const treeBoundBoxList& bbp = procBb[procI];
102 
103  forAll(bbp, bbI)
104  {
105  if (bbp[bbI].overlaps(bb))
106  {
107  overlaps[procI] = true;
108  nOverlaps++;
109  break;
110  }
111  }
112  }
113 
114  return nOverlaps;
115 }
116 
117 
118 template<class SourcePatch, class TargetPatch>
120 (
121  const mapDistribute& map,
122  const TargetPatch& pp,
123  const globalIndex& gi,
124  List<faceList>& faces,
126  List<labelList>& faceIDs
127 ) const
128 {
129  PstreamBuffers pBufs(Pstream::nonBlocking);
130 
131  for (label domain = 0; domain < Pstream::nProcs(); domain++)
132  {
133  const labelList& sendElems = map.subMap()[domain];
134 
135  if (domain != Pstream::myProcNo() && sendElems.size())
136  {
137  labelList globalElems(sendElems.size());
138  forAll(sendElems, i)
139  {
140  globalElems[i] = gi.toGlobal(sendElems[i]);
141  }
142 
143  faceList subFaces(UIndirectList<face>(pp, sendElems));
144  primitivePatch subPatch
145  (
146  SubList<face>(subFaces, subFaces.size()),
147  pp.points()
148  );
149 
150  if (debug & 2)
151  {
152  Pout<< "distributePatches: to processor " << domain
153  << " sending faces " << subPatch.faceCentres() << endl;
154  }
155 
156  UOPstream toDomain(domain, pBufs);
157  toDomain
158  << subPatch.localFaces() << subPatch.localPoints()
159  << globalElems;
160  }
161  }
162 
163  // Start receiving
164  pBufs.finishedSends();
165 
166  faces.setSize(Pstream::nProcs());
167  points.setSize(Pstream::nProcs());
168  faceIDs.setSize(Pstream::nProcs());
169 
170  {
171  // Set up 'send' to myself
172  const labelList& sendElems = map.subMap()[Pstream::myProcNo()];
173  faceList subFaces(UIndirectList<face>(pp, sendElems));
174  primitivePatch subPatch
175  (
176  SubList<face>(subFaces, subFaces.size()),
177  pp.points()
178  );
179 
180  // Receive
181  if (debug & 2)
182  {
183  Pout<< "distributePatches: to processor " << Pstream::myProcNo()
184  << " sending faces " << subPatch.faceCentres() << endl;
185  }
186 
187  faces[Pstream::myProcNo()] = subPatch.localFaces();
188  points[Pstream::myProcNo()] = subPatch.localPoints();
189 
190  faceIDs[Pstream::myProcNo()].setSize(sendElems.size());
191  forAll(sendElems, i)
192  {
193  faceIDs[Pstream::myProcNo()][i] = gi.toGlobal(sendElems[i]);
194  }
195  }
196 
197  // Consume
198  for (label domain = 0; domain < Pstream::nProcs(); domain++)
199  {
200  const labelList& recvElems = map.constructMap()[domain];
201 
202  if (domain != Pstream::myProcNo() && recvElems.size())
203  {
204  UIPstream str(domain, pBufs);
205 
206  str >> faces[domain]
207  >> points[domain]
208  >> faceIDs[domain];
209  }
210  }
211 }
212 
213 
214 template<class SourcePatch, class TargetPatch>
217 (
218  const mapDistribute& map,
219  const TargetPatch& tgtPatch,
220  const globalIndex& gi,
221  faceList& tgtFaces,
222  pointField& tgtPoints,
223  labelList& tgtFaceIDs
224 ) const
225 {
226  // Exchange per-processor data
227  List<faceList> allFaces;
229  List<labelList> allTgtFaceIDs;
230  distributePatches(map, tgtPatch, gi, allFaces, allPoints, allTgtFaceIDs);
231 
232  // Renumber and flatten
233  label nFaces = 0;
234  label nPoints = 0;
235  forAll(allFaces, procI)
236  {
237  nFaces += allFaces[procI].size();
238  nPoints += allPoints[procI].size();
239  }
240 
241  tgtFaces.setSize(nFaces);
242  tgtPoints.setSize(nPoints);
243  tgtFaceIDs.setSize(nFaces);
244 
245  nFaces = 0;
246  nPoints = 0;
247 
248  // My own data first
249  {
250  const labelList& faceIDs = allTgtFaceIDs[Pstream::myProcNo()];
251  SubList<label>(tgtFaceIDs, faceIDs.size()).assign(faceIDs);
252 
253  const faceList& fcs = allFaces[Pstream::myProcNo()];
254  forAll(fcs, i)
255  {
256  const face& f = fcs[i];
257  face& newF = tgtFaces[nFaces++];
258  newF.setSize(f.size());
259  forAll(f, fp)
260  {
261  newF[fp] = f[fp] + nPoints;
262  }
263  }
264 
265  const pointField& pts = allPoints[Pstream::myProcNo()];
266  forAll(pts, i)
267  {
268  tgtPoints[nPoints++] = pts[i];
269  }
270  }
271 
272 
273  // Other proc data follows
274  forAll(allFaces, procI)
275  {
276  if (procI != Pstream::myProcNo())
277  {
278  const labelList& faceIDs = allTgtFaceIDs[procI];
279  SubList<label>(tgtFaceIDs, faceIDs.size(), nFaces).assign(faceIDs);
280 
281  const faceList& fcs = allFaces[procI];
282  forAll(fcs, i)
283  {
284  const face& f = fcs[i];
285  face& newF = tgtFaces[nFaces++];
286  newF.setSize(f.size());
287  forAll(f, fp)
288  {
289  newF[fp] = f[fp] + nPoints;
290  }
291  }
292 
293  const pointField& pts = allPoints[procI];
294  forAll(pts, i)
295  {
296  tgtPoints[nPoints++] = pts[i];
297  }
298  }
299  }
300 
301  // Merge
302  labelList oldToNew;
303  pointField newTgtPoints;
304  bool hasMerged = mergePoints
305  (
306  tgtPoints,
307  SMALL,
308  false,
309  oldToNew,
310  newTgtPoints
311  );
312 
313  if (hasMerged)
314  {
315  if (debug)
316  {
317  Pout<< "Merged from " << tgtPoints.size()
318  << " down to " << newTgtPoints.size() << " points" << endl;
319  }
320 
321  tgtPoints.transfer(newTgtPoints);
322  forAll(tgtFaces, i)
323  {
324  inplaceRenumber(oldToNew, tgtFaces[i]);
325  }
326  }
327 }
328 
329 
330 template<class SourcePatch, class TargetPatch>
333 (
334  const SourcePatch& srcPatch,
335  const TargetPatch& tgtPatch
336 ) const
337 {
338  // Get decomposition of patch
339  List<treeBoundBoxList> procBb(Pstream::nProcs());
340 
341  if (srcPatch.size())
342  {
343  procBb[Pstream::myProcNo()] =
345  (
346  srcPatch.localFaces(),
347  srcPatch.localPoints(),
348  false
349  ).boundBoxes();
350  }
351  else
352  {
353  procBb[Pstream::myProcNo()] = treeBoundBoxList();
354  }
355 
356  Pstream::gatherList(procBb);
357  Pstream::scatterList(procBb);
358 
359  if (debug)
360  {
361  Info<< "Determining extent of srcPatch per processor:" << nl
362  << "\tproc\tbb" << endl;
363  forAll(procBb, procI)
364  {
365  Info<< '\t' << procI << '\t' << procBb[procI] << endl;
366  }
367  }
368 
369  // Determine which faces of tgtPatch overlaps srcPatch per proc
370  const faceList& faces = tgtPatch.localFaces();
371  const pointField& points = tgtPatch.localPoints();
372 
373  labelListList sendMap;
374 
375  {
376  // Per processor indices into all segments to send
377  List<DynamicList<label> > dynSendMap(Pstream::nProcs());
378 
379  // Work array - whether processor bb overlaps the face bounds
380  boolList procBbOverlaps(Pstream::nProcs());
381 
382  forAll(faces, faceI)
383  {
384  if (faces[faceI].size())
385  {
386  treeBoundBox faceBb(points, faces[faceI]);
387 
388  // Find the processor this face overlaps
389  calcOverlappingProcs(procBb, faceBb, procBbOverlaps);
390 
391  forAll(procBbOverlaps, procI)
392  {
393  if (procBbOverlaps[procI])
394  {
395  dynSendMap[procI].append(faceI);
396  }
397  }
398  }
399  }
400 
401  // Convert dynamicList to labelList
402  sendMap.setSize(Pstream::nProcs());
403  forAll(sendMap, procI)
404  {
405  sendMap[procI].transfer(dynSendMap[procI]);
406  }
407  }
408 
409  // Debug printing
410  if (debug)
411  {
412  Pout<< "Of my " << faces.size() << " I need to send to:" << nl
413  << "\tproc\tfaces" << endl;
414  forAll(sendMap, procI)
415  {
416  Pout<< '\t' << procI << '\t' << sendMap[procI].size() << endl;
417  }
418  }
419 
420 
421  // Send over how many faces I need to receive
422  labelListList sendSizes(Pstream::nProcs());
423  sendSizes[Pstream::myProcNo()].setSize(Pstream::nProcs());
424  forAll(sendMap, procI)
425  {
426  sendSizes[Pstream::myProcNo()][procI] = sendMap[procI].size();
427  }
428  Pstream::gatherList(sendSizes);
429  Pstream::scatterList(sendSizes);
430 
431 
432  // Determine order of receiving
433  labelListList constructMap(Pstream::nProcs());
434 
435  // My local segment first
436  constructMap[Pstream::myProcNo()] = identity
437  (
438  sendMap[Pstream::myProcNo()].size()
439  );
440 
441  label segmentI = constructMap[Pstream::myProcNo()].size();
442  forAll(constructMap, procI)
443  {
444  if (procI != Pstream::myProcNo())
445  {
446  // What I need to receive is what other processor is sending to me
447  label nRecv = sendSizes[procI][Pstream::myProcNo()];
448  constructMap[procI].setSize(nRecv);
449 
450  for (label i = 0; i < nRecv; i++)
451  {
452  constructMap[procI][i] = segmentI++;
453  }
454  }
455  }
456 
458  (
459  new mapDistribute
460  (
461  segmentI, // size after construction
462  sendMap.xfer(),
463  constructMap.xfer()
464  )
465  );
466 
467  return mapPtr;
468 }
469 
470 
471 // ************************************************************************* //
Foam::mapDistributeBase::subMap
const labelListList & subMap() const
From subsetted data back to original data.
Definition: mapDistributeBase.H:256
Foam::AMIInterpolation::calcProcMap
autoPtr< mapDistribute > calcProcMap(const SourcePatch &srcPatch, const TargetPatch &tgtPatch) const
Definition: AMIInterpolationParallelOps.C:333
Foam::UOPstream
Output inter-processor communications stream operating on external buffer.
Definition: UOPstream.H:54
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::findIndex
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurence of given element and return index,.
Foam::List::xfer
Xfer< List< T > > xfer()
Transfer contents to the Xfer container.
Definition: ListI.H:90
Foam::PrimitivePatch::localPoints
const Field< PointType > & localPoints() const
Return pointField of points in patch.
Definition: PrimitivePatchTemplate.C:432
Foam::SubList
A List obtained as a section of another List.
Definition: SubList.H:53
Foam::treeBoundBox
Standard boundBox + extra functionality for use in octree.
Definition: treeBoundBox.H:75
Foam::PstreamBuffers
Buffers for inter-processor communications streams (UOPstream, UIPstream).
Definition: PstreamBuffers.H:85
Foam::List::transfer
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Foam::AABBTree::boundBoxes
const List< treeBoundBox > & boundBoxes() const
Return the bounding boxes making up the tree.
Definition: AABBTree.C:428
Foam::AMIInterpolation::calcOverlappingProcs
label calcOverlappingProcs(const List< treeBoundBoxList > &procBb, const treeBoundBox &bb, boolList &overlaps) const
Definition: AMIInterpolationParallelOps.C:88
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
AMIInterpolation.H
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Foam::inplaceRenumber
void inplaceRenumber(const labelUList &oldToNew, ListType &)
Inplace renumber the values of a list.
Definition: ListOpsTemplates.C:57
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:59
Foam::Field
Pre-declare SubField and related Field type.
Definition: Field.H:57
Foam::List::append
void append(const T &)
Append an element at the end of the list.
Foam::nl
static const char nl
Definition: Ostream.H:260
Foam::Info
messageStream Info
Foam::mapDistribute
Class containing processor-to-processor mapping information.
Definition: mapDistribute.H:152
Foam::UList::assign
void assign(const UList< T > &)
Assign elements to those from UList.
Definition: UList.C:37
AABBTree.H
Foam::PstreamBuffers::finishedSends
void finishedSends(const bool block=true)
Mark all sends as having been done. This will start receives.
Definition: PstreamBuffers.C:82
Foam::identity
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
Foam::globalIndex
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:63
Foam::AMIInterpolation::distributeAndMergePatches
void distributeAndMergePatches(const mapDistribute &map, const TargetPatch &tgtPatch, const globalIndex &gi, faceList &tgtFaces, pointField &tgtPoints, labelList &tgtFaceIDs) const
Definition: AMIInterpolationParallelOps.C:217
Foam::List::setSize
void setSize(const label)
Reset size of List.
Foam::autoPtr< Foam::mapDistribute >
Foam::AMIInterpolation::distributePatches
void distributePatches(const mapDistribute &map, const TargetPatch &pp, const globalIndex &gi, List< faceList > &faces, List< pointField > &points, List< labelList > &tgtFaceIDs) const
Definition: AMIInterpolationParallelOps.C:120
Foam::Pout
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
mapDistribute.H
f
labelList f(nPoints)
Foam::AABBTree
Templated tree of axis-aligned bounding boxes (AABB)
Definition: AABBTree.H:57
Foam::List< label >
Foam::PrimitivePatch::faceCentres
const Field< PointType > & faceCentres() const
Return face centres for patch.
Definition: PrimitivePatchTemplate.C:500
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:333
mergePoints.H
Merge points. See below.
Foam::PrimitivePatch::localFaces
const List< Face > & localFaces() const
Return patch faces addressing into local point list.
Definition: PrimitivePatchTemplate.C:372
Foam::UIndirectList
A List with indirect addressing.
Definition: fvMatrix.H:106
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
Foam::DelaunayMeshTools::allPoints
tmp< pointField > allPoints(const Triangulation &t)
Extract all points in vertex-index order.
Foam::List::size
void size(const label)
Override size to be inconsistent with allocated storage.
Foam::UIPstream
Input inter-processor communications stream operating on external buffer.
Definition: UIPstream.H:53
Foam::AMIInterpolation::calcDistribution
label calcDistribution(const SourcePatch &srcPatch, const TargetPatch &tgtPatch) const
Calculate if patches are on multiple processors.
Definition: AMIInterpolationParallelOps.C:35
Foam::mapDistributeBase::constructMap
const labelListList & constructMap() const
From subsetted data to new reconstructed data.
Definition: mapDistributeBase.H:268
Foam::treeBoundBoxList
List< treeBoundBox > treeBoundBoxList
List of bounding boxes.
Definition: treeBoundBoxList.H:44
Foam::mergePoints
label mergePoints(const UList< Type > &points, const scalar mergeTol, const bool verbose, labelList &pointMap, const Type &origin=Type::zero)
Sorts and merges points. All points closer than/equal mergeTol get merged.
Foam::globalIndex::toGlobal
label toGlobal(const label i) const
From local to global.
Definition: globalIndexI.H:82
Foam::PrimitivePatch
A list of faces which address into the list of points.
Definition: PrimitivePatchTemplate.H:88