globalIndexTemplates.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) 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 "globalIndex.H"
27 
28 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
29 
30 template<class Type>
32 (
33  const labelUList& off,
34  const label comm,
35  const labelList& procIDs,
36  const UList<Type>& fld,
37  List<Type>& allFld,
38  const int tag,
39  const Pstream::commsTypes commsType
40 )
41 {
42  if (Pstream::myProcNo(comm) == procIDs[0])
43  {
44  allFld.setSize(off.last());
45 
46  // Assign my local data
47  SubList<Type>(allFld, fld.size(), 0).assign(fld);
48 
49  if (commsType == Pstream::scheduled || commsType == Pstream::blocking)
50  {
51  for (label i = 1; i < procIDs.size(); i++)
52  {
53  SubList<Type> procSlot(allFld, off[i+1]-off[i], off[i]);
54 
55  if (contiguous<Type>())
56  {
58  (
59  commsType,
60  procIDs[i],
61  reinterpret_cast<char*>(procSlot.begin()),
62  procSlot.byteSize(),
63  tag,
64  comm
65  );
66  }
67  else
68  {
69  IPstream fromSlave
70  (
71  commsType,
72  procIDs[i],
73  0,
74  tag,
75  comm
76  );
77  fromSlave >> procSlot;
78  }
79  }
80  }
81  else
82  {
83  // nonBlocking
84 
85  if (!contiguous<Type>())
86  {
87  FatalErrorIn("globalIndex::gather(..)")
88  << "nonBlocking not supported for non-contiguous data"
89  << exit(FatalError);
90  }
91 
92  label startOfRequests = Pstream::nRequests();
93 
94  // Set up reads
95  for (label i = 1; i < procIDs.size(); i++)
96  {
97  SubList<Type> procSlot(allFld, off[i+1]-off[i], off[i]);
98 
100  (
101  commsType,
102  procIDs[i],
103  reinterpret_cast<char*>(procSlot.begin()),
104  procSlot.byteSize(),
105  tag,
106  comm
107  );
108  }
109 
110  // Wait for all to finish
111  Pstream::waitRequests(startOfRequests);
112  }
113  }
114  else
115  {
116  if (commsType == Pstream::scheduled || commsType == Pstream::blocking)
117  {
118  if (contiguous<Type>())
119  {
121  (
122  commsType,
123  procIDs[0],
124  reinterpret_cast<const char*>(fld.begin()),
125  fld.byteSize(),
126  tag,
127  comm
128  );
129  }
130  else
131  {
132  OPstream toMaster
133  (
134  commsType,
135  procIDs[0],
136  0,
137  tag,
138  comm
139  );
140  toMaster << fld;
141  }
142  }
143  else
144  {
145  // nonBlocking
146 
147  if (!contiguous<Type>())
148  {
149  FatalErrorIn("globalIndex::gather(..)")
150  << "nonBlocking not supported for non-contiguous data"
151  << exit(FatalError);
152  }
153 
154  label startOfRequests = Pstream::nRequests();
155 
156  // Set up write
158  (
159  commsType,
160  procIDs[0],
161  reinterpret_cast<const char*>(fld.begin()),
162  fld.byteSize(),
163  tag,
164  comm
165  );
166 
167  // Wait for all to finish
168  Pstream::waitRequests(startOfRequests);
169  }
170  }
171 }
172 
173 
174 template<class Type>
176 (
177  const labelUList& off,
178  const label comm,
179  const labelList& procIDs,
180  List<Type>& fld,
181  const int tag,
182  const Pstream::commsTypes commsType
183 )
184 {
185  List<Type> allFld;
186 
187  gather(off, comm, procIDs, fld, allFld, tag, commsType);
188 
189  if (Pstream::myProcNo(comm) == procIDs[0])
190  {
191  fld.transfer(allFld);
192  }
193 }
194 
195 
196 template<class Type>
198 (
199  const labelUList& off,
200  const label comm,
201  const labelList& procIDs,
202  const UList<Type>& allFld,
203  UList<Type>& fld,
204  const int tag,
205  const Pstream::commsTypes commsType
206 )
207 {
208  if (Pstream::myProcNo(comm) == procIDs[0])
209  {
210  fld.assign(SubList<Type>(allFld, off[1]-off[0]));
211 
212  if (commsType == Pstream::scheduled || commsType == Pstream::blocking)
213  {
214  for (label i = 1; i < procIDs.size(); i++)
215  {
216  const SubList<Type> procSlot
217  (
218  allFld,
219  off[i+1]-off[i],
220  off[i]
221  );
222 
223  if (contiguous<Type>())
224  {
226  (
227  commsType,
228  procIDs[i],
229  reinterpret_cast<const char*>(procSlot.begin()),
230  procSlot.byteSize(),
231  tag,
232  comm
233  );
234  }
235  else
236  {
237  OPstream toSlave
238  (
239  commsType,
240  procIDs[i],
241  0,
242  tag,
243  comm
244  );
245  toSlave << procSlot;
246  }
247  }
248  }
249  else
250  {
251  // nonBlocking
252 
253  if (!contiguous<Type>())
254  {
255  FatalErrorIn("globalIndex::scatter(..)")
256  << "nonBlocking not supported for non-contiguous data"
257  << exit(FatalError);
258  }
259 
260  label startOfRequests = Pstream::nRequests();
261 
262  // Set up writes
263  for (label i = 1; i < procIDs.size(); i++)
264  {
265  const SubList<Type> procSlot
266  (
267  allFld,
268  off[i+1]-off[i],
269  off[i]
270  );
271 
273  (
274  commsType,
275  procIDs[i],
276  reinterpret_cast<const char*>(procSlot.begin()),
277  procSlot.byteSize(),
278  tag,
279  comm
280  );
281  }
282 
283  // Wait for all to finish
284  Pstream::waitRequests(startOfRequests);
285  }
286  }
287  else
288  {
289  if (commsType == Pstream::scheduled || commsType == Pstream::blocking)
290  {
291  if (contiguous<Type>())
292  {
294  (
295  commsType,
296  procIDs[0],
297  reinterpret_cast<char*>(fld.begin()),
298  fld.byteSize(),
299  tag,
300  comm
301  );
302  }
303  else
304  {
305  IPstream fromMaster
306  (
307  commsType,
308  procIDs[0],
309  0,
310  tag,
311  comm
312  );
313  fromMaster >> fld;
314  }
315  }
316  else
317  {
318  // nonBlocking
319 
320  if (!contiguous<Type>())
321  {
322  FatalErrorIn("globalIndex::scatter(..)")
323  << "nonBlocking not supported for non-contiguous data"
324  << exit(FatalError);
325  }
326 
327  label startOfRequests = Pstream::nRequests();
328 
329  // Set up read
331  (
332  commsType,
333  procIDs[0],
334  reinterpret_cast<char*>(fld.begin()),
335  fld.byteSize(),
336  tag,
337  comm
338  );
339 
340  // Wait for all to finish
341  Pstream::waitRequests(startOfRequests);
342  }
343  }
344 }
345 
346 
347 // ************************************************************************* //
std::streamsize byteSize() const
Return the binary size in number of characters of the UList.
Definition: UList.C:92
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Definition: List.C:390
void assign(const UList< T > &)
Assign elements to those from UList.
Definition: UList.C:37
T & last()
Return the last element of the list.
Definition: UListI.H:131
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
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:76
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
Output inter-processor communications stream.
Definition: OPstream.H:50
runTime write()
iterator begin()
Return an iterator to begin traversing the UList.
Definition: UListI.H:216
void setSize(const label)
Reset size of List.
Definition: List.C:318
commsTypes
Types of communications.
Definition: UPstream.H:64
label size() const
Return the number of elements in the UList.
Definition: UListI.H:299
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){gmvFile<< iter().position().x()<< ' ';}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){gmvFile<< iter().position().y()<< ' ';}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){gmvFile<< iter().position().z()<< ' ';}gmvFile<< nl;forAll(lagrangianScalarNames, i){const word &name=lagrangianScalarNames[i];IOField< scalar > fld(IOobject( name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE ))
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition: error.H:314
error FatalError
Input inter-processor communications stream.
Definition: IPstream.H:50
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:60
bool read(const char *, int32_t &)
Definition: int32IO.C:87
static void gather(const labelUList &offsets, const label comm, const labelList &procIDs, const UList< Type > &fld, List< Type > &allFld, const int tag=UPstream::msgType(), const Pstream::commsTypes commsType=Pstream::nonBlocking)
Collect data in processor order on master (== procIDs[0]).
static void scatter(const labelUList &offsets, const label comm, const labelList &procIDs, const UList< Type > &allFld, UList< Type > &fld, const int tag=UPstream::msgType(), const Pstream::commsTypes commsType=Pstream::nonBlocking)
Distribute data in processor order. Requires fld to be sized!