processorFaPatchField.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) 2016-2017 Wikki Ltd
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 
30 #include "transformField.H"
31 
32 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
33 
34 template<class Type>
36 (
37  const faPatch& p,
39 )
40 :
41  coupledFaPatchField<Type>(p, iF),
42  procPatch_(refCast<const processorFaPatch>(p)),
43  sendRequest_(-1),
44  recvRequest_(-1)
45 {}
46 
47 
48 template<class Type>
50 (
51  const faPatch& p,
53  const Field<Type>& f
54 )
55 :
56  coupledFaPatchField<Type>(p, iF, f),
57  procPatch_(refCast<const processorFaPatch>(p)),
58  sendRequest_(-1),
59  recvRequest_(-1)
60 {}
61 
62 
63 template<class Type>
65 (
66  const processorFaPatchField<Type>& ptf,
67  const faPatch& p,
69  const faPatchFieldMapper& mapper
70 )
71 :
72  coupledFaPatchField<Type>(ptf, p, iF, mapper),
73  procPatch_(refCast<const processorFaPatch>(p)),
74  sendRequest_(-1),
75  recvRequest_(-1)
76 {
77  if (!isType<processorFaPatch>(this->patch()))
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(FatalError);
86  }
87  if (debug && !ptf.all_ready())
88  {
90  << "Outstanding request(s) on patch " << procPatch_.name()
92  }
93 }
94 
95 
96 template<class Type>
98 (
99  const faPatch& p,
100  const DimensionedField<Type, areaMesh>& iF,
101  const dictionary& dict
102 )
103 :
104  coupledFaPatchField<Type>(p, iF, dict, IOobjectOption::NO_READ),
105  procPatch_(refCast<const processorFaPatch>(p, dict)),
106  sendRequest_(-1),
107  recvRequest_(-1)
108 {
109  if (!isType<processorFaPatch>(p))
110  {
112  << "\n patch type '" << p.type()
113  << "' not constraint type '" << typeName << "'"
114  << "\n for patch " << p.name()
115  << " of field " << this->internalField().name()
116  << " in file " << this->internalField().objectPath()
117  << exit(FatalIOError);
118  }
119 
120  // Use 'value' supplied, or set to internal field
121  if (!this->readValueEntry(dict))
122  {
123  this->extrapolateInternal(); // Zero-gradient patch values
124  }
125 }
126 
127 
128 template<class Type>
130 (
131  const processorFaPatchField<Type>& ptf
132 )
133 :
134  processorLduInterfaceField(),
135  coupledFaPatchField<Type>(ptf),
136  procPatch_(refCast<const processorFaPatch>(ptf.patch())),
137  sendRequest_(-1),
138  recvRequest_(-1),
139  sendBuf_(std::move(ptf.sendBuf_)),
140  recvBuf_(std::move(ptf.recvBuf_)),
141  scalarSendBuf_(std::move(ptf.scalarSendBuf_)),
142  scalarRecvBuf_(std::move(ptf.scalarRecvBuf_))
143 {
144  if (debug && !ptf.all_ready())
145  {
147  << "Outstanding request(s) on patch " << procPatch_.name()
149  }
150 }
151 
152 
153 template<class Type>
155 (
156  const processorFaPatchField<Type>& ptf,
157  const DimensionedField<Type, areaMesh>& iF
158 )
159 :
160  coupledFaPatchField<Type>(ptf, iF),
161  procPatch_(refCast<const processorFaPatch>(ptf.patch())),
162  sendRequest_(-1),
163  recvRequest_(-1)
164 {
165  if (debug && !ptf.all_ready())
166  {
168  << "Outstanding request(s) on patch " << procPatch_.name()
169  << abort(FatalError);
170  }
171 }
172 
173 
174 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
175 
176 template<class Type>
178 {
179  return UPstream::finishedRequestPair(recvRequest_, sendRequest_);
180 }
181 
182 
183 template<class Type>
185 {
186  const bool ok = UPstream::finishedRequest(recvRequest_);
187  if (ok)
188  {
189  recvRequest_ = -1;
190  if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
191  }
192  return ok;
193 }
194 
195 
196 template<class Type>
199 {
200  if (debug && !this->ready())
201  {
203  << "Outstanding request on patch " << procPatch_.name()
204  << abort(FatalError);
205  }
206  return *this;
207 }
208 
209 
210 template<class Type>
212 (
213  const Pstream::commsTypes commsType
214 )
215 {
216  if (UPstream::parRun())
217  {
218  this->patchInternalField(sendBuf_);
219 
220  if (commsType == UPstream::commsTypes::nonBlocking)
221  {
222  if (!is_contiguous<Type>::value)
223  {
225  << "Invalid for non-contiguous data types"
226  << abort(FatalError);
227  }
228 
229  // Receive straight into *this
230  this->resize_nocopy(sendBuf_.size());
231 
232  recvRequest_ = UPstream::nRequests();
234  (
236  procPatch_.neighbProcNo(),
237  this->data_bytes(),
238  this->size_bytes(),
239  procPatch_.tag(),
240  procPatch_.comm()
241  );
242 
243  sendRequest_ = UPstream::nRequests();
245  (
247  procPatch_.neighbProcNo(),
248  sendBuf_.cdata_bytes(),
249  sendBuf_.size_bytes(),
250  procPatch_.tag(),
251  procPatch_.comm()
252  );
253  }
254  else
255  {
256  procPatch_.send(commsType, sendBuf_);
257  }
258  }
259 }
260 
261 
262 template<class Type>
264 (
265  const Pstream::commsTypes commsType
266 )
267 {
268  if (UPstream::parRun())
269  {
270  if (commsType == UPstream::commsTypes::nonBlocking)
271  {
272  // Fast path. Received into *this
273 
274  // Require receive data.
275  // Only update the send request state.
276  UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
277  if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
278  }
279  else
280  {
281  procPatch_.receive<Type>(commsType, *this);
282  }
283 
284  if (doTransform())
285  {
286  transform(*this, procPatch_.forwardT(), *this);
287  }
288  }
289 }
290 
291 
292 template<class Type>
294 {
295  return this->patch().deltaCoeffs()*(*this - this->patchInternalField());
296 }
297 
298 
299 template<class Type>
301 (
302  solveScalarField& result,
303  const bool add,
304  const lduAddressing& lduAddr,
305  const label patchId,
306  const solveScalarField& psiInternal,
307  const scalarField& coeffs,
308  const direction,
309  const Pstream::commsTypes commsType
310 ) const
311 {
312  this->patch().patchInternalField(psiInternal, scalarSendBuf_);
313 
314  if (commsType == UPstream::commsTypes::nonBlocking)
315  {
316  // Fast path.
317  if (debug && !this->all_ready())
318  {
320  << "Outstanding request(s) on patch " << procPatch_.name()
321  << abort(FatalError);
322  }
323 
324  scalarRecvBuf_.resize_nocopy(scalarSendBuf_.size());
325 
326  recvRequest_ = UPstream::nRequests();
328  (
330  procPatch_.neighbProcNo(),
331  scalarRecvBuf_.data_bytes(),
332  scalarRecvBuf_.size_bytes(),
333  procPatch_.tag(),
334  procPatch_.comm()
335  );
336 
337  sendRequest_ = UPstream::nRequests();
339  (
341  procPatch_.neighbProcNo(),
342  scalarSendBuf_.cdata_bytes(),
343  scalarSendBuf_.size_bytes(),
344  procPatch_.tag(),
345  procPatch_.comm()
346  );
347  }
348  else
349  {
350  procPatch_.send(commsType, scalarSendBuf_);
351  }
353  this->updatedMatrix(false);
354 }
355 
356 
357 template<class Type>
359 (
360  solveScalarField& result,
361  const bool add,
362  const lduAddressing& lduAddr,
363  const label patchId,
364  const solveScalarField&,
365  const scalarField& coeffs,
366  const direction cmpt,
367  const Pstream::commsTypes commsType
368 ) const
369 {
370  if (this->updatedMatrix())
371  {
372  return;
373  }
374 
375  const labelUList& faceCells = this->patch().edgeFaces();
376 
377  if (commsType == UPstream::commsTypes::nonBlocking)
378  {
379  // Fast path: consume straight from receive buffer
380 
381  // Require receive data.
382  // Only update the send request state.
383  UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
384  if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
385  }
386  else
387  {
388  scalarRecvBuf_.resize_nocopy(this->size());
389  procPatch_.receive(commsType, scalarRecvBuf_);
390  }
391 
392 
394  {
395  // Transform non-scalar data according to the transformation tensor
396  transformCoupleField(scalarRecvBuf_, cmpt);
397  }
398 
399  // Multiply the field by coefficients and add into the result
400  this->addToInternalField(result, !add, faceCells, coeffs, scalarRecvBuf_);
402  this->updatedMatrix(true);
403 }
404 
405 
406 template<class Type>
408 (
409  Field<Type>& result,
410  const bool add,
411  const lduAddressing& lduAddr,
412  const label patchId,
413  const Field<Type>& psiInternal,
414  const scalarField& coeffs,
415  const Pstream::commsTypes commsType
416 ) const
417 {
418  this->patch().patchInternalField(psiInternal, sendBuf_);
419 
420  if (commsType == UPstream::commsTypes::nonBlocking)
421  {
422  // Fast path.
423  if (debug && !this->all_ready())
424  {
426  << "Outstanding request(s) on patch " << procPatch_.name()
427  << abort(FatalError);
428  }
429 
430  recvBuf_.resize_nocopy(sendBuf_.size());
431 
432  recvRequest_ = UPstream::nRequests();
434  (
436  procPatch_.neighbProcNo(),
437  recvBuf_.data_bytes(),
438  recvBuf_.size_bytes(),
439  procPatch_.tag(),
440  procPatch_.comm()
441  );
442 
443  sendRequest_ = UPstream::nRequests();
445  (
447  procPatch_.neighbProcNo(),
448  sendBuf_.cdata_bytes(),
449  sendBuf_.size_bytes(),
450  procPatch_.tag(),
451  procPatch_.comm()
452  );
453  }
454  else
455  {
456  procPatch_.send(commsType, sendBuf_);
457  }
459  this->updatedMatrix(false);
460 }
461 
462 
463 template<class Type>
465 (
466  Field<Type>& result,
467  const bool add,
468  const lduAddressing& lduAddr,
469  const label patchId,
470  const Field<Type>&,
471  const scalarField& coeffs,
472  const Pstream::commsTypes commsType
473 ) const
474 {
475  if (this->updatedMatrix())
476  {
477  return;
478  }
479 
480  const labelUList& faceCells = this->patch().edgeFaces();
481 
482  if (commsType == UPstream::commsTypes::nonBlocking)
483  {
484  // Fast path: consume straight from receive buffer
485 
486  // Require receive data.
487  // Only update the send request state.
488  UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
489  if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
490  }
491  else
492  {
493  recvBuf_.resize_nocopy(this->size());
494  procPatch_.receive(commsType, recvBuf_);
495  }
496 
497 
498  // Transform according to the transformation tensor
499  transformCoupleField(recvBuf_);
500 
501  // Multiply the field by coefficients and add into the result
502  this->addToInternalField(result, !add, faceCells, coeffs, recvBuf_);
503 
504  this->updatedMatrix(true);
505 }
506 
507 
508 // ************************************************************************* //
label patchId(-1)
dictionary dict
const faPatch & patch() const noexcept
Return the patch.
Definition: faPatchField.H:231
uint8_t direction
Definition: direction.H:46
virtual void initEvaluate(const Pstream::commsTypes commsType)
Initialise the evaluation of the patch field.
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
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...
#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
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1049
const DimensionedField< Type, areaMesh > & internalField() const noexcept
Return const-reference to the dimensioned internal field.
Definition: faPatchField.H:564
static bool finishedRequest(const label i)
Non-blocking comms: has request i finished? Corresponds to MPI_Test()
void extrapolateInternal()
Assign the patch field from the internal field.
Definition: faPatchField.C:60
UList< label > labelUList
A UList of labels.
Definition: UList.H:78
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.
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
Author Zeljko Tukovic, FMENA Hrvoje Jasak, Wikki Ltd.
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
virtual void evaluate(const Pstream::commsTypes commsType)
Evaluate the patch field.
const word & name() const noexcept
The patch name.
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.
Finite area patch class. Used for 2-D non-Euclidian finite area method.
Definition: faPatch.H:72
labelList f(nPoints)
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:627
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
Definition: areaFieldsFwd.H:42
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.
virtual tmp< Field< Type > > snGrad() const
Return patch-normal gradient.
::Foam::direction rank(const expressions::valueTypeCode) noexcept
The vector-space rank associated with given valueTypeCode.
Definition: exprTraits.C:70
"nonBlocking" : (MPI_Isend, MPI_Irecv)
The class contains the addressing required by the lduMatrix: upper, lower and losort.
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
A FieldMapper for finite-area patch fields.
static void waitRequest(const label i)
Wait until request i has finished. Corresponds to MPI_Wait()
processorFaPatchField(const faPatch &, const DimensionedField< Type, areaMesh > &)
Construct from patch and internal field.
virtual bool ready() const
Are all (receive) data available?
bool readValueEntry(const dictionary &dict, IOobjectOption::readOption readOpt=IOobjectOption::LAZY_READ)
Read the "value" entry into *this.
Definition: faPatchField.C:30
Author Zeljko Tukovic, FMENA Hrvoje Jasak, Wikki Ltd.
Processor patch.
tmp< Field< Type > > patchNeighbourField() const
Return neighbour field given internal field.
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...