processorFvPatchField.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2020 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 fvPatch& p,
75  const dictionary& dict
76 )
77 :
78  coupledFvPatchField<Type>(p, iF, dict, dict.found("value")),
79  procPatch_(refCast<const processorFvPatch>(p)),
80  sendBuf_(0),
81  receiveBuf_(0),
82  outstandingSendRequest_(-1),
83  outstandingRecvRequest_(-1),
84  scalarSendBuf_(0),
85  scalarReceiveBuf_(0)
86 {
87  if (!isA<processorFvPatch>(p))
88  {
90  (
91  dict
92  ) << "\n patch type '" << p.type()
93  << "' not constraint type '" << typeName << "'"
94  << "\n for patch " << p.name()
95  << " of field " << this->internalField().name()
96  << " in file " << this->internalField().objectPath()
97  << exit(FatalIOError);
98  }
99 
100  // If the value is not supplied set to the internal field
101  if (!dict.found("value"))
102  {
103  fvPatchField<Type>::operator=(this->patchInternalField());
104  }
105 }
106 
107 
108 template<class Type>
110 (
111  const processorFvPatchField<Type>& ptf,
112  const fvPatch& p,
114  const fvPatchFieldMapper& mapper
115 )
116 :
117  coupledFvPatchField<Type>(ptf, p, iF, mapper),
118  procPatch_(refCast<const processorFvPatch>(p)),
119  sendBuf_(0),
120  receiveBuf_(0),
121  outstandingSendRequest_(-1),
122  outstandingRecvRequest_(-1),
123  scalarSendBuf_(0),
124  scalarReceiveBuf_(0)
125 {
126  if (!isA<processorFvPatch>(this->patch()))
127  {
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  if (debug && !ptf.ready())
136  {
138  << "On patch " << procPatch_.name() << " outstanding request."
139  << abort(FatalError);
140  }
141 }
142 
143 
144 template<class Type>
146 (
147  const processorFvPatchField<Type>& ptf,
149 )
150 :
151  coupledFvPatchField<Type>(ptf, iF),
152  procPatch_(refCast<const processorFvPatch>(ptf.patch())),
153  sendBuf_(0),
154  receiveBuf_(0),
155  outstandingSendRequest_(-1),
156  outstandingRecvRequest_(-1),
157  scalarSendBuf_(0),
158  scalarReceiveBuf_(0)
159 {
160  if (debug && !ptf.ready())
161  {
163  << "On patch " << procPatch_.name() << " outstanding request."
164  << abort(FatalError);
165  }
166 }
167 
168 
169 // * * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * //
170 
171 template<class Type>
173 {}
174 
175 
176 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
177 
178 template<class Type>
181 {
182  if (debug && !this->ready())
183  {
185  << "On patch " << procPatch_.name()
186  << " outstanding request."
187  << abort(FatalError);
188  }
189  return *this;
190 }
191 
192 
193 template<class Type>
195 (
196  const Pstream::commsTypes commsType
197 )
198 {
199  if (Pstream::parRun())
200  {
201  this->patchInternalField(sendBuf_);
202 
203  if
204  (
205  commsType == Pstream::commsTypes::nonBlocking
206  && !Pstream::floatTransfer
207  )
208  {
209  // Fast path. Receive into *this
210  this->setSize(sendBuf_.size());
211  outstandingRecvRequest_ = UPstream::nRequests();
213  (
214  Pstream::commsTypes::nonBlocking,
215  procPatch_.neighbProcNo(),
216  reinterpret_cast<char*>(this->begin()),
217  this->byteSize(),
218  procPatch_.tag(),
219  procPatch_.comm()
220  );
221 
222  outstandingSendRequest_ = UPstream::nRequests();
224  (
225  Pstream::commsTypes::nonBlocking,
226  procPatch_.neighbProcNo(),
227  reinterpret_cast<const char*>(sendBuf_.begin()),
228  this->byteSize(),
229  procPatch_.tag(),
230  procPatch_.comm()
231  );
232  }
233  else
234  {
235  procPatch_.compressedSend(commsType, sendBuf_);
236  }
237  }
238 }
239 
240 
241 template<class Type>
243 (
244  const Pstream::commsTypes commsType
245 )
246 {
247  if (Pstream::parRun())
248  {
249  if
250  (
251  commsType == Pstream::commsTypes::nonBlocking
252  && !Pstream::floatTransfer
253  )
254  {
255  // Fast path. Received into *this
256 
257  if
258  (
259  outstandingRecvRequest_ >= 0
260  && outstandingRecvRequest_ < Pstream::nRequests()
261  )
262  {
263  UPstream::waitRequest(outstandingRecvRequest_);
264  }
265  outstandingSendRequest_ = -1;
266  outstandingRecvRequest_ = -1;
267  }
268  else
269  {
270  procPatch_.compressedReceive<Type>(commsType, *this);
271  }
272 
273  procPatch_.transform().transform(*this, *this);
274  }
275 }
276 
277 
278 template<class Type>
281 (
282  const scalarField& deltaCoeffs
283 ) const
284 {
285  return deltaCoeffs*(*this - this->patchInternalField());
286 }
287 
288 
289 template<class Type>
291 (
292  scalarField&,
293  const scalarField& psiInternal,
294  const scalarField&,
295  const direction,
296  const Pstream::commsTypes commsType
297 ) const
298 {
299  this->patch().patchInternalField(psiInternal, scalarSendBuf_);
300 
301  if
302  (
303  commsType == Pstream::commsTypes::nonBlocking
304  && !Pstream::floatTransfer
305  )
306  {
307  // Fast path.
308  if (debug && !this->ready())
309  {
311  << "On patch " << procPatch_.name()
312  << " outstanding request."
313  << abort(FatalError);
314  }
315 
316 
317  scalarReceiveBuf_.setSize(scalarSendBuf_.size());
318  outstandingRecvRequest_ = UPstream::nRequests();
320  (
321  Pstream::commsTypes::nonBlocking,
322  procPatch_.neighbProcNo(),
323  reinterpret_cast<char*>(scalarReceiveBuf_.begin()),
324  scalarReceiveBuf_.byteSize(),
325  procPatch_.tag(),
326  procPatch_.comm()
327  );
328 
329  outstandingSendRequest_ = UPstream::nRequests();
331  (
332  Pstream::commsTypes::nonBlocking,
333  procPatch_.neighbProcNo(),
334  reinterpret_cast<const char*>(scalarSendBuf_.begin()),
335  scalarSendBuf_.byteSize(),
336  procPatch_.tag(),
337  procPatch_.comm()
338  );
339  }
340  else
341  {
342  procPatch_.compressedSend(commsType, scalarSendBuf_);
343  }
344 
345  const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = false;
346 }
347 
348 
349 template<class Type>
351 (
352  scalarField& result,
353  const scalarField&,
354  const scalarField& coeffs,
355  const direction cmpt,
356  const Pstream::commsTypes commsType
357 ) const
358 {
359  if (this->updatedMatrix())
360  {
361  return;
362  }
363 
364  const labelUList& faceCells = this->patch().faceCells();
365 
366  if
367  (
368  commsType == Pstream::commsTypes::nonBlocking
369  && !Pstream::floatTransfer
370  )
371  {
372  // Fast path.
373  if
374  (
375  outstandingRecvRequest_ >= 0
376  && outstandingRecvRequest_ < Pstream::nRequests()
377  )
378  {
379  UPstream::waitRequest(outstandingRecvRequest_);
380  }
381  // Recv finished so assume sending finished as well.
382  outstandingSendRequest_ = -1;
383  outstandingRecvRequest_ = -1;
384 
385  // Consume straight from scalarReceiveBuf_
386 
387  // Transform according to the transformation tensor
388  transformCoupleField(scalarReceiveBuf_, cmpt);
389 
390  // Multiply the field by coefficients and add into the result
391  forAll(faceCells, elemI)
392  {
393  result[faceCells[elemI]] -= coeffs[elemI]*scalarReceiveBuf_[elemI];
394  }
395  }
396  else
397  {
398  scalarField pnf
399  (
400  procPatch_.compressedReceive<scalar>(commsType, this->size())()
401  );
402 
403  // Transform according to the transformation tensor
404  transformCoupleField(pnf, cmpt);
405 
406  // Multiply the field by coefficients and add into the result
407  forAll(faceCells, elemI)
408  {
409  result[faceCells[elemI]] -= coeffs[elemI]*pnf[elemI];
410  }
411  }
412 
413  const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = true;
414 }
415 
416 
417 template<class Type>
419 (
420  Field<Type>&,
421  const Field<Type>& psiInternal,
422  const scalarField&,
423  const Pstream::commsTypes commsType
424 ) const
425 {
426  this->patch().patchInternalField(psiInternal, sendBuf_);
427 
428  if
429  (
430  commsType == Pstream::commsTypes::nonBlocking
431  && !Pstream::floatTransfer
432  )
433  {
434  // Fast path.
435  if (debug && !this->ready())
436  {
438  << "On patch " << procPatch_.name()
439  << " outstanding request."
440  << abort(FatalError);
441  }
442 
443 
444  receiveBuf_.setSize(sendBuf_.size());
445  outstandingRecvRequest_ = UPstream::nRequests();
447  (
448  Pstream::commsTypes::nonBlocking,
449  procPatch_.neighbProcNo(),
450  reinterpret_cast<char*>(receiveBuf_.begin()),
451  receiveBuf_.byteSize(),
452  procPatch_.tag(),
453  procPatch_.comm()
454  );
455 
456  outstandingSendRequest_ = UPstream::nRequests();
458  (
459  Pstream::commsTypes::nonBlocking,
460  procPatch_.neighbProcNo(),
461  reinterpret_cast<const char*>(sendBuf_.begin()),
462  sendBuf_.byteSize(),
463  procPatch_.tag(),
464  procPatch_.comm()
465  );
466  }
467  else
468  {
469  procPatch_.compressedSend(commsType, sendBuf_);
470  }
471 
472  const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = false;
473 }
474 
475 
476 template<class Type>
478 (
479  Field<Type>& result,
480  const Field<Type>&,
481  const scalarField& coeffs,
482  const Pstream::commsTypes commsType
483 ) const
484 {
485  if (this->updatedMatrix())
486  {
487  return;
488  }
489 
490  const labelUList& faceCells = this->patch().faceCells();
491 
492  if
493  (
494  commsType == Pstream::commsTypes::nonBlocking
495  && !Pstream::floatTransfer
496  )
497  {
498  // Fast path.
499  if
500  (
501  outstandingRecvRequest_ >= 0
502  && outstandingRecvRequest_ < Pstream::nRequests()
503  )
504  {
505  UPstream::waitRequest(outstandingRecvRequest_);
506  }
507  // Recv finished so assume sending finished as well.
508  outstandingSendRequest_ = -1;
509  outstandingRecvRequest_ = -1;
510 
511  // Consume straight from receiveBuf_
512 
513  // Transform according to the transformation tensor
514  transformCoupleField(receiveBuf_);
515 
516  // Multiply the field by coefficients and add into the result
517  forAll(faceCells, elemI)
518  {
519  result[faceCells[elemI]] -= coeffs[elemI]*receiveBuf_[elemI];
520  }
521  }
522  else
523  {
524  Field<Type> pnf
525  (
526  procPatch_.compressedReceive<Type>(commsType, this->size())()
527  );
528 
529  // Transform according to the transformation tensor
530  transformCoupleField(pnf);
531 
532  // Multiply the field by coefficients and add into the result
533  forAll(faceCells, elemI)
534  {
535  result[faceCells[elemI]] -= coeffs[elemI]*pnf[elemI];
536  }
537  }
538 
539  const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = true;
540 }
541 
542 
543 template<class Type>
545 {
546  if
547  (
548  outstandingSendRequest_ >= 0
549  && outstandingSendRequest_ < Pstream::nRequests()
550  )
551  {
552  bool finished = UPstream::finishedRequest(outstandingSendRequest_);
553  if (!finished)
554  {
555  return false;
556  }
557  }
558  outstandingSendRequest_ = -1;
559 
560  if
561  (
562  outstandingRecvRequest_ >= 0
563  && outstandingRecvRequest_ < Pstream::nRequests()
564  )
565  {
566  bool finished = UPstream::finishedRequest(outstandingRecvRequest_);
567  if (!finished)
568  {
569  return false;
570  }
571  }
572  outstandingRecvRequest_ = -1;
573 
574  return true;
575 }
576 
577 
578 // ************************************************************************* //
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
bool updatedMatrix() const
Whether matrix has been updated.
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:156
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:323
commsTypes
Types of communications.
Definition: UPstream.H:64
uint8_t direction
Definition: direction.H:45
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:62
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
Definition: fvPatchField.H:66
void read(Istream &, label &, const dictionary &)
In-place read with dictionary lookup.
virtual void initInterfaceMatrixUpdate(scalarField &result, const scalarField &psiInternal, const scalarField &coeffs, const direction cmpt, const Pstream::commsTypes commsType) const
Initialise neighbour matrix update.
points setSize(newPointi)
Spatial transformation functions for primitive fields.
Pre-declare SubField and related Field type.
Definition: Field.H:56
Foam::fvPatchFieldMapper.
void write(std::ostream &os, const bool binary, List< floatScalar > &fField)
Write floats ascii or binary.
virtual bool ready() const
Is all data available.
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
const fvPatch & patch() const
Return patch.
Definition: fvPatchField.H:337
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:335
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
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.
This boundary condition enables processor communication across patches.
volScalarField & p
A class for managing temporary objects.
Definition: PtrList.H:53
virtual bool ready() const
Is all data available.
virtual tmp< Field< Type > > patchNeighbourField() const
Return neighbour field given internal field.
virtual tmp< Field< Type > > snGrad() const
Return patch-normal gradient.
processorFvPatchField(const fvPatch &, const DimensionedField< Type, volMesh > &)
Construct from patch and internal field.
IOerror FatalIOError