advancingFrontAMIParallelOps.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  Copyright (C) 2018-2022 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "advancingFrontAMI.H"
30 #include "mergePoints.H"
31 #include "mapDistribute.H"
32 #include "AABBTree.H"
33 
34 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
35 
36 Foam::label Foam::advancingFrontAMI::calcOverlappingProcs
37 (
38  const List<treeBoundBoxList>& procBb,
39  const treeBoundBox& bb,
40  boolList& overlaps
41 ) const
42 {
43  overlaps.setSize(procBb.size());
44  overlaps = false;
45 
46  label nOverlaps = 0;
47 
48  forAll(procBb, proci)
49  {
50  const treeBoundBoxList& bbp = procBb[proci];
51 
52  for (const treeBoundBox& tbb: bbp)
53  {
54  if (tbb.overlaps(bb))
55  {
56  overlaps[proci] = true;
57  ++nOverlaps;
58  break;
59  }
60  }
61  }
62 
63  return nOverlaps;
64 }
65 
66 
67 void Foam::advancingFrontAMI::distributePatches
68 (
69  const mapDistribute& map,
70  const primitivePatch& pp,
71  const globalIndex& gi,
72  List<faceList>& faces,
73  List<pointField>& points,
74  List<labelList>& faceIDs
75 ) const
76 {
77  faces.setSize(Pstream::nProcs(comm_));
79  faceIDs.setSize(Pstream::nProcs(comm_));
80 
81  PstreamBuffers pBufs
82  (
85  comm_
86  );
87 
88  for (const int domain : Pstream::allProcs(comm_))
89  {
90  const labelList& sendElems = map.subMap()[domain];
91 
92  if (sendElems.empty())
93  {
94  // Safety
95  faces[domain].clear();
96  points[domain].clear();
97  faceIDs[domain].clear();
98  }
99  else
100  {
101  faceList subFaces(UIndirectList<face>(pp, sendElems));
102  primitivePatch subPatch(SubList<face>(subFaces), pp.points());
103 
104  if (debug & 2)
105  {
106  Pout<< "distributePatches: to processor " << domain
107  << " sending faces " << subPatch.faceCentres() << endl;
108  }
109 
110 
111  if (domain == Pstream::myProcNo(comm_))
112  {
113  // Do send/receive for myself
114  faces[domain] = subPatch.localFaces();
115  points[domain] = subPatch.localPoints();
116  faceIDs[domain] =
117  gi.toGlobal(Pstream::myProcNo(comm_), sendElems);
118  }
119  else
120  {
121  // Normal send
122  UOPstream str(domain, pBufs);
123  str
124  << subPatch.localFaces()
125  << subPatch.localPoints()
126  << gi.toGlobal(Pstream::myProcNo(comm_), sendElems);
127  }
128  }
129  }
130 
131  pBufs.finishedSends();
132 
133 
134  // Consume
135  for (const int domain : Pstream::allProcs(comm_))
136  {
137  const labelList& recvElems = map.constructMap()[domain];
138 
139  if (domain != Pstream::myProcNo(comm_) && recvElems.size())
140  {
141  UIPstream is(domain, pBufs);
142 
143  is >> faces[domain]
144  >> points[domain]
145  >> faceIDs[domain];
146  }
147  }
148 }
149 
150 
151 void Foam::advancingFrontAMI::distributeAndMergePatches
152 (
153  const mapDistribute& map,
154  const primitivePatch& tgtPatch,
155  const globalIndex& gi,
156  faceList& tgtFaces,
157  pointField& tgtPoints,
158  labelList& tgtFaceIDs
159 ) const
160 {
161  // Exchange per-processor data
162  List<faceList> allFaces;
163  List<pointField> allPoints;
164  List<labelList> allTgtFaceIDs;
165  distributePatches(map, tgtPatch, gi, allFaces, allPoints, allTgtFaceIDs);
166 
167  // Renumber and flatten
168  label nFaces = 0;
169  label nPoints = 0;
170  forAll(allFaces, proci)
171  {
172  nFaces += allFaces[proci].size();
173  nPoints += allPoints[proci].size();
174  }
175 
176  tgtFaces.setSize(nFaces);
177  tgtPoints.setSize(nPoints);
178  tgtFaceIDs.setSize(nFaces);
179 
180  nFaces = 0;
181  nPoints = 0;
182 
183  // My own data first
184  {
185  const labelList& faceIDs = allTgtFaceIDs[Pstream::myProcNo(comm_)];
186  SubList<label>(tgtFaceIDs, faceIDs.size()) = faceIDs;
187 
188  const faceList& fcs = allFaces[Pstream::myProcNo(comm_)];
189  for (const face& f : fcs)
190  {
191  face& newF = tgtFaces[nFaces++];
192  newF.setSize(f.size());
193  forAll(f, fp)
194  {
195  newF[fp] = f[fp] + nPoints;
196  }
197  }
198 
199  const pointField& pts = allPoints[Pstream::myProcNo(comm_)];
200  for (const point& pt: pts)
201  {
202  tgtPoints[nPoints++] = pt;
203  }
204  }
205 
206 
207  // Other proc data follows
208  forAll(allFaces, proci)
209  {
210  if (proci != Pstream::myProcNo(comm_))
211  {
212  const labelList& faceIDs = allTgtFaceIDs[proci];
213  SubList<label>(tgtFaceIDs, faceIDs.size(), nFaces) = faceIDs;
214 
215  const faceList& fcs = allFaces[proci];
216  for (const face& f : fcs)
217  {
218  face& newF = tgtFaces[nFaces++];
219  newF.setSize(f.size());
220  forAll(f, fp)
221  {
222  newF[fp] = f[fp] + nPoints;
223  }
224  }
225 
226  const pointField& pts = allPoints[proci];
227  for (const point& pt: pts)
228  {
229  tgtPoints[nPoints++] = pt;
230  }
231  }
232  }
233 
234  // Merge
235  labelList oldToNew;
236  bool nChanged = Foam::inplaceMergePoints
237  (
238  tgtPoints,
239  SMALL,
240  false,
241  oldToNew
242  );
243 
244  if (nChanged)
245  {
246  if (debug)
247  {
248  Pout<< "Merged from " << oldToNew.size()
249  << " down to " << tgtPoints.size() << " points" << endl;
250  }
251 
252  for (face& f : tgtFaces)
253  {
254  inplaceRenumber(oldToNew, f);
255  }
256  }
257 }
258 
259 
260 Foam::autoPtr<Foam::mapDistribute> Foam::advancingFrontAMI::calcProcMap
261 (
262  const primitivePatch& srcPatch,
263  const primitivePatch& tgtPatch
264 ) const
265 {
266  // Get decomposition of patch
267  List<treeBoundBoxList> procBb(Pstream::nProcs(comm_));
268 
269  if (srcPatch.size())
270  {
271  procBb[Pstream::myProcNo(comm_)] =
272  AABBTree<face>
273  (
274  srcPatch.localFaces(),
275  srcPatch.localPoints(),
276  false
277  ).boundBoxes();
278  }
279  else
280  {
281  procBb[Pstream::myProcNo(comm_)] = treeBoundBoxList();
282  }
283 
284  Pstream::allGatherList(procBb, UPstream::msgType(), comm_);
285 
286  if (debug)
287  {
288  Info<< "Determining extent of srcPatch per processor:" << nl
289  << "\tproc\tbb" << endl;
290  forAll(procBb, proci)
291  {
292  Info<< '\t' << proci << '\t' << procBb[proci] << endl;
293  }
294  }
295 
296  // Determine which faces of tgtPatch overlaps srcPatch per proc
297  const faceList& faces = tgtPatch.localFaces();
298  const pointField& points = tgtPatch.localPoints();
299 
300  labelListList sendMap;
301 
302  {
303  // Per processor indices into all segments to send
304  List<DynamicList<label>> dynSendMap(Pstream::nProcs(comm_));
305 
306  // Work array - whether processor bb overlaps the face bounds
307  boolList procBbOverlaps(Pstream::nProcs(comm_));
308 
309  forAll(faces, facei)
310  {
311  if (faces[facei].size())
312  {
313  treeBoundBox faceBb(points, faces[facei]);
314 
315  // Find the processor this face overlaps
316  calcOverlappingProcs(procBb, faceBb, procBbOverlaps);
317 
318  forAll(procBbOverlaps, proci)
319  {
320  if (procBbOverlaps[proci])
321  {
322  dynSendMap[proci].append(facei);
323  }
324  }
325  }
326  }
327 
328  // Convert dynamicList to labelList
329  sendMap.setSize(Pstream::nProcs(comm_));
330  forAll(sendMap, proci)
331  {
332  sendMap[proci].transfer(dynSendMap[proci]);
333  }
334  }
335 
336  // Debug printing
337  if (debug)
338  {
339  Pout<< "Of my " << faces.size() << " I need to send to:" << nl
340  << "\tproc\tfaces" << endl;
341  forAll(sendMap, proci)
342  {
343  Pout<< '\t' << proci << '\t' << sendMap[proci].size() << endl;
344  }
345  }
346 
348  (
349  std::move(sendMap),
350  false, //subHasFlip
351  false, //constructHasFlip
352  comm_
353  );
354 }
355 
356 
357 // ************************************************************************* //
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
static rangeType allProcs(const label communicator=worldComm)
Range of process indices for all processes.
Definition: UPstream.H:1176
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:1229
List< treeBoundBox > treeBoundBoxList
A List of treeBoundBox.
Definition: treeBoundBox.H:83
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Can be negative if the process i...
Definition: UPstream.H:1074
List< labelList > labelListList
List of labelList.
Definition: labelList.H:38
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
static void allGatherList(List< T > &values, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Gather data, but keep individual values separate. Uses linear/tree communication. ...
List< face > faceList
List of faces.
Definition: faceListFwd.H:39
static label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run. ...
Definition: UPstream.H:1065
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
void setSize(const label n)
Alias for resize()
Definition: List.H:316
const pointField & points
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:137
label nPoints
const Field< point_type > & points() const noexcept
Return reference to global points.
label inplaceMergePoints(PointList &points, const scalar mergeTol, const bool verbose, labelList &pointToUnique)
Inplace merge points, preserving the original point order. All points closer/equal mergeTol are to be...
int debug
Static debugging option.
Geometric merging of points. See below.
labelList f(nPoints)
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
A PrimitivePatch with a SubList addressing for the faces, const reference for the point field...
void inplaceRenumber(const labelUList &oldToNew, IntListType &input)
Inplace renumber the values (not the indices) of a list.
vector point
Point is a vector.
Definition: point.H:37
"nonBlocking" : (MPI_Isend, MPI_Irecv)
messageStream Info
Information stream (stdout output on master, null elsewhere)
tmp< pointField > allPoints(const Triangulation &t)
Extract all points in vertex-index order.
List< label > labelList
A List of labels.
Definition: List.H:62
static autoPtr< T > New(Args &&... args)
Construct autoPtr with forwarding arguments.
Definition: autoPtr.H:178
List< bool > boolList
A List of bools.
Definition: List.H:60
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
const pointField & pts