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"
30 #include "processorFvPatch.H"
32 #include "transformField.H"
33 
34 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
35 
36 template<class Type>
38 (
39  const fvPatch& p,
41 )
42 :
43  coupledFvPatchField<Type>(p, iF),
44  procPatch_(refCast<const processorFvPatch>(p)),
45  sendRequest_(-1),
46  recvRequest_(-1)
47 {}
48 
49 
50 template<class Type>
52 (
53  const fvPatch& p,
55  const Field<Type>& f
56 )
57 :
58  coupledFvPatchField<Type>(p, iF, f),
59  procPatch_(refCast<const processorFvPatch>(p)),
60  sendRequest_(-1),
61  recvRequest_(-1)
62 {}
63 
64 
65 template<class Type>
67 (
68  const fvPatch& p,
70  const dictionary& dict
71 )
72 :
73  coupledFvPatchField<Type>(p, iF, dict, IOobjectOption::NO_READ),
74  procPatch_(refCast<const processorFvPatch>(p, dict)),
75  sendRequest_(-1),
76  recvRequest_(-1)
77 {
78  if (!isA<processorFvPatch>(p))
79  {
81  << "\n patch type '" << p.type()
82  << "' not constraint type '" << typeName << "'"
83  << "\n for patch " << p.name()
84  << " of field " << this->internalField().name()
85  << " in file " << this->internalField().objectPath()
86  << exit(FatalIOError);
87  }
88 
89  // Use 'value' supplied, or set to internal field
90  if (!this->readValueEntry(dict))
91  {
93  }
94 }
95 
96 
97 template<class Type>
99 (
100  const processorFvPatchField<Type>& ptf,
101  const fvPatch& p,
102  const DimensionedField<Type, volMesh>& iF,
103  const fvPatchFieldMapper& mapper
104 )
105 :
106  coupledFvPatchField<Type>(ptf, p, iF, mapper),
107  procPatch_(refCast<const processorFvPatch>(p)),
108  sendRequest_(-1),
109  recvRequest_(-1)
110 {
111  if (!isA<processorFvPatch>(this->patch()))
112  {
114  << "\n patch type '" << p.type()
115  << "' not constraint type '" << typeName << "'"
116  << "\n for patch " << p.name()
117  << " of field " << this->internalField().name()
118  << " in file " << this->internalField().objectPath()
119  << exit(FatalError);
120  }
121  if (debug && !ptf.all_ready())
122  {
124  << "Outstanding request(s) on patch " << procPatch_.name()
126  }
127 }
128 
129 
130 template<class Type>
132 (
133  const processorFvPatchField<Type>& ptf
134 )
135 :
136  processorLduInterfaceField(),
137  coupledFvPatchField<Type>(ptf),
138  procPatch_(refCast<const processorFvPatch>(ptf.patch())),
139  sendRequest_(-1),
140  recvRequest_(-1),
141  sendBuf_(std::move(ptf.sendBuf_)),
142  recvBuf_(std::move(ptf.recvBuf_)),
143  scalarSendBuf_(std::move(ptf.scalarSendBuf_)),
144  scalarRecvBuf_(std::move(ptf.scalarRecvBuf_))
145 {
146  if (debug && !ptf.all_ready())
147  {
149  << "Outstanding request(s) on patch " << procPatch_.name()
151  }
152 }
153 
154 
155 template<class Type>
157 (
158  const processorFvPatchField<Type>& ptf,
159  const DimensionedField<Type, volMesh>& iF
160 )
161 :
162  coupledFvPatchField<Type>(ptf, iF),
163  procPatch_(refCast<const processorFvPatch>(ptf.patch())),
164  sendRequest_(-1),
165  recvRequest_(-1)
166 {
167  if (debug && !ptf.all_ready())
168  {
170  << "Outstanding request(s) on patch " << procPatch_.name()
171  << abort(FatalError);
172  }
173 }
174 
175 
176 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
177 
178 template<class Type>
180 {
181  return UPstream::finishedRequestPair(recvRequest_, sendRequest_);
182 }
183 
184 
185 template<class Type>
187 {
188  const bool ok = UPstream::finishedRequest(recvRequest_);
189  if (ok)
190  {
191  recvRequest_ = -1;
192  if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
193  }
194  return ok;
195 }
196 
197 
198 template<class Type>
201 {
202  if (debug && !this->ready())
203  {
205  << "Outstanding request on patch " << procPatch_.name()
206  << abort(FatalError);
207  }
208  return *this;
209 }
210 
211 
212 template<class Type>
214 (
215  const Pstream::commsTypes commsType
216 )
217 {
218  if (UPstream::parRun())
219  {
220  this->patchInternalField(sendBuf_);
221 
222  if
223  (
225  && (std::is_integral<Type>::value || !UPstream::floatTransfer)
226  )
227  {
228  if (!is_contiguous<Type>::value)
229  {
231  << "Invalid for non-contiguous data types"
232  << abort(FatalError);
233  }
234 
235  // Receive straight into *this
236  this->resize_nocopy(sendBuf_.size());
237 
238  recvRequest_ = UPstream::nRequests();
240  (
242  procPatch_.neighbProcNo(),
243  this->data_bytes(),
244  this->size_bytes(),
245  procPatch_.tag(),
246  procPatch_.comm()
247  );
248 
249  sendRequest_ = UPstream::nRequests();
251  (
253  procPatch_.neighbProcNo(),
254  sendBuf_.cdata_bytes(),
255  sendBuf_.size_bytes(),
256  procPatch_.tag(),
257  procPatch_.comm()
258  );
259  }
260  else
261  {
262  procPatch_.compressedSend(commsType, sendBuf_);
263  }
264  }
265 }
266 
267 
268 template<class Type>
270 (
271  const Pstream::commsTypes commsType
272 )
273 {
274  if (UPstream::parRun())
275  {
276  if
277  (
279  && (std::is_integral<Type>::value || !UPstream::floatTransfer)
280  )
281  {
282  // Fast path: received into *this
283 
284  // Require receive data.
285  // Only update the send request state.
286  UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
287  if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
288  }
289  else
290  {
291  procPatch_.compressedReceive<Type>(commsType, *this);
292  }
293 
294  if (doTransform())
295  {
296  transform(*this, procPatch_.forwardT(), *this);
297  }
298  }
299 }
300 
301 
302 template<class Type>
305 (
306  const scalarField& deltaCoeffs
307 ) const
308 {
309  return deltaCoeffs*(*this - this->patchInternalField());
310 }
311 
312 
313 template<class Type>
315 (
317  const bool add,
318  const lduAddressing& lduAddr,
319  const label patchId,
320  const solveScalarField& psiInternal,
321  const scalarField&,
322  const direction,
323  const Pstream::commsTypes commsType
324 ) const
325 {
326  //this->patch().patchInternalField(psiInternal, scalarSendBuf_);
327 
328  const labelUList& faceCells = lduAddr.patchAddr(patchId);
329 
330  scalarSendBuf_.resize_nocopy(this->patch().size());
331  forAll(scalarSendBuf_, facei)
332  {
333  scalarSendBuf_[facei] = psiInternal[faceCells[facei]];
334  }
335 
336  if
337  (
340  )
341  {
342  // Fast path.
343  if (debug && !this->all_ready())
344  {
346  << "Outstanding request(s) on patch " << procPatch_.name()
347  << abort(FatalError);
348  }
349 
350  scalarRecvBuf_.resize_nocopy(scalarSendBuf_.size());
351 
352  recvRequest_ = UPstream::nRequests();
354  (
356  procPatch_.neighbProcNo(),
357  scalarRecvBuf_.data_bytes(),
358  scalarRecvBuf_.size_bytes(),
359  procPatch_.tag(),
360  procPatch_.comm()
361  );
362 
363  sendRequest_ = UPstream::nRequests();
365  (
367  procPatch_.neighbProcNo(),
368  scalarSendBuf_.cdata_bytes(),
369  scalarSendBuf_.size_bytes(),
370  procPatch_.tag(),
371  procPatch_.comm()
372  );
373  }
374  else
375  {
376  procPatch_.compressedSend(commsType, scalarSendBuf_);
377  }
379  this->updatedMatrix(false);
380 }
381 
382 
383 template<class Type>
385 (
386  solveScalarField& result,
387  const bool add,
388  const lduAddressing& lduAddr,
389  const label patchId,
390  const solveScalarField&,
391  const scalarField& coeffs,
392  const direction cmpt,
393  const Pstream::commsTypes commsType
394 ) const
395 {
396  if (this->updatedMatrix())
397  {
398  return;
399  }
400 
401  const labelUList& faceCells = lduAddr.patchAddr(patchId);
402 
403  if
404  (
407  )
408  {
409  // Fast path: consume straight from receive buffer
410 
411  // Require receive data.
412  // Only update the send request state.
413  UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
414  if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
415  }
416  else
417  {
418  scalarRecvBuf_.resize_nocopy(this->size());
419  procPatch_.compressedReceive(commsType, scalarRecvBuf_);
420  }
421 
422 
424  {
425  // Transform non-scalar data according to the transformation tensor
426  transformCoupleField(scalarRecvBuf_, cmpt);
427  }
428 
429  // Multiply the field by coefficients and add into the result
430  this->addToInternalField(result, !add, faceCells, coeffs, scalarRecvBuf_);
432  this->updatedMatrix(true);
433 }
434 
435 
436 template<class Type>
438 (
439  Field<Type>&,
440  const bool add,
441  const lduAddressing& lduAddr,
442  const label patchId,
443  const Field<Type>& psiInternal,
444  const scalarField&,
445  const Pstream::commsTypes commsType
446 ) const
447 {
448  sendBuf_.resize_nocopy(this->patch().size());
449 
450  const labelUList& faceCells = lduAddr.patchAddr(patchId);
451 
452  forAll(sendBuf_, facei)
453  {
454  sendBuf_[facei] = psiInternal[faceCells[facei]];
455  }
456 
457  if
458  (
460  && (std::is_integral<Type>::value || !UPstream::floatTransfer)
461  )
462  {
463  // Fast path.
464  if (debug && !this->all_ready())
465  {
467  << "Outstanding request(s) on patch " << procPatch_.name()
468  << abort(FatalError);
469  }
470 
471  recvBuf_.resize_nocopy(sendBuf_.size());
472 
473  recvRequest_ = UPstream::nRequests();
475  (
477  procPatch_.neighbProcNo(),
478  recvBuf_.data_bytes(),
479  recvBuf_.size_bytes(),
480  procPatch_.tag(),
481  procPatch_.comm()
482  );
483 
484  sendRequest_ = UPstream::nRequests();
486  (
488  procPatch_.neighbProcNo(),
489  sendBuf_.cdata_bytes(),
490  sendBuf_.size_bytes(),
491  procPatch_.tag(),
492  procPatch_.comm()
493  );
494  }
495  else
496  {
497  procPatch_.compressedSend(commsType, sendBuf_);
498  }
500  this->updatedMatrix(false);
501 }
502 
503 
504 template<class Type>
506 (
507  Field<Type>& result,
508  const bool add,
509  const lduAddressing& lduAddr,
510  const label patchId,
511  const Field<Type>&,
512  const scalarField& coeffs,
513  const Pstream::commsTypes commsType
514 ) const
515 {
516  if (this->updatedMatrix())
517  {
518  return;
519  }
520 
521  const labelUList& faceCells = lduAddr.patchAddr(patchId);
522 
523  if
524  (
526  && (std::is_integral<Type>::value || !UPstream::floatTransfer)
527  )
528  {
529  // Fast path: consume straight from receive buffer
530 
531  // Require receive data.
532  // Only update the send request state.
533  UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
534  if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
535  }
536  else
537  {
538  recvBuf_.resize_nocopy(this->size());
539  procPatch_.compressedReceive(commsType, recvBuf_);
540  }
541 
542 
543  // Transform according to the transformation tensor
544  transformCoupleField(recvBuf_);
545 
546  // Multiply the field by coefficients and add into the result
547  this->addToInternalField(result, !add, faceCells, coeffs, recvBuf_);
548 
549  this->updatedMatrix(true);
550 }
551 
552 
553 // ************************************************************************* //
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:364
label patchId(-1)
dictionary dict
uint8_t direction
Definition: direction.H:46
static label 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
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:72
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:598
static label nRequests() noexcept
Number of outstanding requests (on the internal list of requests)
Type & refCast(U &obj)
A dynamic_cast (for references). Generates a FatalError on failed casts and uses the virtual type() m...
Definition: typeInfo.H:159
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:1049
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)
Template functions to aid in the implementation of demand driven data.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:627
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...
Definition: areaFieldsFwd.H:42
const DimensionedField< Type, volMesh > & internalField() const noexcept
Return const-reference to the dimensioned internal field.
Definition: fvPatchField.H:662
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" : (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.
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...