ProcessorTopology.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-2013 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 "ProcessorTopology.H"
27 #include "ListOps.H"
28 #include "Pstream.H"
29 #include "commSchedule.H"
30 #include "boolList.H"
31 
32 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
33 
34 template<class Container, class ProcPatch>
36 (
37  const label nProcs,
38  const Container& patches
39 )
40 {
41  // Determine number of processor neighbours and max neighbour id.
42 
43  label nNeighbours = 0;
44 
45  label maxNb = 0;
46 
47  boolList isNeighbourProc(nProcs, false);
48 
50  {
51  const typename Container::const_reference patch = patches[patchi];
52 
53  if (isA<ProcPatch>(patch))
54  {
55  const ProcPatch& procPatch =
56  refCast<const ProcPatch>(patch);
57 
58  label pNeighbProcNo = procPatch.neighbProcNo();
59 
60  if (!isNeighbourProc[pNeighbProcNo])
61  {
62  nNeighbours++;
63 
64  maxNb = max(maxNb, procPatch.neighbProcNo());
65 
66  isNeighbourProc[pNeighbProcNo] = true;
67  }
68  }
69  }
70 
71  labelList neighbours(nNeighbours, -1);
72 
73  nNeighbours = 0;
74 
75  forAll(isNeighbourProc, procI)
76  {
77  if (isNeighbourProc[procI])
78  {
79  neighbours[nNeighbours++] = procI;
80  }
81  }
82 
83  procPatchMap_.setSize(maxNb + 1);
84  procPatchMap_ = -1;
85 
87  {
88  const typename Container::const_reference patch = patches[patchi];
89 
90  if (isA<ProcPatch>(patch))
91  {
92  const ProcPatch& procPatch =
93  refCast<const ProcPatch>(patch);
94 
95  // Construct reverse map
96  procPatchMap_[procPatch.neighbProcNo()] = patchi;
97  }
98  }
99 
100  return neighbours;
101 }
102 
103 
104 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
105 
106 // Construct from components
107 template<class Container, class ProcPatch>
109 (
110  const Container& patches,
111  const label comm
112 )
113 :
114  labelListList(Pstream::nProcs(comm)),
115  patchSchedule_(2*patches.size())
116 {
117  if (Pstream::parRun())
118  {
119  // Fill my 'slot' with my neighbours
120  operator[](Pstream::myProcNo(comm)) =
121  procNeighbours(this->size(), patches);
122 
123  // Distribute to all processors
124  Pstream::gatherList(*this, Pstream::msgType(), comm);
125  Pstream::scatterList(*this, Pstream::msgType(), comm);
126  }
127 
128  if (Pstream::parRun() && Pstream::defaultCommsType == Pstream::scheduled)
129  {
130  label patchEvali = 0;
131 
132  // 1. All non-processor patches
133  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
134 
136  {
137  if (!isA<ProcPatch>(patches[patchi]))
138  {
139  patchSchedule_[patchEvali].patch = patchi;
140  patchSchedule_[patchEvali++].init = true;
141  patchSchedule_[patchEvali].patch = patchi;
142  patchSchedule_[patchEvali++].init = false;
143  }
144  }
145 
146  // 2. All processor patches
147  // ~~~~~~~~~~~~~~~~~~~~~~~~
148 
149  // Determine the schedule for all. Insert processor pair once
150  // to determine the schedule. Each processor pair stands for both
151  // send and receive.
152  label nComms = 0;
153  forAll(*this, procI)
154  {
155  nComms += operator[](procI).size();
156  }
157  DynamicList<labelPair> comms(nComms);
158 
159  forAll(*this, procI)
160  {
161  const labelList& nbrs = operator[](procI);
162 
163  forAll(nbrs, i)
164  {
165  if (procI < nbrs[i])
166  {
167  comms.append(labelPair(procI, nbrs[i]));
168  }
169  }
170  }
171  comms.shrink();
172 
173  // Determine a schedule.
174  labelList mySchedule
175  (
177  (
178  Pstream::nProcs(comm),
179  comms
180  ).procSchedule()[Pstream::myProcNo(comm)]
181  );
182 
183  forAll(mySchedule, iter)
184  {
185  label commI = mySchedule[iter];
186 
187  // Get the other processor
188  label nb = comms[commI][0];
189  if (nb == Pstream::myProcNo(comm))
190  {
191  nb = comms[commI][1];
192  }
193  label patchi = procPatchMap_[nb];
194 
195  if (Pstream::myProcNo(comm) > nb)
196  {
197  patchSchedule_[patchEvali].patch = patchi;
198  patchSchedule_[patchEvali++].init = true;
199  patchSchedule_[patchEvali].patch = patchi;
200  patchSchedule_[patchEvali++].init = false;
201  }
202  else
203  {
204  patchSchedule_[patchEvali].patch = patchi;
205  patchSchedule_[patchEvali++].init = false;
206  patchSchedule_[patchEvali].patch = patchi;
207  patchSchedule_[patchEvali++].init = true;
208  }
209  }
210  }
211  else
212  {
213  patchSchedule_ = nonBlockingSchedule(patches);
214  }
215 }
216 
217 
218 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
219 
220 template<class Container, class ProcPatch>
223 (
224  const Container& patches
225 )
226 {
227  lduSchedule patchSchedule(2*patches.size());
228 
229  label patchEvali = 0;
230 
231  // 1. All non-processor patches
232  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
233 
234  // Have evaluate directly after initEvaluate. Could have them separated
235  // as long as they're not intermingled with processor patches since
236  // then e.g. any reduce parallel traffic would interfere with the
237  // processor swaps.
238 
240  {
241  if (!isA<ProcPatch>(patches[patchi]))
242  {
243  patchSchedule[patchEvali].patch = patchi;
244  patchSchedule[patchEvali++].init = true;
245  patchSchedule[patchEvali].patch = patchi;
246  patchSchedule[patchEvali++].init = false;
247  }
248  }
249 
250  // 2. All processor patches
251  // ~~~~~~~~~~~~~~~~~~~~~~~~
252 
253  // 2a. initEvaluate
255  {
256  if (isA<ProcPatch>(patches[patchi]))
257  {
258  patchSchedule[patchEvali].patch = patchi;
259  patchSchedule[patchEvali++].init = true;
260  }
261  }
262 
263  // 2b. evaluate
265  {
266  if (isA<ProcPatch>(patches[patchi]))
267  {
268  patchSchedule[patchEvali].patch = patchi;
269  patchSchedule[patchEvali++].init = false;
270  }
271  }
272 
273  return patchSchedule;
274 }
275 
276 
277 // ************************************************************************* //
Foam::ProcessorTopology::procNeighbours
labelList procNeighbours(const label nProcs, const Container &)
Return all neighbouring processors of this processor. Set.
Definition: ProcessorTopology.C:36
boolList.H
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::DynamicList
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:56
Foam::ProcessorTopology::nonBlockingSchedule
static lduSchedule nonBlockingSchedule(const Container &patches)
Calculate non-blocking (i.e. unscheduled) schedule.
Definition: ProcessorTopology.C:223
Foam::commSchedule
Determines the order in which a set of processors should communicate with one another.
Definition: commSchedule.H:65
Foam::ProcessorTopology::ProcessorTopology
ProcessorTopology(const Container &patches, const label comm)
Construct from boundaryMesh.
Definition: ProcessorTopology.C:109
commSchedule.H
ProcessorTopology.H
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::DynamicList::shrink
DynamicList< T, SizeInc, SizeMult, SizeDiv > & shrink()
Shrink the allocated space to the number of elements used.
Definition: DynamicListI.H:258
procNeighbours
labelList procNeighbours(const polyMesh &mesh)
Definition: Test-processorRouter.C:49
Pstream.H
Foam::DynamicList::append
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Foam::max
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
Foam::List::setSize
void setSize(const label)
Reset size of List.
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:57
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
patchi
label patchi
Definition: getPatchFieldScalar.H:1
patches
patches[0]
Definition: createSingleCellMesh.H:36
ListOps.H
Various functions to operate on Lists.
Foam::labelPair
Pair< label > labelPair
Label pair.
Definition: labelPair.H:48