FreeFOAM The Cross-Platform CFD Toolkit
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) 1991-2010 OpenCFD Ltd.
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 <OpenFOAM/ListOps.H>
28 #include <OpenFOAM/Pstream.H>
29 #include "commSchedule.H"
30 
31 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
32 
33 template<class Patch, class ProcPatch>
35 (
36  const PtrList<Patch>& patches
37 )
38 {
39  // Determine number of processor neighbours and max neighbour id.
40 
41  label nNeighbours = 0;
42 
43  label maxNb = 0;
44 
45  forAll(patches, patchi)
46  {
47  const Patch& patch = patches[patchi];
48 
49  if (isA<ProcPatch>(patch))
50  {
51  const ProcPatch& procPatch =
52  refCast<const ProcPatch>(patch);
53 
54  nNeighbours++;
55 
56  maxNb = max(maxNb, procPatch.neighbProcNo());
57  }
58  }
59 
60  labelList neighbours(nNeighbours);
61 
62  procPatchMap_.setSize(maxNb + 1);
63  procPatchMap_ = -1;
64 
65  nNeighbours = 0;
66 
67  forAll(patches, patchi)
68  {
69  const Patch& patch = patches[patchi];
70 
71  if (isA<ProcPatch>(patch))
72  {
73  const ProcPatch& procPatch =
74  refCast<const ProcPatch>(patch);
75 
76  neighbours[nNeighbours++] = procPatch.neighbProcNo();
77 
78  // Construct reverse map
79  procPatchMap_[procPatch.neighbProcNo()] = patchi;
80  }
81  }
82 
83  return neighbours;
84 }
85 
86 
87 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
88 
89 // Construct from components
90 template<class Patch, class ProcPatch>
92 (
93  const PtrList<Patch>& patches
94 )
95 :
96  labelListList(Pstream::nProcs()),
97  patchSchedule_(2*patches.size())
98 {
99  if (Pstream::parRun())
100  {
101  // Fill my 'slot' with my neighbours
102  operator[](Pstream::myProcNo()) = procNeighbours(patches);
103 
104  // Distribute to all processors
105  Pstream::gatherList(*this);
106  Pstream::scatterList(*this);
107  }
108 
109  if (Pstream::parRun() && Pstream::defaultCommsType == Pstream::scheduled)
110  {
111  label patchEvali = 0;
112 
113  // 1. All non-processor patches
114  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
115 
116  forAll(patches, patchi)
117  {
118  if (!isA<ProcPatch>(patches[patchi]))
119  {
120  patchSchedule_[patchEvali].patch = patchi;
121  patchSchedule_[patchEvali++].init = true;
122  patchSchedule_[patchEvali].patch = patchi;
123  patchSchedule_[patchEvali++].init = false;
124  }
125  }
126 
127  // 2. All processor patches
128  // ~~~~~~~~~~~~~~~~~~~~~~~~
129 
130  // Determine the schedule for all. Insert processor pair once
131  // to determine the schedule. Each processor pair stands for both
132  // send and receive.
133  label nComms = 0;
134  forAll(*this, procI)
135  {
136  nComms += operator[](procI).size();
137  }
138  DynamicList<labelPair> comms(nComms);
139 
140  forAll(*this, procI)
141  {
142  const labelList& nbrs = operator[](procI);
143 
144  forAll(nbrs, i)
145  {
146  if (procI < nbrs[i])
147  {
148  comms.append(labelPair(procI, nbrs[i]));
149  }
150  }
151  }
152  comms.shrink();
153 
154  // Determine a schedule.
155  labelList mySchedule
156  (
158  (
159  Pstream::nProcs(),
160  comms
161  ).procSchedule()[Pstream::myProcNo()]
162  );
163 
164  forAll(mySchedule, iter)
165  {
166  label commI = mySchedule[iter];
167 
168  // Get the other processor
169  label nb = comms[commI][0];
170  if (nb == Pstream::myProcNo())
171  {
172  nb = comms[commI][1];
173  }
174  label patchi = procPatchMap_[nb];
175 
176  if (Pstream::myProcNo() > nb)
177  {
178  patchSchedule_[patchEvali].patch = patchi;
179  patchSchedule_[patchEvali++].init = true;
180  patchSchedule_[patchEvali].patch = patchi;
181  patchSchedule_[patchEvali++].init = false;
182  }
183  else
184  {
185  patchSchedule_[patchEvali].patch = patchi;
186  patchSchedule_[patchEvali++].init = false;
187  patchSchedule_[patchEvali].patch = patchi;
188  patchSchedule_[patchEvali++].init = true;
189  }
190  }
191  }
192  else
193  {
194  label patchEvali = 0;
195 
196  // 1. All non-processor patches
197  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
198 
199  // Have evaluate directly after initEvaluate. Could have them separated
200  // as long as they're not intermingled with processor patches since
201  // then e.g. any reduce parallel traffic would interfere with the
202  // processor swaps.
203 
204  forAll(patches, patchi)
205  {
206  if (!isA<ProcPatch>(patches[patchi]))
207  {
208  patchSchedule_[patchEvali].patch = patchi;
209  patchSchedule_[patchEvali++].init = true;
210  patchSchedule_[patchEvali].patch = patchi;
211  patchSchedule_[patchEvali++].init = false;
212  }
213  }
214 
215  // 2. All processor patches
216  // ~~~~~~~~~~~~~~~~~~~~~~~~
217 
218  // 2a. initEvaluate
219  forAll(patches, patchi)
220  {
221  if (isA<ProcPatch>(patches[patchi]))
222  {
223  patchSchedule_[patchEvali].patch = patchi;
224  patchSchedule_[patchEvali++].init = true;
225  }
226  }
227 
228  // 2b. evaluate
229  forAll(patches, patchi)
230  {
231  if (isA<ProcPatch>(patches[patchi]))
232  {
233  patchSchedule_[patchEvali].patch = patchi;
234  patchSchedule_[patchEvali++].init = false;
235  }
236  }
237  }
238 }
239 
240 
241 // ************************ vim: set sw=4 sts=4 et: ************************ //