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-2022 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  const Pstream::commsTypes
183 ) const
184 {
185  if (debug && !this->ready())
186  {
188  << "On patch " << procPatch_.name()
189  << " outstanding request."
190  << abort(FatalError);
191  }
192  return *this;
193 }
194 
195 
196 template<class Type>
198 (
199  const Pstream::commsTypes commsType
200 )
201 {
202  if (Pstream::parRun())
203  {
204  this->patchInternalField(sendBuf_);
205 
206  if
207  (
208  commsType == Pstream::commsTypes::nonBlocking
209  && !Pstream::floatTransfer
210  )
211  {
212  // Fast path. Receive into *this
213  this->setSize(sendBuf_.size());
214  outstandingRecvRequest_ = UPstream::nRequests();
216  (
217  Pstream::commsTypes::nonBlocking,
218  procPatch_.neighbProcNo(),
219  reinterpret_cast<char*>(this->begin()),
220  this->byteSize(),
221  procPatch_.tag(),
222  procPatch_.comm()
223  );
224 
225  outstandingSendRequest_ = UPstream::nRequests();
227  (
228  Pstream::commsTypes::nonBlocking,
229  procPatch_.neighbProcNo(),
230  reinterpret_cast<const char*>(sendBuf_.begin()),
231  this->byteSize(),
232  procPatch_.tag(),
233  procPatch_.comm()
234  );
235  }
236  else
237  {
238  procPatch_.compressedSend(commsType, sendBuf_);
239  }
240  }
241 }
242 
243 
244 template<class Type>
246 (
247  const Pstream::commsTypes commsType
248 )
249 {
250  if (Pstream::parRun())
251  {
252  if
253  (
254  commsType == Pstream::commsTypes::nonBlocking
255  && !Pstream::floatTransfer
256  )
257  {
258  // Fast path. Received into *this
259 
260  if
261  (
262  outstandingRecvRequest_ >= 0
263  && outstandingRecvRequest_ < Pstream::nRequests()
264  )
265  {
266  UPstream::waitRequest(outstandingRecvRequest_);
267  }
268  outstandingSendRequest_ = -1;
269  outstandingRecvRequest_ = -1;
270  }
271  else
272  {
273  procPatch_.compressedReceive<Type>(commsType, *this);
274  }
275 
276  procPatch_.transform().transform(*this, *this);
277  }
278 }
279 
280 
281 template<class Type>
284 (
285  const scalarField& deltaCoeffs
286 ) const
287 {
288  return deltaCoeffs*(*this - this->patchInternalField());
289 }
290 
291 
292 template<class Type>
294 (
295  scalarField&,
296  const scalarField& psiInternal,
297  const scalarField&,
298  const direction,
299  const Pstream::commsTypes commsType
300 ) const
301 {
302  this->patch().patchInternalField(psiInternal, scalarSendBuf_);
303 
304  if
305  (
306  commsType == Pstream::commsTypes::nonBlocking
307  && !Pstream::floatTransfer
308  )
309  {
310  // Fast path.
311  if (debug && !this->ready())
312  {
314  << "On patch " << procPatch_.name()
315  << " outstanding request."
316  << abort(FatalError);
317  }
318 
319 
320  scalarReceiveBuf_.setSize(scalarSendBuf_.size());
321  outstandingRecvRequest_ = UPstream::nRequests();
323  (
324  Pstream::commsTypes::nonBlocking,
325  procPatch_.neighbProcNo(),
326  reinterpret_cast<char*>(scalarReceiveBuf_.begin()),
327  scalarReceiveBuf_.byteSize(),
328  procPatch_.tag(),
329  procPatch_.comm()
330  );
331 
332  outstandingSendRequest_ = UPstream::nRequests();
334  (
335  Pstream::commsTypes::nonBlocking,
336  procPatch_.neighbProcNo(),
337  reinterpret_cast<const char*>(scalarSendBuf_.begin()),
338  scalarSendBuf_.byteSize(),
339  procPatch_.tag(),
340  procPatch_.comm()
341  );
342  }
343  else
344  {
345  procPatch_.compressedSend(commsType, scalarSendBuf_);
346  }
347 
348  const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = false;
349 }
350 
351 
352 template<class Type>
354 (
355  scalarField& result,
356  const scalarField&,
357  const scalarField& coeffs,
358  const direction cmpt,
359  const Pstream::commsTypes commsType
360 ) const
361 {
362  if (this->updatedMatrix())
363  {
364  return;
365  }
366 
367  const labelUList& faceCells = this->patch().faceCells();
368 
369  if
370  (
371  commsType == Pstream::commsTypes::nonBlocking
372  && !Pstream::floatTransfer
373  )
374  {
375  // Fast path.
376  if
377  (
378  outstandingRecvRequest_ >= 0
379  && outstandingRecvRequest_ < Pstream::nRequests()
380  )
381  {
382  UPstream::waitRequest(outstandingRecvRequest_);
383  }
384  // Recv finished so assume sending finished as well.
385  outstandingSendRequest_ = -1;
386  outstandingRecvRequest_ = -1;
387 
388  // Consume straight from scalarReceiveBuf_
389 
390  // Transform according to the transformation tensor
391  transformCoupleField(scalarReceiveBuf_, cmpt);
392 
393  // Multiply the field by coefficients and add into the result
394  forAll(faceCells, elemI)
395  {
396  result[faceCells[elemI]] -= coeffs[elemI]*scalarReceiveBuf_[elemI];
397  }
398  }
399  else
400  {
401  scalarField pnf
402  (
403  procPatch_.compressedReceive<scalar>(commsType, this->size())()
404  );
405 
406  // Transform according to the transformation tensor
407  transformCoupleField(pnf, cmpt);
408 
409  // Multiply the field by coefficients and add into the result
410  forAll(faceCells, elemI)
411  {
412  result[faceCells[elemI]] -= coeffs[elemI]*pnf[elemI];
413  }
414  }
415 
416  const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = true;
417 }
418 
419 
420 template<class Type>
422 (
423  Field<Type>&,
424  const Field<Type>& psiInternal,
425  const scalarField&,
426  const Pstream::commsTypes commsType
427 ) const
428 {
429  this->patch().patchInternalField(psiInternal, sendBuf_);
430 
431  if
432  (
433  commsType == Pstream::commsTypes::nonBlocking
434  && !Pstream::floatTransfer
435  )
436  {
437  // Fast path.
438  if (debug && !this->ready())
439  {
441  << "On patch " << procPatch_.name()
442  << " outstanding request."
443  << abort(FatalError);
444  }
445 
446 
447  receiveBuf_.setSize(sendBuf_.size());
448  outstandingRecvRequest_ = UPstream::nRequests();
450  (
451  Pstream::commsTypes::nonBlocking,
452  procPatch_.neighbProcNo(),
453  reinterpret_cast<char*>(receiveBuf_.begin()),
454  receiveBuf_.byteSize(),
455  procPatch_.tag(),
456  procPatch_.comm()
457  );
458 
459  outstandingSendRequest_ = UPstream::nRequests();
461  (
462  Pstream::commsTypes::nonBlocking,
463  procPatch_.neighbProcNo(),
464  reinterpret_cast<const char*>(sendBuf_.begin()),
465  sendBuf_.byteSize(),
466  procPatch_.tag(),
467  procPatch_.comm()
468  );
469  }
470  else
471  {
472  procPatch_.compressedSend(commsType, sendBuf_);
473  }
474 
475  const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = false;
476 }
477 
478 
479 template<class Type>
481 (
482  Field<Type>& result,
483  const Field<Type>&,
484  const scalarField& coeffs,
485  const Pstream::commsTypes commsType
486 ) const
487 {
488  if (this->updatedMatrix())
489  {
490  return;
491  }
492 
493  const labelUList& faceCells = this->patch().faceCells();
494 
495  if
496  (
497  commsType == Pstream::commsTypes::nonBlocking
498  && !Pstream::floatTransfer
499  )
500  {
501  // Fast path.
502  if
503  (
504  outstandingRecvRequest_ >= 0
505  && outstandingRecvRequest_ < Pstream::nRequests()
506  )
507  {
508  UPstream::waitRequest(outstandingRecvRequest_);
509  }
510  // Recv finished so assume sending finished as well.
511  outstandingSendRequest_ = -1;
512  outstandingRecvRequest_ = -1;
513 
514  // Consume straight from receiveBuf_
515 
516  // Transform according to the transformation tensor
517  transformCoupleField(receiveBuf_);
518 
519  // Multiply the field by coefficients and add into the result
520  forAll(faceCells, elemI)
521  {
522  result[faceCells[elemI]] -= coeffs[elemI]*receiveBuf_[elemI];
523  }
524  }
525  else
526  {
527  Field<Type> pnf
528  (
529  procPatch_.compressedReceive<Type>(commsType, this->size())()
530  );
531 
532  // Transform according to the transformation tensor
533  transformCoupleField(pnf);
534 
535  // Multiply the field by coefficients and add into the result
536  forAll(faceCells, elemI)
537  {
538  result[faceCells[elemI]] -= coeffs[elemI]*pnf[elemI];
539  }
540  }
541 
542  const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = true;
543 }
544 
545 
546 template<class Type>
548 {
549  if
550  (
551  outstandingSendRequest_ >= 0
552  && outstandingSendRequest_ < Pstream::nRequests()
553  )
554  {
555  bool finished = UPstream::finishedRequest(outstandingSendRequest_);
556  if (!finished)
557  {
558  return false;
559  }
560  }
561  outstandingSendRequest_ = -1;
562 
563  if
564  (
565  outstandingRecvRequest_ >= 0
566  && outstandingRecvRequest_ < Pstream::nRequests()
567  )
568  {
569  bool finished = UPstream::finishedRequest(outstandingRecvRequest_);
570  if (!finished)
571  {
572  return false;
573  }
574  }
575  outstandingRecvRequest_ = -1;
576 
577  return true;
578 }
579 
580 
581 // ************************************************************************* //
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:306
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:63
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:351
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:318
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.
virtual tmp< Field< Type > > patchNeighbourField(const Pstream::commsTypes) const
Return neighbour field given internal field.
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 > > snGrad() const
Return patch-normal gradient.
processorFvPatchField(const fvPatch &, const DimensionedField< Type, volMesh > &)
Construct from patch and internal field.
IOerror FatalIOError