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-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 
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  UList<Type>& pnf
214 ) const
215 {
216  if (debug && !this->ready())
217  {
219  << "Outstanding request on patch " << procPatch_.name()
220  << abort(FatalError);
221  }
222  pnf.deepCopy(*this);
223 }
224 
225 
226 template<class Type>
228 (
229  const Pstream::commsTypes commsType
230 )
231 {
232  if (UPstream::parRun())
233  {
234  sendBuf_.resize_nocopy(this->patch().size());
235  this->patchInternalField(sendBuf_);
236 
237  if (commsType == UPstream::commsTypes::nonBlocking)
238  {
239  if constexpr (!is_contiguous_v<Type>)
240  {
242  << "Invalid for non-contiguous data types"
243  << abort(FatalError);
244  }
245 
246  // Receive straight into *this
247  Field<Type>& self = *this;
248  self.resize_nocopy(sendBuf_.size());
249 
250  recvRequest_ = UPstream::nRequests();
252  (
254  procPatch_.neighbProcNo(),
255  self,
256  procPatch_.tag(),
257  procPatch_.comm()
258  );
259 
260  sendRequest_ = UPstream::nRequests();
262  (
264  procPatch_.neighbProcNo(),
265  sendBuf_,
266  procPatch_.tag(),
267  procPatch_.comm()
268  );
269  }
270  else
271  {
272  procPatch_.send(commsType, sendBuf_);
273  }
274  }
275 }
276 
277 
278 template<class Type>
280 (
281  const Pstream::commsTypes commsType
282 )
283 {
284  if (UPstream::parRun())
285  {
286  if (commsType == UPstream::commsTypes::nonBlocking)
287  {
288  // Fast path. Received into *this
289 
290  // Require receive data.
291  // Only update the send request state.
292  UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
293  if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
294  }
295  else
296  {
297  procPatch_.receive<Type>(commsType, *this);
298  }
299 
300  if (doTransform())
301  {
302  transform(*this, procPatch_.forwardT(), *this);
303  }
304  }
305 }
306 
307 
308 template<class Type>
310 {
311  return this->patch().deltaCoeffs()*(*this - this->patchInternalField());
312 }
313 
314 
315 template<class Type>
317 (
318  solveScalarField& result,
319  const bool add,
320  const lduAddressing& lduAddr,
321  const label patchId,
322  const solveScalarField& psiInternal,
323  const scalarField& coeffs,
324  const direction,
325  const Pstream::commsTypes commsType
326 ) const
327 {
328  const labelUList& faceCells = lduAddr.patchAddr(patchId);
329 
330  {
331  scalarSendBuf_.resize_nocopy(faceCells.size());
332  scalarRecvBuf_.resize_nocopy(faceCells.size());
333 
334  forAll(faceCells, i)
335  {
336  scalarSendBuf_[i] = psiInternal[faceCells[i]];
337  }
338  }
339 
340  if (commsType == UPstream::commsTypes::nonBlocking)
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  recvRequest_ = UPstream::nRequests();
352  (
354  procPatch_.neighbProcNo(),
355  scalarRecvBuf_,
356  procPatch_.tag(),
357  procPatch_.comm()
358  );
359 
360  sendRequest_ = UPstream::nRequests();
362  (
364  procPatch_.neighbProcNo(),
365  scalarSendBuf_,
366  procPatch_.tag(),
367  procPatch_.comm()
368  );
369  }
370  else
371  {
372  procPatch_.send(commsType, scalarSendBuf_);
373  }
375  this->updatedMatrix(false);
376 }
377 
378 
379 template<class Type>
381 (
382  solveScalarField& result,
383  const bool add,
384  const lduAddressing& lduAddr,
385  const label patchId,
386  const solveScalarField&,
387  const scalarField& coeffs,
388  const direction cmpt,
389  const Pstream::commsTypes commsType
390 ) const
391 {
392  if (this->updatedMatrix())
393  {
394  return;
395  }
396 
397  const labelUList& faceCells = this->patch().edgeFaces();
398 
399  if (commsType == UPstream::commsTypes::nonBlocking)
400  {
401  // Fast path: consume straight from receive buffer
402 
403  // Require receive data.
404  // Only update the send request state.
405  UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
406  if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
407  }
408  else
409  {
410  scalarRecvBuf_.resize_nocopy(faceCells.size()); // In general a no-op
411  procPatch_.receive(commsType, scalarRecvBuf_);
412  }
413 
414 
416  {
417  // Transform non-scalar data according to the transformation tensor
418  transformCoupleField(scalarRecvBuf_, cmpt);
419  }
420 
421  // Multiply the field by coefficients and add into the result
422  this->addToInternalField(result, !add, faceCells, coeffs, scalarRecvBuf_);
424  this->updatedMatrix(true);
425 }
426 
427 
428 template<class Type>
430 (
431  Field<Type>& result,
432  const bool add,
433  const lduAddressing& lduAddr,
434  const label patchId,
435  const Field<Type>& psiInternal,
436  const scalarField& coeffs,
437  const Pstream::commsTypes commsType
438 ) const
439 {
440  const labelUList& faceCells = lduAddr.patchAddr(patchId);
441 
442  {
443  sendBuf_.resize_nocopy(faceCells.size());
444  recvBuf_.resize_nocopy(faceCells.size());
445 
446  forAll(faceCells, i)
447  {
448  sendBuf_[i] = psiInternal[faceCells[i]];
449  }
450  }
451 
452 
453  if (commsType == UPstream::commsTypes::nonBlocking)
454  {
455  // Fast path.
456  if (debug && !this->all_ready())
457  {
459  << "Outstanding request(s) on patch " << procPatch_.name()
460  << abort(FatalError);
461  }
462 
463  recvRequest_ = UPstream::nRequests();
465  (
467  procPatch_.neighbProcNo(),
468  recvBuf_,
469  procPatch_.tag(),
470  procPatch_.comm()
471  );
472 
473  sendRequest_ = UPstream::nRequests();
475  (
477  procPatch_.neighbProcNo(),
478  sendBuf_,
479  procPatch_.tag(),
480  procPatch_.comm()
481  );
482  }
483  else
484  {
485  procPatch_.send(commsType, sendBuf_);
486  }
488  this->updatedMatrix(false);
489 }
490 
491 
492 template<class Type>
494 (
495  Field<Type>& result,
496  const bool add,
497  const lduAddressing& lduAddr,
498  const label patchId,
499  const Field<Type>&,
500  const scalarField& coeffs,
501  const Pstream::commsTypes commsType
502 ) const
503 {
504  if (this->updatedMatrix())
505  {
506  return;
507  }
508 
509  const labelUList& faceCells = this->patch().edgeFaces();
510 
511  if (commsType == UPstream::commsTypes::nonBlocking)
512  {
513  // Fast path: consume straight from receive buffer
514 
515  // Require receive data.
516  // Only update the send request state.
517  UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
518  if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
519  }
520  else
521  {
522  recvBuf_.resize_nocopy(faceCells.size()); // In general a no-op
523  procPatch_.receive(commsType, recvBuf_);
524  }
525 
526 
527  // Transform according to the transformation tensor
528  transformCoupleField(recvBuf_);
529 
530  // Multiply the field by coefficients and add into the result
531  this->addToInternalField(result, !add, faceCells, coeffs, recvBuf_);
532 
533  this->updatedMatrix(true);
534 }
535 
536 
537 // ************************************************************************* //
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.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
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...
#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
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1586
const DimensionedField< Type, areaMesh > & internalField() const noexcept
Return const-reference to the dimensioned internal field.
Definition: faPatchField.H:650
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
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
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
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:87
Spatial transformation functions for primitive fields.
Generic templated field type.
Definition: Field.H:63
virtual const labelUList & patchAddr(const label patchNo) const =0
Return patch to internal addressing given patch number.
Author Zeljko Tukovic, FMENA Hrvoje Jasak, Wikki Ltd.
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
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)
refinementData transform(const tensor &, const refinementData val)
No-op rotational transform for base types.
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:629
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
const std::string patch
OpenFOAM patch number as a std::string.
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" (immediate) : (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
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.
virtual 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 ...