processorFvPatchField.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-2016 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 "processorFvPatchField.H"
27 #include "processorFvPatch.H"
28 #include "demandDrivenData.H"
29 #include "transformField.H"
30 
31 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
32 
33 template<class Type>
35 (
36  const fvPatch& p,
38 )
39 :
41  procPatch_(refCast<const processorFvPatch>(p)),
42  sendBuf_(0),
43  receiveBuf_(0),
44  outstandingSendRequest_(-1),
45  outstandingRecvRequest_(-1),
46  scalarSendBuf_(0),
47  scalarReceiveBuf_(0)
48 {}
49 
50 
51 template<class Type>
53 (
54  const fvPatch& p,
56  const Field<Type>& f
57 )
58 :
60  procPatch_(refCast<const processorFvPatch>(p)),
61  sendBuf_(0),
62  receiveBuf_(0),
63  outstandingSendRequest_(-1),
64  outstandingRecvRequest_(-1),
65  scalarSendBuf_(0),
66  scalarReceiveBuf_(0)
67 {}
68 
69 
70 template<class Type>
72 (
73  const processorFvPatchField<Type>& ptf,
74  const fvPatch& p,
76  const fvPatchFieldMapper& mapper
77 )
78 :
79  coupledFvPatchField<Type>(ptf, p, iF, mapper),
80  procPatch_(refCast<const processorFvPatch>(p)),
81  sendBuf_(0),
82  receiveBuf_(0),
83  outstandingSendRequest_(-1),
84  outstandingRecvRequest_(-1),
85  scalarSendBuf_(0),
86  scalarReceiveBuf_(0)
87 {
88  if (!isA<processorFvPatch>(this->patch()))
89  {
91  << "' not constraint type '" << typeName << "'"
92  << "\n for patch " << p.name()
93  << " of field " << this->internalField().name()
94  << " in file " << this->internalField().objectPath()
95  << exit(FatalIOError);
96  }
97  if (debug && !ptf.ready())
98  {
100  << "On patch " << procPatch_.name() << " outstanding request."
101  << abort(FatalError);
102  }
103 }
104 
105 
106 template<class Type>
108 (
109  const fvPatch& p,
111  const dictionary& dict
112 )
113 :
115  procPatch_(refCast<const processorFvPatch>(p)),
116  sendBuf_(0),
117  receiveBuf_(0),
118  outstandingSendRequest_(-1),
119  outstandingRecvRequest_(-1),
120  scalarSendBuf_(0),
121  scalarReceiveBuf_(0)
122 {
123  if (!isA<processorFvPatch>(p))
124  {
126  (
127  dict
128  ) << "\n patch type '" << p.type()
129  << "' not constraint type '" << typeName << "'"
130  << "\n for patch " << p.name()
131  << " of field " << this->internalField().name()
132  << " in file " << this->internalField().objectPath()
133  << exit(FatalIOError);
134  }
135 }
136 
137 
138 template<class Type>
140 (
141  const processorFvPatchField<Type>& ptf
142 )
143 :
146  procPatch_(refCast<const processorFvPatch>(ptf.patch())),
147  sendBuf_(ptf.sendBuf_.xfer()),
148  receiveBuf_(ptf.receiveBuf_.xfer()),
149  outstandingSendRequest_(-1),
150  outstandingRecvRequest_(-1),
151  scalarSendBuf_(ptf.scalarSendBuf_.xfer()),
152  scalarReceiveBuf_(ptf.scalarReceiveBuf_.xfer())
153 {
154  if (debug && !ptf.ready())
155  {
157  << "On patch " << procPatch_.name() << " outstanding request."
158  << abort(FatalError);
159  }
160 }
161 
162 
163 template<class Type>
165 (
166  const processorFvPatchField<Type>& ptf,
168 )
169 :
170  coupledFvPatchField<Type>(ptf, iF),
171  procPatch_(refCast<const processorFvPatch>(ptf.patch())),
172  sendBuf_(0),
173  receiveBuf_(0),
174  outstandingSendRequest_(-1),
175  outstandingRecvRequest_(-1),
176  scalarSendBuf_(0),
177  scalarReceiveBuf_(0)
178 {
179  if (debug && !ptf.ready())
180  {
182  << "On patch " << procPatch_.name() << " outstanding request."
183  << abort(FatalError);
184  }
185 }
186 
187 
188 // * * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * //
189 
190 template<class Type>
192 {}
193 
194 
195 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
196 
197 template<class Type>
200 {
201  if (debug && !this->ready())
202  {
204  << "On patch " << procPatch_.name()
205  << " outstanding request."
206  << abort(FatalError);
207  }
208  return *this;
209 }
210 
211 
212 template<class Type>
214 (
215  const Pstream::commsTypes commsType
216 )
217 {
218  if (Pstream::parRun())
219  {
220  this->patchInternalField(sendBuf_);
221 
222  if (commsType == Pstream::nonBlocking && !Pstream::floatTransfer)
223  {
224  // Fast path. Receive into *this
225  this->setSize(sendBuf_.size());
226  outstandingRecvRequest_ = UPstream::nRequests();
228  (
229  Pstream::nonBlocking,
230  procPatch_.neighbProcNo(),
231  reinterpret_cast<char*>(this->begin()),
232  this->byteSize(),
233  procPatch_.tag(),
234  procPatch_.comm()
235  );
236 
237  outstandingSendRequest_ = UPstream::nRequests();
239  (
240  Pstream::nonBlocking,
241  procPatch_.neighbProcNo(),
242  reinterpret_cast<const char*>(sendBuf_.begin()),
243  this->byteSize(),
244  procPatch_.tag(),
245  procPatch_.comm()
246  );
247  }
248  else
249  {
250  procPatch_.compressedSend(commsType, sendBuf_);
251  }
252  }
253 }
254 
255 
256 template<class Type>
258 (
259  const Pstream::commsTypes commsType
260 )
261 {
262  if (Pstream::parRun())
263  {
264  if (commsType == Pstream::nonBlocking && !Pstream::floatTransfer)
265  {
266  // Fast path. Received into *this
267 
268  if
269  (
270  outstandingRecvRequest_ >= 0
271  && outstandingRecvRequest_ < Pstream::nRequests()
272  )
273  {
274  UPstream::waitRequest(outstandingRecvRequest_);
275  }
276  outstandingSendRequest_ = -1;
277  outstandingRecvRequest_ = -1;
278  }
279  else
280  {
281  procPatch_.compressedReceive<Type>(commsType, *this);
282  }
283 
284  if (doTransform())
285  {
286  transform(*this, procPatch_.forwardT(), *this);
287  }
288  }
289 }
290 
291 
292 template<class Type>
295 (
296  const scalarField& deltaCoeffs
297 ) const
298 {
299  return deltaCoeffs*(*this - this->patchInternalField());
300 }
301 
302 
303 template<class Type>
305 (
306  scalarField&,
307  const scalarField& psiInternal,
308  const scalarField&,
309  const direction,
310  const Pstream::commsTypes commsType
311 ) const
312 {
313  this->patch().patchInternalField(psiInternal, scalarSendBuf_);
314 
315  if (commsType == Pstream::nonBlocking && !Pstream::floatTransfer)
316  {
317  // Fast path.
318  if (debug && !this->ready())
319  {
321  << "On patch " << procPatch_.name()
322  << " outstanding request."
323  << abort(FatalError);
324  }
325 
326 
327  scalarReceiveBuf_.setSize(scalarSendBuf_.size());
328  outstandingRecvRequest_ = UPstream::nRequests();
330  (
331  Pstream::nonBlocking,
332  procPatch_.neighbProcNo(),
333  reinterpret_cast<char*>(scalarReceiveBuf_.begin()),
334  scalarReceiveBuf_.byteSize(),
335  procPatch_.tag(),
336  procPatch_.comm()
337  );
338 
339  outstandingSendRequest_ = UPstream::nRequests();
341  (
342  Pstream::nonBlocking,
343  procPatch_.neighbProcNo(),
344  reinterpret_cast<const char*>(scalarSendBuf_.begin()),
345  scalarSendBuf_.byteSize(),
346  procPatch_.tag(),
347  procPatch_.comm()
348  );
349  }
350  else
351  {
352  procPatch_.compressedSend(commsType, scalarSendBuf_);
353  }
354 
355  const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = false;
356 }
357 
358 
359 template<class Type>
361 (
362  scalarField& result,
363  const scalarField&,
364  const scalarField& coeffs,
365  const direction cmpt,
366  const Pstream::commsTypes commsType
367 ) const
368 {
369  if (this->updatedMatrix())
370  {
371  return;
372  }
373 
374  const labelUList& faceCells = this->patch().faceCells();
375 
376  if (commsType == Pstream::nonBlocking && !Pstream::floatTransfer)
377  {
378  // Fast path.
379  if
380  (
381  outstandingRecvRequest_ >= 0
382  && outstandingRecvRequest_ < Pstream::nRequests()
383  )
384  {
385  UPstream::waitRequest(outstandingRecvRequest_);
386  }
387  // Recv finished so assume sending finished as well.
388  outstandingSendRequest_ = -1;
389  outstandingRecvRequest_ = -1;
390 
391  // Consume straight from scalarReceiveBuf_
392 
393  // Transform according to the transformation tensor
394  transformCoupleField(scalarReceiveBuf_, cmpt);
395 
396  // Multiply the field by coefficients and add into the result
397  forAll(faceCells, elemI)
398  {
399  result[faceCells[elemI]] -= coeffs[elemI]*scalarReceiveBuf_[elemI];
400  }
401  }
402  else
403  {
404  scalarField pnf
405  (
406  procPatch_.compressedReceive<scalar>(commsType, this->size())()
407  );
408 
409  // Transform according to the transformation tensor
410  transformCoupleField(pnf, cmpt);
411 
412  // Multiply the field by coefficients and add into the result
413  forAll(faceCells, elemI)
414  {
415  result[faceCells[elemI]] -= coeffs[elemI]*pnf[elemI];
416  }
417  }
418 
419  const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = true;
420 }
421 
422 
423 template<class Type>
425 (
426  Field<Type>&,
427  const Field<Type>& psiInternal,
428  const scalarField&,
429  const Pstream::commsTypes commsType
430 ) const
431 {
432  this->patch().patchInternalField(psiInternal, sendBuf_);
433 
434  if (commsType == Pstream::nonBlocking && !Pstream::floatTransfer)
435  {
436  // Fast path.
437  if (debug && !this->ready())
438  {
440  << "On patch " << procPatch_.name()
441  << " outstanding request."
442  << abort(FatalError);
443  }
444 
445 
446  receiveBuf_.setSize(sendBuf_.size());
447  outstandingRecvRequest_ = UPstream::nRequests();
449  (
450  Pstream::nonBlocking,
451  procPatch_.neighbProcNo(),
452  reinterpret_cast<char*>(receiveBuf_.begin()),
453  receiveBuf_.byteSize(),
454  procPatch_.tag(),
455  procPatch_.comm()
456  );
457 
458  outstandingSendRequest_ = UPstream::nRequests();
460  (
461  Pstream::nonBlocking,
462  procPatch_.neighbProcNo(),
463  reinterpret_cast<const char*>(sendBuf_.begin()),
464  sendBuf_.byteSize(),
465  procPatch_.tag(),
466  procPatch_.comm()
467  );
468  }
469  else
470  {
471  procPatch_.compressedSend(commsType, sendBuf_);
472  }
473 
474  const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = false;
475 }
476 
477 
478 template<class Type>
480 (
481  Field<Type>& result,
482  const Field<Type>&,
483  const scalarField& coeffs,
484  const Pstream::commsTypes commsType
485 ) const
486 {
487  if (this->updatedMatrix())
488  {
489  return;
490  }
491 
492  const labelUList& faceCells = this->patch().faceCells();
493 
494  if (commsType == Pstream::nonBlocking && !Pstream::floatTransfer)
495  {
496  // Fast path.
497  if
498  (
499  outstandingRecvRequest_ >= 0
500  && outstandingRecvRequest_ < Pstream::nRequests()
501  )
502  {
503  UPstream::waitRequest(outstandingRecvRequest_);
504  }
505  // Recv finished so assume sending finished as well.
506  outstandingSendRequest_ = -1;
507  outstandingRecvRequest_ = -1;
508 
509  // Consume straight from receiveBuf_
510 
511  // Transform according to the transformation tensor
512  transformCoupleField(receiveBuf_);
513 
514  // Multiply the field by coefficients and add into the result
515  forAll(faceCells, elemI)
516  {
517  result[faceCells[elemI]] -= coeffs[elemI]*receiveBuf_[elemI];
518  }
519  }
520  else
521  {
522  Field<Type> pnf
523  (
524  procPatch_.compressedReceive<Type>(commsType, this->size())()
525  );
526 
527  // Transform according to the transformation tensor
528  transformCoupleField(pnf);
529 
530  // Multiply the field by coefficients and add into the result
531  forAll(faceCells, elemI)
532  {
533  result[faceCells[elemI]] -= coeffs[elemI]*pnf[elemI];
534  }
535  }
536 
537  const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = true;
538 }
539 
540 
541 template<class Type>
543 {
544  if
545  (
546  outstandingSendRequest_ >= 0
547  && outstandingSendRequest_ < Pstream::nRequests()
548  )
549  {
550  bool finished = UPstream::finishedRequest(outstandingSendRequest_);
551  if (!finished)
552  {
553  return false;
554  }
555  }
556  outstandingSendRequest_ = -1;
557 
558  if
559  (
560  outstandingRecvRequest_ >= 0
561  && outstandingRecvRequest_ < Pstream::nRequests()
562  )
563  {
564  bool finished = UPstream::finishedRequest(outstandingRecvRequest_);
565  if (!finished)
566  {
567  return false;
568  }
569  }
570  outstandingRecvRequest_ = -1;
571 
572  return true;
573 }
574 
575 
576 // ************************************************************************* //
const fvPatch & patch() const
Return patch.
Definition: fvPatchField.H:339
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
uint8_t direction
Definition: direction.H:46
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
virtual void initEvaluate(const Pstream::commsTypes commsType)
Initialise the evaluation of the patch field.
error FatalError
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:137
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
Xfer< List< T > > xfer()
Transfer contents to the Xfer container.
Definition: ListI.H:90
commsTypes
Types of communications.
Definition: UPstream.H:64
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:61
virtual bool ready() const
Is all data available.
points setSize(newPointi)
Spatial transformation functions for primitive fields.
virtual bool ready() const
Is all data available.
bool read(const char *, int32_t &)
Definition: int32IO.C:85
Abstract base class for processor coupled interfaces.
Pre-declare SubField and related Field type.
Definition: Field.H:57
Foam::fvPatchFieldMapper.
virtual void initInterfaceMatrixUpdate(scalarField &result, const scalarField &psiInternal, const scalarField &coeffs, const direction cmpt, const Pstream::commsTypes commsType) const
Initialise neighbour matrix update.
bool updatedMatrix() const
Whether matrix has been updated.
virtual tmp< Field< Type > > patchNeighbourField() const
Return neighbour field given internal field.
errorManip< error > abort(error &err)
Definition: errorManip.H:131
Abstract base class for coupled patches.
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
virtual tmp< Field< Type > > snGrad() const
Return patch-normal gradient.
virtual void evaluate(const Pstream::commsTypes commsType)
Evaluate the patch field.
labelList f(nPoints)
Template functions to aid in the implementation of demand driven data.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:331
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
This boundary condition enables processor communication across patches.
volScalarField & p
A class for managing temporary objects.
Definition: PtrList.H:54
virtual void updateInterfaceMatrix(scalarField &result, const scalarField &psiInternal, const scalarField &coeffs, const direction cmpt, const Pstream::commsTypes commsType) const
Update result field based on interface functionality.
runTime write()
processorFvPatchField(const fvPatch &, const DimensionedField< Type, volMesh > &)
Construct from patch and internal field.
dimensionSet transform(const dimensionSet &)
Definition: dimensionSet.C:465
IOerror FatalIOError