processorLduInterfaceTemplates.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) 2019-2023 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 "processorLduInterface.H"
30 #include "IPstream.H"
31 #include "OPstream.H"
32 
33 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
34 
35 template<class Type>
37 (
38  const UPstream::commsTypes commsType,
39  const UList<Type>& f
40 ) const
41 {
42  const label nBytes = f.byteSize();
43 
44  if
45  (
47  || commsType == UPstream::commsTypes::scheduled
48  )
49  {
51  (
52  commsType,
53  neighbProcNo(),
54  f.cdata_bytes(),
55  nBytes,
56  tag(),
57  comm()
58  );
59  }
60  else if (commsType == UPstream::commsTypes::nonBlocking)
61  {
62  resizeBuf(byteSendBuf_, nBytes);
63  std::memcpy
64  (
65  static_cast<void*>(byteSendBuf_.data()), f.cdata(), nBytes
66  );
67 
68  resizeBuf(byteRecvBuf_, nBytes);
69 
70  if (!nBytes)
71  {
72  // Can skip empty messages
73  return;
74  }
75 
77  (
78  commsType,
79  neighbProcNo(),
80  byteRecvBuf_.data(),
81  nBytes,
82  tag(),
83  comm()
84  );
85 
87  (
88  commsType,
89  neighbProcNo(),
90  byteSendBuf_.cdata(),
91  nBytes,
92  tag(),
93  comm()
94  );
95  }
96  else
97  {
99  << "Unsupported communications type " << int(commsType)
101  }
102 }
103 
104 
105 template<class Type>
107 (
108  const UPstream::commsTypes commsType,
109  UList<Type>& f
110 ) const
111 {
112  const label nBytes = f.byteSize();
113 
114  if
115  (
116  commsType == UPstream::commsTypes::blocking
117  || commsType == UPstream::commsTypes::scheduled
118  )
119  {
121  (
122  commsType,
123  neighbProcNo(),
124  f.data_bytes(),
125  nBytes,
126  tag(),
127  comm()
128  );
129  }
130  else if (commsType == UPstream::commsTypes::nonBlocking)
131  {
132  std::memcpy
133  (
134  static_cast<void*>(f.data()), byteRecvBuf_.cdata(), nBytes
135  );
136  }
137  else
138  {
140  << "Unsupported communications type " << int(commsType)
142  }
143 }
144 
145 
146 template<class Type>
148 (
149  const UPstream::commsTypes commsType,
150  const label size
151 ) const
152 {
153  auto tfld = tmp<Field<Type>>::New(size);
154  receive(commsType, tfld.ref());
155  return tfld;
156 }
157 
158 
159 template<class Type>
161 (
162  const UPstream::commsTypes commsType,
163  const UList<Type>& f
164 ) const
165 {
166  if
167  (
168  f.size()
170  && (!std::is_integral<Type>::value && sizeof(scalar) != sizeof(float))
171  )
172  {
173  static const label nCmpts =
174  (
175  // Placeholder value for unusable template instantiation
176  std::is_integral<Type>::value
177  ? 1
178  : sizeof(Type)/sizeof(scalar)
179  );
180  const label nm1 = (f.size() - 1)*nCmpts;
181  const label nBytes = f.size()*nCmpts*sizeof(float);
182 
183  const scalar *sArray = reinterpret_cast<const scalar*>(f.cdata());
184  const scalar *slast = &sArray[nm1];
185  resizeBuf(byteSendBuf_, nBytes);
186  float *fArray = reinterpret_cast<float*>(byteSendBuf_.data());
187 
188  for (label i=0; i<nm1; i++)
189  {
190  fArray[i] = sArray[i] - slast[i%nCmpts];
191  }
192 
193  reinterpret_cast<Type&>(fArray[nm1]) = f.last();
194 
195  if
196  (
197  commsType == UPstream::commsTypes::blocking
198  || commsType == UPstream::commsTypes::scheduled
199  )
200  {
202  (
203  commsType,
204  neighbProcNo(),
205  byteSendBuf_.cdata(),
206  nBytes,
207  tag(),
208  comm()
209  );
210  }
211  else if (commsType == UPstream::commsTypes::nonBlocking)
212  {
213  resizeBuf(byteRecvBuf_, nBytes);
214 
216  (
217  commsType,
218  neighbProcNo(),
219  byteRecvBuf_.data(),
220  nBytes,
221  tag(),
222  comm()
223  );
224 
226  (
227  commsType,
228  neighbProcNo(),
229  byteSendBuf_.cdata(),
230  nBytes,
231  tag(),
232  comm()
233  );
234  }
235  else
236  {
238  << "Unsupported communications type " << int(commsType)
239  << exit(FatalError);
240  }
241  }
242  else
243  {
244  this->send(commsType, f);
245  }
246 }
247 
248 
249 template<class Type>
251 (
252  const UPstream::commsTypes commsType,
253  UList<Type>& f
254 ) const
255 {
256  if
257  (
258  f.size()
260  && (!std::is_integral<Type>::value && sizeof(scalar) != sizeof(float))
261  )
262  {
263  static const label nCmpts =
264  (
265  // Placeholder value for unusable template instantiation
266  std::is_integral<Type>::value
267  ? 1
268  : sizeof(Type)/sizeof(scalar)
269  );
270  const label nm1 = (f.size() - 1)*nCmpts;
271  const label nBytes = f.size()*nCmpts*sizeof(float);
272 
273  if
274  (
275  commsType == UPstream::commsTypes::blocking
276  || commsType == UPstream::commsTypes::scheduled
277  )
278  {
279  resizeBuf(byteRecvBuf_, nBytes);
280 
282  (
283  commsType,
284  neighbProcNo(),
285  byteRecvBuf_.data(),
286  nBytes,
287  tag(),
288  comm()
289  );
290  }
291  else if (commsType != UPstream::commsTypes::nonBlocking)
292  {
294  << "Unsupported communications type " << int(commsType)
295  << exit(FatalError);
296  }
297 
298  const float *fArray =
299  reinterpret_cast<const float*>(byteRecvBuf_.cdata());
300  f.last() = reinterpret_cast<const Type&>(fArray[nm1]);
301  scalar *sArray = reinterpret_cast<scalar*>(f.data());
302  const scalar *slast = &sArray[nm1];
303 
304  for (label i=0; i<nm1; i++)
305  {
306  sArray[i] = fArray[i] + slast[i%nCmpts];
307  }
308  }
309  else
310  {
311  this->receive<Type>(commsType, f);
312  }
313 }
314 
315 
316 template<class Type>
318 (
319  const UPstream::commsTypes commsType,
320  const label size
321 ) const
322 {
323  auto tfld = tmp<Field<Type>>::New(size);
324  compressedReceive(commsType, tfld.ref());
325  return tfld;
326 }
327 
328 
329 // ************************************************************************* //
static bool floatTransfer
Should compact transfer be used in which floats replace doubles reducing the bandwidth requirement at...
Definition: UPstream.H:364
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
"blocking" : (MPI_Bsend, MPI_Recv)
void send(const UPstream::commsTypes commsType, const UList< Type > &f) const
Raw send function.
static label read(const UPstream::commsTypes commsType, const int fromProcNo, char *buf, const std::streamsize bufSize, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm, UPstream::Request *req=nullptr)
Read buffer contents from given processor.
Definition: UIPstreamRead.C:35
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
commsTypes
Communications types.
Definition: UPstream.H:72
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
T * data() noexcept
Return pointer to the underlying array serving as data storage.
Definition: UListI.H:272
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
char * data_bytes() noexcept
Return pointer to the underlying array serving as data storage,.
Definition: UListI.H:286
"scheduled" : (MPI_Send, MPI_Recv)
virtual label comm() const =0
Return communicator used for parallel communication.
virtual int tag() const =0
Return message tag used for sending.
labelList f(nPoints)
T & last()
Access last element of the list, position [size()-1].
Definition: UList.H:867
void compressedReceive(const UPstream::commsTypes commsType, UList< Type > &f) const
Raw receive function with data compression.
std::streamsize byteSize() const
Number of contiguous bytes for the List data, runtime FatalError if type is not contiguous.
Definition: UList.C:160
virtual int neighbProcNo() const =0
Return neighbour processor number (rank in communicator)
static bool write(const UPstream::commsTypes commsType, const int toProcNo, const char *buf, const std::streamsize bufSize, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm, UPstream::Request *req=nullptr, const UPstream::sendModes sendMode=UPstream::sendModes::normal)
Write buffer contents to given processor.
"nonBlocking" : (MPI_Isend, MPI_Irecv)
const T * cdata() const noexcept
Return pointer to the underlying array serving as data storage.
Definition: UListI.H:265
A class for managing temporary objects.
Definition: HashPtrTable.H:50
void compressedSend(const UPstream::commsTypes commsType, const UList< Type > &f) const
Raw send function with data compression.
void receive(const UPstream::commsTypes commsType, UList< Type > &f) const
Raw receive function.