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-2020 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  PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
78 
79  for (const int domain : Pstream::allProcs())
80  {
81  const labelList& sendElems = map.subMap()[domain];
82 
83  if (domain != Pstream::myProcNo() && sendElems.size())
84  {
85  faceList subFaces(UIndirectList<face>(pp, sendElems));
86  primitivePatch subPatch
87  (
88  SubList<face>(subFaces, subFaces.size()),
89  pp.points()
90  );
91 
92  if (debug & 2)
93  {
94  Pout<< "distributePatches: to processor " << domain
95  << " sending faces " << subPatch.faceCentres() << endl;
96  }
97 
98  UOPstream toDomain(domain, pBufs);
99  toDomain
100  << subPatch.localFaces() << subPatch.localPoints()
101  << gi.toGlobal(sendElems);
102  }
103  }
104 
105  // Start receiving
106  pBufs.finishedSends();
107 
108  faces.setSize(Pstream::nProcs());
109  points.setSize(Pstream::nProcs());
110  faceIDs.setSize(Pstream::nProcs());
111 
112  {
113  // Set up 'send' to myself
114  const labelList& sendElems = map.subMap()[Pstream::myProcNo()];
115  faceList subFaces(UIndirectList<face>(pp, sendElems));
116  primitivePatch subPatch
117  (
118  SubList<face>(subFaces, subFaces.size()),
119  pp.points()
120  );
121 
122  // Receive
123  if (debug & 2)
124  {
125  Pout<< "distributePatches: to processor " << Pstream::myProcNo()
126  << " sending faces " << subPatch.faceCentres() << endl;
127  }
128 
129  faces[Pstream::myProcNo()] = subPatch.localFaces();
130  points[Pstream::myProcNo()] = subPatch.localPoints();
131  faceIDs[Pstream::myProcNo()] = gi.toGlobal(sendElems);
132  }
133 
134  // Consume
135  for (const int domain : Pstream::allProcs())
136  {
137  const labelList& recvElems = map.constructMap()[domain];
138 
139  if (domain != Pstream::myProcNo() && recvElems.size())
140  {
141  UIPstream str(domain, pBufs);
142 
143  str >> 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()];
186  SubList<label>(tgtFaceIDs, faceIDs.size()) = faceIDs;
187 
188  const faceList& fcs = allFaces[Pstream::myProcNo()];
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()];
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())
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  pointField newTgtPoints;
237  bool hasMerged = mergePoints
238  (
239  tgtPoints,
240  SMALL,
241  false,
242  oldToNew,
243  newTgtPoints
244  );
245 
246  if (hasMerged)
247  {
248  if (debug)
249  {
250  Pout<< "Merged from " << tgtPoints.size()
251  << " down to " << newTgtPoints.size() << " points" << endl;
252  }
253 
254  tgtPoints.transfer(newTgtPoints);
255  for (face& f : tgtFaces)
256  {
257  inplaceRenumber(oldToNew, f);
258  }
259  }
260 }
261 
262 
263 Foam::autoPtr<Foam::mapDistribute> Foam::advancingFrontAMI::calcProcMap
264 (
265  const primitivePatch& srcPatch,
266  const primitivePatch& tgtPatch
267 ) const
268 {
269  // Get decomposition of patch
270  List<treeBoundBoxList> procBb(Pstream::nProcs());
271 
272  if (srcPatch.size())
273  {
274  procBb[Pstream::myProcNo()] =
275  AABBTree<face>
276  (
277  srcPatch.localFaces(),
278  srcPatch.localPoints(),
279  false
280  ).boundBoxes();
281  }
282  else
283  {
284  procBb[Pstream::myProcNo()] = treeBoundBoxList();
285  }
286 
287  Pstream::gatherList(procBb);
288  Pstream::scatterList(procBb);
289 
290  if (debug)
291  {
292  Info<< "Determining extent of srcPatch per processor:" << nl
293  << "\tproc\tbb" << endl;
294  forAll(procBb, proci)
295  {
296  Info<< '\t' << proci << '\t' << procBb[proci] << endl;
297  }
298  }
299 
300  // Determine which faces of tgtPatch overlaps srcPatch per proc
301  const faceList& faces = tgtPatch.localFaces();
302  const pointField& points = tgtPatch.localPoints();
303 
304  labelListList sendMap;
305 
306  {
307  // Per processor indices into all segments to send
308  List<DynamicList<label>> dynSendMap(Pstream::nProcs());
309 
310  // Work array - whether processor bb overlaps the face bounds
311  boolList procBbOverlaps(Pstream::nProcs());
312 
313  forAll(faces, facei)
314  {
315  if (faces[facei].size())
316  {
317  treeBoundBox faceBb(points, faces[facei]);
318 
319  // Find the processor this face overlaps
320  calcOverlappingProcs(procBb, faceBb, procBbOverlaps);
321 
322  forAll(procBbOverlaps, proci)
323  {
324  if (procBbOverlaps[proci])
325  {
326  dynSendMap[proci].append(facei);
327  }
328  }
329  }
330  }
331 
332  // Convert dynamicList to labelList
333  sendMap.setSize(Pstream::nProcs());
334  forAll(sendMap, proci)
335  {
336  sendMap[proci].transfer(dynSendMap[proci]);
337  }
338  }
339 
340  // Debug printing
341  if (debug)
342  {
343  Pout<< "Of my " << faces.size() << " I need to send to:" << nl
344  << "\tproc\tfaces" << endl;
345  forAll(sendMap, proci)
346  {
347  Pout<< '\t' << proci << '\t' << sendMap[proci].size() << endl;
348  }
349  }
350 
351 
352  // Send over how many faces I need to receive
353  labelListList sendSizes(Pstream::nProcs());
354  sendSizes[Pstream::myProcNo()].setSize(Pstream::nProcs());
355  forAll(sendMap, proci)
356  {
357  sendSizes[Pstream::myProcNo()][proci] = sendMap[proci].size();
358  }
359  Pstream::gatherList(sendSizes);
360  Pstream::scatterList(sendSizes);
361 
362 
363  // Determine order of receiving
364  labelListList constructMap(Pstream::nProcs());
365 
366  // My local segment first
367  constructMap[Pstream::myProcNo()] = identity
368  (
369  sendMap[Pstream::myProcNo()].size()
370  );
371 
372  label segmentI = constructMap[Pstream::myProcNo()].size();
373  forAll(constructMap, proci)
374  {
375  if (proci != Pstream::myProcNo())
376  {
377  // What I need to receive is what other processor is sending to me
378  label nRecv = sendSizes[proci][Pstream::myProcNo()];
379  constructMap[proci].setSize(nRecv);
380 
381  for (label i = 0; i < nRecv; ++i)
382  {
383  constructMap[proci][i] = segmentI++;
384  }
385  }
386  }
387 
389  (
390  segmentI, // size after construction
391  std::move(sendMap),
392  std::move(constructMap)
393  );
394 }
395 
396 
397 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::autoPtr::New
static autoPtr< T > New(Args &&... args)
Construct autoPtr of T with forwarding arguments.
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:67
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
Foam::Pstream::scatterList
static void scatterList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Scatter data. Reverse of gatherList.
Definition: gatherScatterList.C:215
Foam::boolList
List< bool > boolList
A List of bools.
Definition: List.H:65
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::Pout
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
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:296
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
Foam::List::setSize
void setSize(const label n)
Alias for resize()
Definition: List.H:222
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::autoPtr< Foam::mapDistribute >
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
Foam::Pstream::gatherList
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
Definition: gatherScatterList.C:52
Foam::UPstream::allProcs
static rangeType allProcs(const label communicator=worldComm)
Range of process indices for all processes.
Definition: UPstream.H:508
Foam::UPstream::commsTypes::nonBlocking
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=worldComm)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:463
Foam::nl
constexpr char nl
Definition: Ostream.H:404
mapDistribute.H
f
labelList f(nPoints)
Foam::faceList
List< face > faceList
A List of faces.
Definition: faceListFwd.H:47
advancingFrontAMI.H
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
mergePoints.H
Merge points. See below.
Foam::primitivePatch
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
A PrimitivePatch with a SubList addressing for the faces, const reference for the point field.
Definition: primitivePatch.H:51
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::treeBoundBoxList
List< treeBoundBox > treeBoundBoxList
List of bounding boxes.
Definition: treeBoundBoxList.H:46
Foam::UPstream::nProcs
static label nProcs(const label communicator=worldComm)
Number of processes in parallel run, and 1 for serial run.
Definition: UPstream.H:445