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.resize_nocopy(Pstream::nProcs());
79  faceIDs.resize_nocopy(Pstream::nProcs());
80 
81 
82  PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
83 
84  for (const int domain : Pstream::allProcs())
85  {
86  const labelList& sendElems = map.subMap()[domain];
87 
88  if (sendElems.empty())
89  {
90  // Safety
91  faces[domain].clear();
92  points[domain].clear();
93  faceIDs[domain].clear();
94  }
95  else
96  {
97  faceList subFaces(UIndirectList<face>(pp, sendElems));
98  primitivePatch subPatch(SubList<face>(subFaces), pp.points());
99 
100  if (debug & 2)
101  {
102  Pout<< "distributePatches: to processor " << domain
103  << " sending faces " << subPatch.faceCentres() << endl;
104  }
105 
106 
107  if (domain == Pstream::myProcNo())
108  {
109  // Do send/receive for myself
110  faces[domain] = subPatch.localFaces();
111  points[domain] = subPatch.localPoints();
112  faceIDs[domain] = gi.toGlobal(sendElems);
113  }
114  else
115  {
116  // Normal send
117  UOPstream str(domain, pBufs);
118  str
119  << subPatch.localFaces()
120  << subPatch.localPoints()
121  << gi.toGlobal(sendElems);
122  }
123  }
124  }
125 
126  pBufs.finishedSends();
127 
128  // Consume
129  for (const int domain : Pstream::allProcs())
130  {
131  const labelList& recvElems = map.constructMap()[domain];
132 
133  if (domain != Pstream::myProcNo() && recvElems.size())
134  {
135  UIPstream is(domain, pBufs);
136 
137  is >> faces[domain]
138  >> points[domain]
139  >> faceIDs[domain];
140  }
141  }
142 }
143 
144 
145 void Foam::advancingFrontAMI::distributeAndMergePatches
146 (
147  const mapDistribute& map,
148  const primitivePatch& tgtPatch,
149  const globalIndex& gi,
150  faceList& tgtFaces,
151  pointField& tgtPoints,
152  labelList& tgtFaceIDs
153 ) const
154 {
155  // Exchange per-processor data
156  List<faceList> allFaces;
157  List<pointField> allPoints;
158  List<labelList> allTgtFaceIDs;
159  distributePatches(map, tgtPatch, gi, allFaces, allPoints, allTgtFaceIDs);
160 
161  // Renumber and flatten
162  label nFaces = 0;
163  label nPoints = 0;
164  forAll(allFaces, proci)
165  {
166  nFaces += allFaces[proci].size();
167  nPoints += allPoints[proci].size();
168  }
169 
170  tgtFaces.setSize(nFaces);
171  tgtPoints.setSize(nPoints);
172  tgtFaceIDs.setSize(nFaces);
173 
174  nFaces = 0;
175  nPoints = 0;
176 
177  // My own data first
178  {
179  const labelList& faceIDs = allTgtFaceIDs[Pstream::myProcNo()];
180  SubList<label>(tgtFaceIDs, faceIDs.size()) = faceIDs;
181 
182  const faceList& fcs = allFaces[Pstream::myProcNo()];
183  for (const face& f : fcs)
184  {
185  face& newF = tgtFaces[nFaces++];
186  newF.setSize(f.size());
187  forAll(f, fp)
188  {
189  newF[fp] = f[fp] + nPoints;
190  }
191  }
192 
194  for (const point& pt: pts)
195  {
196  tgtPoints[nPoints++] = pt;
197  }
198  }
199 
200 
201  // Other proc data follows
202  forAll(allFaces, proci)
203  {
204  if (proci != Pstream::myProcNo())
205  {
206  const labelList& faceIDs = allTgtFaceIDs[proci];
207  SubList<label>(tgtFaceIDs, faceIDs.size(), nFaces) = faceIDs;
208 
209  const faceList& fcs = allFaces[proci];
210  for (const face& f : fcs)
211  {
212  face& newF = tgtFaces[nFaces++];
213  newF.setSize(f.size());
214  forAll(f, fp)
215  {
216  newF[fp] = f[fp] + nPoints;
217  }
218  }
219 
220  const pointField& pts = allPoints[proci];
221  for (const point& pt: pts)
222  {
223  tgtPoints[nPoints++] = pt;
224  }
225  }
226  }
227 
228  // Merge
229  labelList oldToNew;
230  bool nChanged = Foam::inplaceMergePoints
231  (
232  tgtPoints,
233  SMALL,
234  false,
235  oldToNew
236  );
237 
238  if (nChanged)
239  {
240  if (debug)
241  {
242  Pout<< "Merged from " << oldToNew.size()
243  << " down to " << tgtPoints.size() << " points" << endl;
244  }
245 
246  for (face& f : tgtFaces)
247  {
248  inplaceRenumber(oldToNew, f);
249  }
250  }
251 }
252 
253 
254 Foam::autoPtr<Foam::mapDistribute> Foam::advancingFrontAMI::calcProcMap
255 (
256  const primitivePatch& srcPatch,
257  const primitivePatch& tgtPatch
258 ) const
259 {
260  // Get decomposition of patch
261  List<treeBoundBoxList> procBb(Pstream::nProcs());
262 
263  if (srcPatch.size())
264  {
265  procBb[Pstream::myProcNo()] =
266  AABBTree<face>
267  (
268  srcPatch.localFaces(),
269  srcPatch.localPoints(),
270  false
271  ).boundBoxes();
272  }
273  else
274  {
275  procBb[Pstream::myProcNo()] = treeBoundBoxList();
276  }
277 
278  Pstream::allGatherList(procBb);
279 
280  if (debug)
281  {
282  Info<< "Determining extent of srcPatch per processor:" << nl
283  << "\tproc\tbb" << endl;
284  forAll(procBb, proci)
285  {
286  Info<< '\t' << proci << '\t' << procBb[proci] << endl;
287  }
288  }
289 
290  // Determine which faces of tgtPatch overlaps srcPatch per proc
291  const faceList& faces = tgtPatch.localFaces();
292  const pointField& points = tgtPatch.localPoints();
293 
294  labelListList sendMap;
295 
296  {
297  // Per processor indices into all segments to send
298  List<DynamicList<label>> dynSendMap(Pstream::nProcs());
299 
300  // Work array - whether processor bb overlaps the face bounds
301  boolList procBbOverlaps(Pstream::nProcs());
302 
303  forAll(faces, facei)
304  {
305  if (faces[facei].size())
306  {
307  treeBoundBox faceBb(points, faces[facei]);
308 
309  // Find the processor this face overlaps
310  calcOverlappingProcs(procBb, faceBb, procBbOverlaps);
311 
312  forAll(procBbOverlaps, proci)
313  {
314  if (procBbOverlaps[proci])
315  {
316  dynSendMap[proci].append(facei);
317  }
318  }
319  }
320  }
321 
322  // Convert dynamicList to labelList
323  sendMap.setSize(Pstream::nProcs());
324  forAll(sendMap, proci)
325  {
326  sendMap[proci].transfer(dynSendMap[proci]);
327  }
328  }
329 
330  // Debug printing
331  if (debug)
332  {
333  Pout<< "Of my " << faces.size() << " I need to send to:" << nl
334  << "\tproc\tfaces" << endl;
335  forAll(sendMap, proci)
336  {
337  Pout<< '\t' << proci << '\t' << sendMap[proci].size() << endl;
338  }
339  }
340 
341  return autoPtr<mapDistribute>::New(std::move(sendMap));
342 }
343 
344 
345 // ************************************************************************* //
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:1131
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
void resize_nocopy(const label len)
Adjust allocated size of list without necessarily.
Definition: ListI.H:139
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:1029
List< labelList > labelListList
List of labelList.
Definition: labelList.H:38
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:414
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:1020
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
void setSize(const label n)
Alias for resize()
Definition: List.H:289
const pointField & points
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:109
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