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-2025 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  UList<Type>& pnf
215 ) const
216 {
217  if (debug && !this->ready())
218  {
220  << "Outstanding request on patch " << procPatch_.name()
221  << abort(FatalError);
222  }
223  pnf.deepCopy(*this);
224 }
225 
226 
227 template<class Type>
229 (
230  const Pstream::commsTypes commsType
231 )
232 {
233  if (UPstream::parRun())
234  {
235  sendBuf_.resize_nocopy(this->patch().size());
236  this->patchInternalField(sendBuf_);
237 
238  if
239  (
241  && (std::is_integral_v<Type> || !UPstream::floatTransfer)
242  )
243  {
244  if constexpr (!is_contiguous_v<Type>)
245  {
247  << "Invalid for non-contiguous data types"
248  << abort(FatalError);
249  }
250 
251  // Receive straight into *this
252  Field<Type>& self = *this;
253  self.resize_nocopy(sendBuf_.size());
254 
255  recvRequest_ = UPstream::nRequests();
257  (
259  procPatch_.neighbProcNo(),
260  self,
261  procPatch_.tag(),
262  procPatch_.comm()
263  );
264 
265  sendRequest_ = UPstream::nRequests();
267  (
269  procPatch_.neighbProcNo(),
270  sendBuf_,
271  procPatch_.tag(),
272  procPatch_.comm()
273  );
274  }
275  else
276  {
277  procPatch_.compressedSend(commsType, sendBuf_);
278  }
279  }
280 }
281 
282 
283 template<class Type>
285 (
286  const Pstream::commsTypes commsType
287 )
288 {
289  if (UPstream::parRun())
290  {
291  if
292  (
294  && (std::is_integral_v<Type> || !UPstream::floatTransfer)
295  )
296  {
297  // Fast path: received into *this
298 
299  // Require receive data.
300  // Only update the send request state.
301  UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
302  if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
303  }
304  else
305  {
306  procPatch_.compressedReceive<Type>(commsType, *this);
307  }
308 
309  if (doTransform())
310  {
311  transform(*this, procPatch_.forwardT(), *this);
312  }
313  }
314 }
315 
316 
317 template<class Type>
320 (
321  const scalarField& deltaCoeffs
322 ) const
323 {
324  return deltaCoeffs*(*this - this->patchInternalField());
325 }
326 
327 
328 template<class Type>
330 (
332  const bool add,
333  const lduAddressing& lduAddr,
334  const label patchId,
335  const solveScalarField& psiInternal,
336  const scalarField&,
337  const direction,
338  const Pstream::commsTypes commsType
339 ) const
340 {
341  const labelUList& faceCells = lduAddr.patchAddr(patchId);
342 
343  {
344  scalarSendBuf_.resize_nocopy(faceCells.size());
345  scalarRecvBuf_.resize_nocopy(faceCells.size());
346 
347  forAll(faceCells, i)
348  {
349  scalarSendBuf_[i] = psiInternal[faceCells[i]];
350  }
351  }
352 
353  if
354  (
357  )
358  {
359  // Fast path.
360  if (debug && !this->all_ready())
361  {
363  << "Outstanding request(s) on patch " << procPatch_.name()
364  << abort(FatalError);
365  }
366 
367  recvRequest_ = UPstream::nRequests();
369  (
371  procPatch_.neighbProcNo(),
372  scalarRecvBuf_,
373  procPatch_.tag(),
374  procPatch_.comm()
375  );
376 
377  sendRequest_ = UPstream::nRequests();
379  (
381  procPatch_.neighbProcNo(),
382  scalarSendBuf_,
383  procPatch_.tag(),
384  procPatch_.comm()
385  );
386  }
387  else
388  {
389  procPatch_.compressedSend(commsType, scalarSendBuf_);
390  }
392  this->updatedMatrix(false);
393 }
394 
395 
396 template<class Type>
398 (
399  solveScalarField& result,
400  const bool add,
401  const lduAddressing& lduAddr,
402  const label patchId,
403  const solveScalarField&,
404  const scalarField& coeffs,
405  const direction cmpt,
406  const Pstream::commsTypes commsType
407 ) const
408 {
409  if (this->updatedMatrix())
410  {
411  return;
412  }
413 
414  const labelUList& faceCells = lduAddr.patchAddr(patchId);
415 
416  if
417  (
420  )
421  {
422  // Fast path: consume straight from receive buffer
423 
424  // Require receive data.
425  // Only update the send request state.
426  UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
427  if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
428  }
429  else
430  {
431  scalarRecvBuf_.resize_nocopy(faceCells.size()); // In general a no-op
432  procPatch_.compressedReceive(commsType, scalarRecvBuf_);
433  }
434 
435 
437  {
438  // Transform non-scalar data according to the transformation tensor
439  transformCoupleField(scalarRecvBuf_, cmpt);
440  }
441 
442  // Multiply the field by coefficients and add into the result
443  this->addToInternalField(result, !add, faceCells, coeffs, scalarRecvBuf_);
445  this->updatedMatrix(true);
446 }
447 
448 
449 template<class Type>
451 (
452  Field<Type>&,
453  const bool add,
454  const lduAddressing& lduAddr,
455  const label patchId,
456  const Field<Type>& psiInternal,
457  const scalarField&,
458  const Pstream::commsTypes commsType
459 ) const
460 {
461  const labelUList& faceCells = lduAddr.patchAddr(patchId);
462 
463  {
464  sendBuf_.resize_nocopy(faceCells.size());
465  recvBuf_.resize_nocopy(faceCells.size());
466 
467  forAll(faceCells, i)
468  {
469  sendBuf_[i] = psiInternal[faceCells[i]];
470  }
471  }
472 
473  if
474  (
476  && (std::is_integral_v<Type> || !UPstream::floatTransfer)
477  )
478  {
479  // Fast path.
480  if (debug && !this->all_ready())
481  {
483  << "Outstanding request(s) on patch " << procPatch_.name()
484  << abort(FatalError);
485  }
486 
487  recvRequest_ = UPstream::nRequests();
489  (
491  procPatch_.neighbProcNo(),
492  recvBuf_,
493  procPatch_.tag(),
494  procPatch_.comm()
495  );
496 
497  sendRequest_ = UPstream::nRequests();
499  (
501  procPatch_.neighbProcNo(),
502  sendBuf_,
503  procPatch_.tag(),
504  procPatch_.comm()
505  );
506  }
507  else
508  {
509  procPatch_.compressedSend(commsType, sendBuf_);
510  }
512  this->updatedMatrix(false);
513 }
514 
515 
516 template<class Type>
518 (
519  Field<Type>& result,
520  const bool add,
521  const lduAddressing& lduAddr,
522  const label patchId,
523  const Field<Type>&,
524  const scalarField& coeffs,
525  const Pstream::commsTypes commsType
526 ) const
527 {
528  if (this->updatedMatrix())
529  {
530  return;
531  }
532 
533  const labelUList& faceCells = lduAddr.patchAddr(patchId);
534 
535  if
536  (
538  && (std::is_integral_v<Type> || !UPstream::floatTransfer)
539  )
540  {
541  // Fast path: consume straight from receive buffer
542 
543  // Require receive data.
544  // Only update the send request state.
545  UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
546  if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
547  }
548  else
549  {
550  recvBuf_.resize_nocopy(faceCells.size()); // In general a no-op
551  procPatch_.compressedReceive(commsType, recvBuf_);
552  }
553 
554 
555  // Transform according to the transformation tensor
556  transformCoupleField(recvBuf_);
557 
558  // Multiply the field by coefficients and add into the result
559  this->addToInternalField(result, !add, faceCells, coeffs, recvBuf_);
560 
561  this->updatedMatrix(true);
562 }
563 
564 
565 // ************************************************************************* //
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:942
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:250
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:600
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:1586
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()
static std::streamsize read(const UPstream::commsTypes commsType, const int fromProcNo, Type *buffer, std::streamsize count, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm, UPstream::Request *req=nullptr)
Receive buffer contents (contiguous types) from given processor.
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:76
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:286
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:87
Spatial transformation functions for primitive fields.
Generic templated field type.
Definition: Field.H:63
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.
static bool write(const UPstream::commsTypes commsType, const int toProcNo, const Type *buffer, std::streamsize count, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm, UPstream::Request *req=nullptr, const UPstream::sendModes sendMode=UPstream::sendModes::normal)
Write buffer contents (contiguous types only) to given processor.
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)
refinementData transform(const tensor &, const refinementData val)
No-op rotational transform for base types.
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:629
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:706
const std::string patch
OpenFOAM patch number as a std::string.
::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
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.
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
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...