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 | 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 "processorFvPatchField.H"
31 #include "transformField.H"
32 
33 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
34 
35 template<class Type>
37 (
38  const fvPatch& p,
40 )
41 :
42  coupledFvPatchField<Type>(p, iF),
43  procPatch_(refCast<const processorFvPatch>(p)),
44  sendRequest_(-1),
45  recvRequest_(-1)
46 {}
47 
48 
49 template<class Type>
51 (
52  const fvPatch& p,
54  const Field<Type>& f
55 )
56 :
57  coupledFvPatchField<Type>(p, iF, f),
58  procPatch_(refCast<const processorFvPatch>(p)),
59  sendRequest_(-1),
60  recvRequest_(-1)
61 {}
62 
63 
64 template<class Type>
66 (
67  const fvPatch& p,
69  const dictionary& dict
70 )
71 :
72  coupledFvPatchField<Type>(p, iF, dict, IOobjectOption::NO_READ),
73  procPatch_(refCast<const processorFvPatch>(p, dict)),
74  sendRequest_(-1),
75  recvRequest_(-1)
76 {
77  if (!isA<processorFvPatch>(p))
78  {
80  << "\n patch type '" << p.type()
81  << "' not constraint type '" << typeName << "'"
82  << "\n for patch " << p.name()
83  << " of field " << this->internalField().name()
84  << " in file " << this->internalField().objectPath()
85  << exit(FatalIOError);
86  }
87 
88  // Use 'value' supplied, or set to internal field
89  if (!this->readValueEntry(dict))
90  {
92  }
93 }
94 
95 
96 template<class Type>
98 (
99  const processorFvPatchField<Type>& ptf,
100  const fvPatch& p,
101  const DimensionedField<Type, volMesh>& iF,
102  const fvPatchFieldMapper& mapper
103 )
104 :
105  coupledFvPatchField<Type>(ptf, p, iF, mapper),
106  procPatch_(refCast<const processorFvPatch>(p)),
107  sendRequest_(-1),
108  recvRequest_(-1)
109 {
110  if (!isA<processorFvPatch>(this->patch()))
111  {
113  << "\n patch type '" << p.type()
114  << "' not constraint type '" << typeName << "'"
115  << "\n for patch " << p.name()
116  << " of field " << this->internalField().name()
117  << " in file " << this->internalField().objectPath()
118  << exit(FatalError);
119  }
120  if (debug && !ptf.all_ready())
121  {
123  << "Outstanding request(s) on patch " << procPatch_.name()
125  }
126 }
127 
128 
129 template<class Type>
131 (
132  const processorFvPatchField<Type>& ptf
133 )
134 :
135  processorLduInterfaceField(),
136  coupledFvPatchField<Type>(ptf),
137  procPatch_(refCast<const processorFvPatch>(ptf.patch())),
138  sendRequest_(-1),
139  recvRequest_(-1),
140  sendBuf_(std::move(ptf.sendBuf_)),
141  recvBuf_(std::move(ptf.recvBuf_)),
142  scalarSendBuf_(std::move(ptf.scalarSendBuf_)),
143  scalarRecvBuf_(std::move(ptf.scalarRecvBuf_))
144 {
145  if (debug && !ptf.all_ready())
146  {
148  << "Outstanding request(s) on patch " << procPatch_.name()
150  }
151 }
152 
153 
154 template<class Type>
156 (
157  const processorFvPatchField<Type>& ptf,
158  const DimensionedField<Type, volMesh>& iF
159 )
160 :
161  coupledFvPatchField<Type>(ptf, iF),
162  procPatch_(refCast<const processorFvPatch>(ptf.patch())),
163  sendRequest_(-1),
164  recvRequest_(-1)
165 {
166  if (debug && !ptf.all_ready())
167  {
169  << "Outstanding request(s) on patch " << procPatch_.name()
170  << abort(FatalError);
171  }
172 }
173 
174 
175 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
176 
177 template<class Type>
179 {
180  return UPstream::finishedRequestPair(recvRequest_, sendRequest_);
181 }
182 
183 
184 template<class Type>
186 {
187  const bool ok = UPstream::finishedRequest(recvRequest_);
188  if (ok)
189  {
190  recvRequest_ = -1;
191  if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
192  }
193  return ok;
194 }
195 
196 
197 template<class Type>
200 {
201  if (debug && !this->ready())
202  {
204  << "Outstanding request on patch " << procPatch_.name()
205  << abort(FatalError);
206  }
207  return *this;
208 }
209 
210 
211 template<class Type>
213 (
214  const Pstream::commsTypes commsType
215 )
216 {
217  if (UPstream::parRun())
218  {
219  this->patchInternalField(sendBuf_);
220 
221  if
222  (
224  && (std::is_integral<Type>::value || !UPstream::floatTransfer)
225  )
226  {
227  if (!is_contiguous<Type>::value)
228  {
230  << "Invalid for non-contiguous data types"
231  << abort(FatalError);
232  }
233 
234  // Receive straight into *this
235  this->resize_nocopy(sendBuf_.size());
236 
237  recvRequest_ = UPstream::nRequests();
239  (
241  procPatch_.neighbProcNo(),
242  this->data_bytes(),
243  this->size_bytes(),
244  procPatch_.tag(),
245  procPatch_.comm()
246  );
247 
248  sendRequest_ = UPstream::nRequests();
250  (
252  procPatch_.neighbProcNo(),
253  sendBuf_.cdata_bytes(),
254  sendBuf_.size_bytes(),
255  procPatch_.tag(),
256  procPatch_.comm()
257  );
258  }
259  else
260  {
261  procPatch_.compressedSend(commsType, sendBuf_);
262  }
263  }
264 }
265 
266 
267 template<class Type>
269 (
270  const Pstream::commsTypes commsType
271 )
272 {
273  if (UPstream::parRun())
274  {
275  if
276  (
278  && (std::is_integral<Type>::value || !UPstream::floatTransfer)
279  )
280  {
281  // Fast path: received into *this
282 
283  // Require receive data.
284  // Only update the send request state.
285  UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
286  if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
287  }
288  else
289  {
290  procPatch_.compressedReceive<Type>(commsType, *this);
291  }
292 
293  if (doTransform())
294  {
295  transform(*this, procPatch_.forwardT(), *this);
296  }
297  }
298 }
299 
300 
301 template<class Type>
304 (
305  const scalarField& deltaCoeffs
306 ) const
307 {
308  return deltaCoeffs*(*this - this->patchInternalField());
309 }
310 
311 
312 template<class Type>
314 (
316  const bool add,
317  const lduAddressing& lduAddr,
318  const label patchId,
319  const solveScalarField& psiInternal,
320  const scalarField&,
321  const direction,
322  const Pstream::commsTypes commsType
323 ) const
324 {
325  //this->patch().patchInternalField(psiInternal, scalarSendBuf_);
326 
327  const labelUList& faceCells = lduAddr.patchAddr(patchId);
328 
329  scalarSendBuf_.resize_nocopy(this->patch().size());
330  forAll(scalarSendBuf_, facei)
331  {
332  scalarSendBuf_[facei] = psiInternal[faceCells[facei]];
333  }
334 
335  if
336  (
339  )
340  {
341  // Fast path.
342  if (debug && !this->all_ready())
343  {
345  << "Outstanding request(s) on patch " << procPatch_.name()
346  << abort(FatalError);
347  }
348 
349  scalarRecvBuf_.resize_nocopy(scalarSendBuf_.size());
350 
351  recvRequest_ = UPstream::nRequests();
353  (
355  procPatch_.neighbProcNo(),
356  scalarRecvBuf_.data_bytes(),
357  scalarRecvBuf_.size_bytes(),
358  procPatch_.tag(),
359  procPatch_.comm()
360  );
361 
362  sendRequest_ = UPstream::nRequests();
364  (
366  procPatch_.neighbProcNo(),
367  scalarSendBuf_.cdata_bytes(),
368  scalarSendBuf_.size_bytes(),
369  procPatch_.tag(),
370  procPatch_.comm()
371  );
372  }
373  else
374  {
375  procPatch_.compressedSend(commsType, scalarSendBuf_);
376  }
378  this->updatedMatrix(false);
379 }
380 
381 
382 template<class Type>
384 (
385  solveScalarField& result,
386  const bool add,
387  const lduAddressing& lduAddr,
388  const label patchId,
389  const solveScalarField&,
390  const scalarField& coeffs,
391  const direction cmpt,
392  const Pstream::commsTypes commsType
393 ) const
394 {
395  if (this->updatedMatrix())
396  {
397  return;
398  }
399 
400  const labelUList& faceCells = lduAddr.patchAddr(patchId);
401 
402  if
403  (
406  )
407  {
408  // Fast path: consume straight from receive buffer
409 
410  // Require receive data.
411  // Only update the send request state.
412  UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
413  if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
414  }
415  else
416  {
417  scalarRecvBuf_.resize_nocopy(this->size());
418  procPatch_.compressedReceive(commsType, scalarRecvBuf_);
419  }
420 
421 
423  {
424  // Transform non-scalar data according to the transformation tensor
425  transformCoupleField(scalarRecvBuf_, cmpt);
426  }
427 
428  // Multiply the field by coefficients and add into the result
429  this->addToInternalField(result, !add, faceCells, coeffs, scalarRecvBuf_);
431  this->updatedMatrix(true);
432 }
433 
434 
435 template<class Type>
437 (
438  Field<Type>&,
439  const bool add,
440  const lduAddressing& lduAddr,
441  const label patchId,
442  const Field<Type>& psiInternal,
443  const scalarField&,
444  const Pstream::commsTypes commsType
445 ) const
446 {
447  sendBuf_.resize_nocopy(this->patch().size());
448 
449  const labelUList& faceCells = lduAddr.patchAddr(patchId);
450 
451  forAll(sendBuf_, facei)
452  {
453  sendBuf_[facei] = psiInternal[faceCells[facei]];
454  }
455 
456  if
457  (
459  && (std::is_integral<Type>::value || !UPstream::floatTransfer)
460  )
461  {
462  // Fast path.
463  if (debug && !this->all_ready())
464  {
466  << "Outstanding request(s) on patch " << procPatch_.name()
467  << abort(FatalError);
468  }
469 
470  recvBuf_.resize_nocopy(sendBuf_.size());
471 
472  recvRequest_ = UPstream::nRequests();
474  (
476  procPatch_.neighbProcNo(),
477  recvBuf_.data_bytes(),
478  recvBuf_.size_bytes(),
479  procPatch_.tag(),
480  procPatch_.comm()
481  );
482 
483  sendRequest_ = UPstream::nRequests();
485  (
487  procPatch_.neighbProcNo(),
488  sendBuf_.cdata_bytes(),
489  sendBuf_.size_bytes(),
490  procPatch_.tag(),
491  procPatch_.comm()
492  );
493  }
494  else
495  {
496  procPatch_.compressedSend(commsType, sendBuf_);
497  }
499  this->updatedMatrix(false);
500 }
501 
502 
503 template<class Type>
505 (
506  Field<Type>& result,
507  const bool add,
508  const lduAddressing& lduAddr,
509  const label patchId,
510  const Field<Type>&,
511  const scalarField& coeffs,
512  const Pstream::commsTypes commsType
513 ) const
514 {
515  if (this->updatedMatrix())
516  {
517  return;
518  }
519 
520  const labelUList& faceCells = lduAddr.patchAddr(patchId);
521 
522  if
523  (
525  && (std::is_integral<Type>::value || !UPstream::floatTransfer)
526  )
527  {
528  // Fast path: consume straight from receive buffer
529 
530  // Require receive data.
531  // Only update the send request state.
532  UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
533  if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
534  }
535  else
536  {
537  recvBuf_.resize_nocopy(this->size());
538  procPatch_.compressedReceive(commsType, recvBuf_);
539  }
540 
541 
542  // Transform according to the transformation tensor
543  transformCoupleField(recvBuf_);
544 
545  // Multiply the field by coefficients and add into the result
546  this->addToInternalField(result, !add, faceCells, coeffs, recvBuf_);
547 
548  this->updatedMatrix(true);
549 }
550 
551 
552 // ************************************************************************* //
bool readValueEntry(const dictionary &dict, IOobjectOption::readOption readOpt=IOobjectOption::LAZY_READ)
Read the "value" entry into *this.
Definition: fvPatchField.C:32
static bool floatTransfer
Should compact transfer be used in which floats replace doubles reducing the bandwidth requirement at...
Definition: UPstream.H:376
label patchId(-1)
dictionary dict
uint8_t direction
Definition: direction.H:46
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
virtual void initEvaluate(const Pstream::commsTypes commsType)
Initialise the evaluation of the patch field.
commsTypes
Communications types.
Definition: UPstream.H:77
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
const fvPatch & patch() const noexcept
Return the patch.
Definition: fvPatchField.H:269
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:608
static label nRequests() noexcept
Number of outstanding requests (on the internal list of requests)
Type & refCast(U &obj)
A dynamic_cast (for references) to Type reference.
Definition: typeInfo.H:172
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:70
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1061
void extrapolateInternal()
Assign the patch field from the internal field.
Definition: fvPatchField.C:62
static bool finishedRequest(const label i)
Non-blocking comms: has request i finished? Corresponds to MPI_Test()
Smooth ATC in cells next to a set of patches supplied by type.
Definition: faceCells.H:52
virtual void updateInterfaceMatrix(solveScalarField &result, const bool add, const lduAddressing &lduAddr, const label patchId, const solveScalarField &psiInternal, const scalarField &coeffs, const direction cmpt, const Pstream::commsTypes commsType) const
Update result field based on interface functionality.
UList< label > labelUList
A UList of labels.
Definition: UList.H:78
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
static bool finishedRequestPair(label &req0, label &req1)
Non-blocking comms: have both requests finished? Corresponds to pair of MPI_Test() ...
static const char *const typeName
Typename for Field.
Definition: Field.H:86
Spatial transformation functions for primitive fields.
Generic templated field type.
Definition: Field.H:62
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Processor patch.
virtual const labelUList & patchAddr(const label patchNo) const =0
Return patch to internal addressing given patch number.
virtual void initInterfaceMatrixUpdate(solveScalarField &result, const bool add, const lduAddressing &lduAddr, const label patchId, const solveScalarField &psiInternal, const scalarField &coeffs, const direction cmpt, const Pstream::commsTypes commsType) const
Initialise neighbour matrix update.
errorManip< error > abort(error &err)
Definition: errorManip.H:139
Abstract base class for coupled patches.
void add(FieldField< Field1, typename typeOfSum< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
int debug
Static debugging option.
virtual void evaluate(const Pstream::commsTypes commsType)
Evaluate the patch field.
labelList f(nPoints)
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:637
A simple container of IOobject preferences. Can also be used for general handling of read/no-read/rea...
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
const DimensionedField< Type, volMesh > & internalField() const noexcept
Return const-reference to the dimensioned internal field.
Definition: fvPatchField.H:696
const std::string patch
OpenFOAM patch number as a std::string.
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.
::Foam::direction rank(const expressions::valueTypeCode) noexcept
The vector-space rank associated with given valueTypeCode.
Definition: exprTraits.C:70
"nonBlocking" (immediate) : (MPI_Isend, MPI_Irecv)
This boundary condition enables processor communication across patches.
The class contains the addressing required by the lduMatrix: upper, lower and losort.
virtual const word & name() const
Return name.
Definition: fvPatch.H:210
volScalarField & p
A class for managing temporary objects.
Definition: HashPtrTable.H:50
dimensionSet transform(const dimensionSet &ds)
Return the argument; transformations do not change the dimensions.
Definition: dimensionSet.C:521
virtual bool ready() const
Are all (receive) data available?
static void waitRequest(const label i)
Wait until request i has finished. Corresponds to MPI_Wait()
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.
static std::streamsize 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
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...