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-2021 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
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 "processorFvPatch.H"
31#include "demandDrivenData.H"
32#include "transformField.H"
33
34// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
35
36template<class Type>
38(
39 const fvPatch& p,
41)
42:
43 coupledFvPatchField<Type>(p, iF),
44 procPatch_(refCast<const processorFvPatch>(p)),
45 sendBuf_(0),
46 receiveBuf_(0),
47 outstandingSendRequest_(-1),
48 outstandingRecvRequest_(-1),
49 scalarSendBuf_(0),
50 scalarReceiveBuf_(0)
51{}
52
53
54template<class Type>
56(
57 const fvPatch& p,
59 const Field<Type>& f
60)
61:
62 coupledFvPatchField<Type>(p, iF, f),
63 procPatch_(refCast<const processorFvPatch>(p)),
64 sendBuf_(0),
65 receiveBuf_(0),
66 outstandingSendRequest_(-1),
67 outstandingRecvRequest_(-1),
68 scalarSendBuf_(0),
69 scalarReceiveBuf_(0)
70{}
71
72
73template<class Type>
75(
76 const fvPatch& p,
78 const dictionary& dict
79)
80:
81 coupledFvPatchField<Type>(p, iF, dict, dict.found("value")),
82 procPatch_(refCast<const processorFvPatch>(p, dict)),
83 sendBuf_(0),
84 receiveBuf_(0),
85 outstandingSendRequest_(-1),
86 outstandingRecvRequest_(-1),
87 scalarSendBuf_(0),
88 scalarReceiveBuf_(0)
89{
90 if (!isA<processorFvPatch>(p))
91 {
93 << "\n patch type '" << p.type()
94 << "' not constraint type '" << typeName << "'"
95 << "\n for patch " << p.name()
96 << " of field " << this->internalField().name()
97 << " in file " << this->internalField().objectPath()
99 }
100
101 // If the value is not supplied set to the internal field
102 if (!dict.found("value"))
103 {
105 }
106}
107
108
109template<class Type>
111(
113 const fvPatch& p,
115 const fvPatchFieldMapper& mapper
116)
117:
118 coupledFvPatchField<Type>(ptf, p, iF, mapper),
119 procPatch_(refCast<const processorFvPatch>(p)),
120 sendBuf_(0),
121 receiveBuf_(0),
122 outstandingSendRequest_(-1),
123 outstandingRecvRequest_(-1),
124 scalarSendBuf_(0),
125 scalarReceiveBuf_(0)
126{
127 if (!isA<processorFvPatch>(this->patch()))
128 {
130 << "' not constraint type '" << typeName << "'"
131 << "\n for patch " << p.name()
132 << " of field " << this->internalField().name()
133 << " in file " << this->internalField().objectPath()
134 << exit(FatalError);
135 }
136 if (debug && !ptf.ready())
137 {
139 << "On patch " << procPatch_.name() << " outstanding request."
140 << abort(FatalError);
141 }
142}
143
144
145template<class Type>
147(
149)
150:
152 coupledFvPatchField<Type>(ptf),
153 procPatch_(refCast<const processorFvPatch>(ptf.patch())),
154 sendBuf_(std::move(ptf.sendBuf_)),
155 receiveBuf_(std::move(ptf.receiveBuf_)),
156 outstandingSendRequest_(-1),
157 outstandingRecvRequest_(-1),
158 scalarSendBuf_(std::move(ptf.scalarSendBuf_)),
159 scalarReceiveBuf_(std::move(ptf.scalarReceiveBuf_))
160{
161 if (debug && !ptf.ready())
162 {
164 << "On patch " << procPatch_.name() << " outstanding request."
165 << abort(FatalError);
166 }
167}
168
169
170template<class Type>
172(
175)
176:
177 coupledFvPatchField<Type>(ptf, iF),
178 procPatch_(refCast<const processorFvPatch>(ptf.patch())),
179 sendBuf_(0),
180 receiveBuf_(0),
181 outstandingSendRequest_(-1),
182 outstandingRecvRequest_(-1),
183 scalarSendBuf_(0),
184 scalarReceiveBuf_(0)
185{
186 if (debug && !ptf.ready())
187 {
189 << "On patch " << procPatch_.name() << " outstanding request."
190 << abort(FatalError);
191 }
192}
193
194
195// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
196
197template<class Type>
200{
201 if (debug && !this->ready())
202 {
204 << "On patch " << procPatch_.name()
205 << " outstanding request."
206 << abort(FatalError);
207 }
208 return *this;
209}
210
211
212template<class Type>
214(
215 const Pstream::commsTypes commsType
216)
217{
218 if (Pstream::parRun())
219 {
220 this->patchInternalField(sendBuf_);
221
222 if
223 (
226 )
227 {
229 {
231 << "Invalid for non-contiguous data types"
232 << abort(FatalError);
233 }
234
235 // Receive straight into *this
236 this->setSize(sendBuf_.size());
237 outstandingRecvRequest_ = UPstream::nRequests();
239 (
241 procPatch_.neighbProcNo(),
242 this->data_bytes(),
243 this->size_bytes(),
244 procPatch_.tag(),
245 procPatch_.comm()
246 );
247
248 outstandingSendRequest_ = 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
267template<class Type>
269(
270 const Pstream::commsTypes commsType
271)
272{
273 if (Pstream::parRun())
274 {
275 if
276 (
279 )
280 {
281 // Fast path. Received into *this
282
283 if
284 (
285 outstandingRecvRequest_ >= 0
286 && outstandingRecvRequest_ < Pstream::nRequests()
287 )
288 {
289 UPstream::waitRequest(outstandingRecvRequest_);
290 }
291 outstandingSendRequest_ = -1;
292 outstandingRecvRequest_ = -1;
293 }
294 else
295 {
296 procPatch_.compressedReceive<Type>(commsType, *this);
297 }
298
299 if (doTransform())
300 {
301 transform(*this, procPatch_.forwardT(), *this);
302 }
303 }
304}
305
306
307template<class Type>
310(
311 const scalarField& deltaCoeffs
312) const
313{
314 return deltaCoeffs*(*this - this->patchInternalField());
315}
316
317
318template<class Type>
320(
322 const bool add,
323 const lduAddressing& lduAddr,
324 const label patchId,
325 const solveScalarField& psiInternal,
326 const scalarField&,
327 const direction,
328 const Pstream::commsTypes commsType
329) const
330{
331 //this->patch().patchInternalField(psiInternal, scalarSendBuf_);
332
333 const labelUList& faceCells = lduAddr.patchAddr(patchId);
334
335 scalarSendBuf_.setSize(this->patch().size());
336 forAll(scalarSendBuf_, facei)
337 {
338 scalarSendBuf_[facei] = psiInternal[faceCells[facei]];
339 }
340
341 if
342 (
345 )
346 {
347 // Fast path.
348 if (debug && !this->ready())
349 {
351 << "On patch " << procPatch_.name()
352 << " outstanding request."
353 << abort(FatalError);
354 }
355
356
357 scalarReceiveBuf_.setSize(scalarSendBuf_.size());
358 outstandingRecvRequest_ = UPstream::nRequests();
360 (
362 procPatch_.neighbProcNo(),
363 scalarReceiveBuf_.data_bytes(),
364 scalarReceiveBuf_.size_bytes(),
365 procPatch_.tag(),
366 procPatch_.comm()
367 );
368
369 outstandingSendRequest_ = UPstream::nRequests();
371 (
373 procPatch_.neighbProcNo(),
374 scalarSendBuf_.cdata_bytes(),
375 scalarSendBuf_.size_bytes(),
376 procPatch_.tag(),
377 procPatch_.comm()
378 );
379 }
380 else
381 {
382 procPatch_.compressedSend(commsType, scalarSendBuf_);
383 }
384
385 const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = false;
386}
387
388
389template<class Type>
391(
392 solveScalarField& result,
393 const bool add,
394 const lduAddressing& lduAddr,
395 const label patchId,
396 const solveScalarField&,
397 const scalarField& coeffs,
398 const direction cmpt,
399 const Pstream::commsTypes commsType
400) const
401{
402 if (this->updatedMatrix())
403 {
404 return;
405 }
406
407 const labelUList& faceCells = lduAddr.patchAddr(patchId);
408
409 if
410 (
413 )
414 {
415 // Fast path.
416 if
417 (
418 outstandingRecvRequest_ >= 0
419 && outstandingRecvRequest_ < Pstream::nRequests()
420 )
421 {
422 UPstream::waitRequest(outstandingRecvRequest_);
423 }
424 // Recv finished so assume sending finished as well.
425 outstandingSendRequest_ = -1;
426 outstandingRecvRequest_ = -1;
427 // Consume straight from scalarReceiveBuf_
428
429 if (!std::is_arithmetic<Type>::value)
430 {
431 // Transform non-scalar data according to the transformation tensor
432 transformCoupleField(scalarReceiveBuf_, cmpt);
433 }
434
435 // Multiply the field by coefficients and add into the result
436 this->addToInternalField
437 (
438 result,
439 !add,
440 faceCells,
441 coeffs,
442 scalarReceiveBuf_
443 );
444 }
445 else
446 {
448 (
449 procPatch_.compressedReceive<solveScalar>
450 (
451 commsType,
452 this->size()
453 )()
454 );
455
456 if (!std::is_arithmetic<Type>::value)
457 {
458 // Transform non-scalar data according to the transformation tensor
459 transformCoupleField(pnf, cmpt);
460 }
461
462 // Multiply the field by coefficients and add into the result
463 this->addToInternalField(result, !add, faceCells, coeffs, pnf);
464 }
465
466 const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = true;
467}
468
469
470template<class Type>
472(
474 const bool add,
475 const lduAddressing& lduAddr,
476 const label patchId,
477 const Field<Type>& psiInternal,
478 const scalarField&,
479 const Pstream::commsTypes commsType
480) const
481{
482 sendBuf_.setSize(this->patch().size());
483
484 const labelUList& faceCells = lduAddr.patchAddr(patchId);
485
486 forAll(sendBuf_, facei)
487 {
488 sendBuf_[facei] = psiInternal[faceCells[facei]];
489 }
490
491 if
492 (
495 )
496 {
497 // Fast path.
498 if (debug && !this->ready())
499 {
501 << "On patch " << procPatch_.name()
502 << " outstanding request."
503 << abort(FatalError);
504 }
505
506
507 receiveBuf_.setSize(sendBuf_.size());
508 outstandingRecvRequest_ = UPstream::nRequests();
510 (
512 procPatch_.neighbProcNo(),
513 receiveBuf_.data_bytes(),
514 receiveBuf_.size_bytes(),
515 procPatch_.tag(),
516 procPatch_.comm()
517 );
518
519 outstandingSendRequest_ = UPstream::nRequests();
521 (
523 procPatch_.neighbProcNo(),
524 sendBuf_.cdata_bytes(),
525 sendBuf_.size_bytes(),
526 procPatch_.tag(),
527 procPatch_.comm()
528 );
529 }
530 else
531 {
532 procPatch_.compressedSend(commsType, sendBuf_);
533 }
534
535 const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = false;
536}
537
538
539template<class Type>
541(
542 Field<Type>& result,
543 const bool add,
544 const lduAddressing& lduAddr,
545 const label patchId,
546 const Field<Type>&,
547 const scalarField& coeffs,
548 const Pstream::commsTypes commsType
549) const
550{
551 if (this->updatedMatrix())
552 {
553 return;
554 }
555
556 const labelUList& faceCells = lduAddr.patchAddr(patchId);
557
558 if
559 (
562 )
563 {
564 // Fast path.
565 if
566 (
567 outstandingRecvRequest_ >= 0
568 && outstandingRecvRequest_ < Pstream::nRequests()
569 )
570 {
571 UPstream::waitRequest(outstandingRecvRequest_);
572 }
573 // Recv finished so assume sending finished as well.
574 outstandingSendRequest_ = -1;
575 outstandingRecvRequest_ = -1;
576
577 // Consume straight from receiveBuf_
578
579 // Transform according to the transformation tensor
580 transformCoupleField(receiveBuf_);
581
582 // Multiply the field by coefficients and add into the result
583 this->addToInternalField(result, !add, faceCells, coeffs, receiveBuf_);
584 }
585 else
586 {
587 Field<Type> pnf
588 (
589 procPatch_.compressedReceive<Type>(commsType, this->size())()
590 );
591
592 // Transform according to the transformation tensor
593 transformCoupleField(pnf);
594
595 // Multiply the field by coefficients and add into the result
596 this->addToInternalField(result, !add, faceCells, coeffs, pnf);
597 }
598
599 const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = true;
600}
601
602
603template<class Type>
605{
606 if
607 (
608 outstandingSendRequest_ >= 0
609 && outstandingSendRequest_ < Pstream::nRequests()
610 )
611 {
612 bool finished = UPstream::finishedRequest(outstandingSendRequest_);
613 if (!finished)
614 {
615 return false;
616 }
617 }
618 outstandingSendRequest_ = -1;
619
620 if
621 (
622 outstandingRecvRequest_ >= 0
623 && outstandingRecvRequest_ < Pstream::nRequests()
624 )
625 {
626 bool finished = UPstream::finishedRequest(outstandingRecvRequest_);
627 if (!finished)
628 {
629 return false;
630 }
631 }
632 outstandingRecvRequest_ = -1;
633
634 return true;
635}
636
637
638// ************************************************************************* //
bool found
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
static const char *const typeName
Typename for Field.
Definition: FieldBase.H:59
Generic templated field type.
Definition: Field.H:82
void evaluate()
Evaluate boundary conditions.
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:65
virtual bool read()
Re-read model coefficients if they have changed.
commsTypes
Types of communications.
Definition: UPstream.H:67
@ nonBlocking
"nonBlocking"
static bool floatTransfer
Definition: UPstream.H:275
static label nRequests()
Get number of outstanding requests.
Definition: UPstream.C:90
static bool finishedRequest(const label i)
Non-blocking comms: has request i finished?
Definition: UPstream.C:108
static void waitRequest(const label i)
Wait until request i has finished.
Definition: UPstream.C:104
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:433
virtual tmp< Field< Type > > snGrad() const
Return gradient at boundary.
Abstract base class for coupled patches.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Search for an entry (const access) with the given keyword.
Definition: dictionaryI.H:87
Smooth ATC in cells next to a set of patches supplied by type.
Definition: faceCells.H:59
virtual bool write()
Write the output fields.
A FieldMapper for finite-volume patch fields.
virtual tmp< Field< Type > > patchInternalField() const
Return internal field next to patch as patch field.
Definition: fvPatchField.C:237
virtual void operator=(const UList< Type > &)
Definition: fvPatchField.C:408
const DimensionedField< Type, volMesh > & internalField() const
Return dimensioned internal field reference.
Definition: fvPatchField.H:368
const fvPatch & patch() const
Return patch.
Definition: fvPatchField.H:362
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:71
virtual const word & name() const
Return name.
Definition: fvPatch.H:173
The class contains the addressing required by the lduMatrix: upper, lower and losort.
virtual const labelUList & patchAddr(const label patchNo) const =0
Return patch to internal addressing given patch number.
bool updatedMatrix() const
Whether matrix has been updated.
This boundary condition enables processor communication across patches.
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.
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.
virtual void initEvaluate(const Pstream::commsTypes commsType)
Initialise the evaluation of the patch field.
virtual bool ready() const
Is all data available.
virtual tmp< Field< Type > > patchNeighbourField() const
Return neighbour field given internal field.
Abstract base class for processor coupled interfaces.
A class for managing temporary objects.
Definition: tmp.H:65
volScalarField & p
Template functions to aid in the implementation of demand driven data.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
label patchId(-1)
To & refCast(From &r)
Reference type cast template function.
Definition: typeInfo.H:131
dimensionSet transform(const dimensionSet &ds)
Return the argument; transformations do not change the dimensions.
Definition: dimensionSet.C:536
void add(FieldField< Field1, typename typeOfSum< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
errorManip< error > abort(error &err)
Definition: errorManip.H:144
uint8_t direction
Definition: direction.H:56
IOerror FatalIOError
error FatalError
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
points setSize(newPointi)
labelList f(nPoints)
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
A template class to specify that a data type can be considered as being contiguous in memory.
Definition: contiguous.H:78
Spatial transformation functions for primitive fields.