Loading...
Searching...
No Matches
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-------------------------------------------------------------------------------
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 "transformField.H"
32
33// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
34
35template<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
49template<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
64template<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{
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()
86 }
87
88 // Use 'value' supplied, or set to internal field
89 if (!this->readValueEntry(dict))
90 {
91 this->extrapolateInternal();
92 }
93}
94
95
96template<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 {
122 FatalErrorInFunction
123 << "Outstanding request(s) on patch " << procPatch_.name()
124 << abort(FatalError);
125 }
126}
127
128
129template<class Type>
131(
133)
134:
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 {
147 FatalErrorInFunction
148 << "Outstanding request(s) on patch " << procPatch_.name()
149 << abort(FatalError);
150 }
151}
152
153
154template<class Type>
156(
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 {
168 FatalErrorInFunction
169 << "Outstanding request(s) on patch " << procPatch_.name()
170 << abort(FatalError);
171 }
172}
173
174
175// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
176
177template<class Type>
178bool Foam::processorFvPatchField<Type>::all_ready() const
179{
180 return UPstream::finishedRequestPair(recvRequest_, sendRequest_);
181}
182
183
184template<class Type>
186{
187 const bool ok = UPstream::finishedRequest(recvRequest_);
188 if (ok)
189 {
190 recvRequest_ = -1;
191 if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
193 return ok;
194}
195
196
197template<class Type>
200{
201 if (debug && !this->ready())
202 {
204 << "Outstanding request on patch " << procPatch_.name()
206 }
207 return *this;
208}
209
210
211template<class Type>
213(
214 UList<Type>& pnf
215) const
216{
217 if (debug && !this->ready())
218 {
220 << "Outstanding request on patch " << procPatch_.name()
222 }
223 pnf.deepCopy(*this);
224}
225
226
227template<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
283template<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
317template<class Type>
319(
320 const scalarField& deltaCoeffs,
321 UList<Type>& result
322) const
323{
324 // Get patch internal field, store temporarily in result
325 this->patchInternalField(result);
326 const auto& pif = result;
327
328 const auto& pnf = *this;
329
330 const label len = result.size();
331
332 for (label i = 0; i < len; ++i)
333 {
334 result[i] = deltaCoeffs[i]*(pnf[i] - pif[i]);
335 }
336}
337
338
339template<class Type>
342(
343 const scalarField& deltaCoeffs
344) const
345{
346 // OR
347 // auto tfld = tmp<Field<Type>>::New(this->size());
348 // this->snGrad(deltaCoeffs, tfld.ref());
349 // return tfld;
350 return deltaCoeffs*(*this - this->patchInternalField());
351}
352
353
354template<class Type>
356(
358 const bool add,
359 const lduAddressing& lduAddr,
360 const label patchId,
361 const solveScalarField& psiInternal,
362 const scalarField&,
363 const direction,
364 const Pstream::commsTypes commsType
365) const
366{
367 const labelUList& faceCells = lduAddr.patchAddr(patchId);
368
369 {
370 scalarSendBuf_.resize_nocopy(faceCells.size());
371 scalarRecvBuf_.resize_nocopy(faceCells.size());
372
373 forAll(faceCells, i)
374 {
375 scalarSendBuf_[i] = psiInternal[faceCells[i]];
376 }
377 }
378
379 if
380 (
383 )
384 {
385 // Fast path.
386 if (debug && !this->all_ready())
387 {
389 << "Outstanding request(s) on patch " << procPatch_.name()
390 << abort(FatalError);
391 }
392
393 recvRequest_ = UPstream::nRequests();
395 (
397 procPatch_.neighbProcNo(),
398 scalarRecvBuf_,
399 procPatch_.tag(),
400 procPatch_.comm()
401 );
402
403 sendRequest_ = UPstream::nRequests();
405 (
407 procPatch_.neighbProcNo(),
408 scalarSendBuf_,
409 procPatch_.tag(),
410 procPatch_.comm()
411 );
412 }
413 else
414 {
415 procPatch_.compressedSend(commsType, scalarSendBuf_);
417
418 this->updatedMatrix(false);
419}
420
421
422template<class Type>
424(
425 solveScalarField& result,
426 const bool add,
427 const lduAddressing& lduAddr,
428 const label patchId,
429 const solveScalarField&,
430 const scalarField& coeffs,
431 const direction cmpt,
432 const Pstream::commsTypes commsType
433) const
434{
435 if (this->updatedMatrix())
436 {
437 return;
438 }
439
440 const labelUList& faceCells = lduAddr.patchAddr(patchId);
441
442 if
443 (
446 )
447 {
448 // Fast path: consume straight from receive buffer
449
450 // Require receive data.
451 // Only update the send request state.
452 UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
453 if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
454 }
455 else
456 {
457 scalarRecvBuf_.resize_nocopy(faceCells.size()); // In general a no-op
458 procPatch_.compressedReceive(commsType, scalarRecvBuf_);
459 }
460
461
463 {
464 // Transform non-scalar data according to the transformation tensor
465 transformCoupleField(scalarRecvBuf_, cmpt);
466 }
467
468 // Multiply the field by coefficients and add into the result
469 this->addToInternalField(result, !add, faceCells, coeffs, scalarRecvBuf_);
470
471 this->updatedMatrix(true);
472}
473
474
475template<class Type>
477(
479 const bool add,
480 const lduAddressing& lduAddr,
481 const label patchId,
482 const Field<Type>& psiInternal,
483 const scalarField&,
484 const Pstream::commsTypes commsType
485) const
486{
487 const labelUList& faceCells = lduAddr.patchAddr(patchId);
488
489 {
490 sendBuf_.resize_nocopy(faceCells.size());
491 recvBuf_.resize_nocopy(faceCells.size());
492
493 forAll(faceCells, i)
494 {
495 sendBuf_[i] = psiInternal[faceCells[i]];
496 }
497 }
498
499 if
500 (
502 && (std::is_integral_v<Type> || !UPstream::floatTransfer)
503 )
504 {
505 // Fast path.
506 if (debug && !this->all_ready())
507 {
509 << "Outstanding request(s) on patch " << procPatch_.name()
510 << abort(FatalError);
511 }
512
513 recvRequest_ = UPstream::nRequests();
515 (
517 procPatch_.neighbProcNo(),
518 recvBuf_,
519 procPatch_.tag(),
520 procPatch_.comm()
521 );
522
523 sendRequest_ = UPstream::nRequests();
525 (
527 procPatch_.neighbProcNo(),
528 sendBuf_,
529 procPatch_.tag(),
530 procPatch_.comm()
531 );
532 }
533 else
534 {
535 procPatch_.compressedSend(commsType, sendBuf_);
537
538 this->updatedMatrix(false);
539}
540
541
542template<class Type>
544(
545 Field<Type>& result,
546 const bool add,
547 const lduAddressing& lduAddr,
548 const label patchId,
549 const Field<Type>&,
550 const scalarField& coeffs,
551 const Pstream::commsTypes commsType
552) const
553{
554 if (this->updatedMatrix())
555 {
556 return;
557 }
558
559 const labelUList& faceCells = lduAddr.patchAddr(patchId);
560
561 if
562 (
564 && (std::is_integral_v<Type> || !UPstream::floatTransfer)
565 )
566 {
567 // Fast path: consume straight from receive buffer
568
569 // Require receive data.
570 // Only update the send request state.
571 UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
572 if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
573 }
574 else
575 {
576 recvBuf_.resize_nocopy(faceCells.size()); // In general a no-op
577 procPatch_.compressedReceive(commsType, recvBuf_);
578 }
579
580
581 // Transform according to the transformation tensor
582 transformCoupleField(recvBuf_);
583
584 // Multiply the field by coefficients and add into the result
585 this->addToInternalField(result, !add, faceCells, coeffs, recvBuf_);
586
587 this->updatedMatrix(true);
588}
589
590
591// ************************************************************************* //
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
Generic templated field type that is much like a Foam::List except that it is expected to hold numeri...
Definition Field.H:172
A simple container of IOobject preferences. Can also be used for general handling of read/no-read/rea...
const word & name() const noexcept
Return the object name.
Definition IOobjectI.H:205
fileName objectPath() const
The complete path + object name.
Definition IOobjectI.H:313
void resize_nocopy(const label len)
Adjust allocated size of list without necessarily.
Definition ListI.H:171
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.
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition UList.H:89
void deepCopy(const UList< T > &list)
Copy elements of the given UList. Sizes must match!
Definition UList.C:95
void size(const label n)
Definition UList.H:118
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.
static label nRequests() noexcept
Number of outstanding requests (on the internal list of requests).
commsTypes
Communications types.
Definition UPstream.H:81
@ nonBlocking
"nonBlocking" (immediate) : (MPI_Isend, MPI_Irecv)
Definition UPstream.H:84
static bool parRun(const bool on) noexcept
Set as parallel run on/off.
Definition UPstream.H:1669
static bool floatTransfer
Should compact transfer be used in which floats replace doubles reducing the bandwidth requirement at...
Definition UPstream.H:1024
static bool finishedRequestPair(label &req0, label &req1)
Non-blocking comms: have both requests finished? Corresponds to pair of MPI_Test().
static bool finishedRequest(const label i)
Non-blocking comms: has request i finished? Corresponds to MPI_Test().
static void waitRequest(const label i)
Wait until request i has finished. Corresponds to MPI_Wait().
static bool & parRun() noexcept
Test if this a parallel run.
Definition UPstream.H:1681
Abstract base class for coupled patches.
virtual tmp< Field< Type > > snGrad() const
Return patch-normal gradient.
coupledFvPatchField(const fvPatch &, const DimensionedField< Type, volMesh > &)
Construct from patch and internal field.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
Smooth ATC in cells next to a set of patches supplied by type.
Definition faceCells.H:55
const fvPatch & patch() const noexcept
Return the patch.
A FieldMapper for finite-volume patch fields.
virtual tmp< Field< Type > > patchInternalField() const
Return internal field next to patch.
const DimensionedField< Type, volMesh > & internalField() const noexcept
Return const-reference to the dimensioned internal field.
bool readValueEntry(const dictionary &dict, IOobjectOption::readOption readOpt=IOobjectOption::LAZY_READ)
Read the "value" entry into *this.
void extrapolateInternal()
Assign the patch field from the internal field.
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition fvPatch.H:71
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 noexcept
Whether matrix has been updated.
void addToInternalField(Field< Type > &result, const bool add, const labelUList &faceCells, const scalarField &coeffs, const Field< Type > &vals) const
Add/subtract weighted contributions to internal field.
A traits class, which is primarily used for primitives and vector-space.
Definition pTraits.H:64
This boundary condition enables processor communication across patches.
virtual bool doTransform() const
Does the patch field perform the transformation.
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.
processorFvPatchField(const fvPatch &, const DimensionedField< Type, volMesh > &)
Construct from patch and internal field.
virtual void evaluate(const Pstream::commsTypes commsType)
Evaluate the patch field.
virtual bool ready() const
Are all (receive) data available?
virtual tmp< Field< Type > > patchNeighbourField() const
Return neighbour field.
Abstract base class for processor coupled interfaces.
processorLduInterfaceField()=default
Default construct.
void transformCoupleField(Field< Type > &f) const
Transform given patch field.
A class for managing temporary objects.
Definition tmp.H:75
volScalarField & p
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition error.H:629
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
label patchId(-1)
Namespace for handling debugging switches.
Definition debug.C:45
Type & refCast(U &obj)
A dynamic_cast (for references) to Type reference.
Definition typeInfo.H:172
refinementData transform(const tensor &, const refinementData val)
No-op rotational transform for base types.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
const word GlobalIOList< Tuple2< scalar, vector > >::typeName("scalarVectorTable")
void add(DimensionedField< scalar, GeoMesh > &result, const dimensioned< scalar > &dt1, const DimensionedField< scalar, GeoMesh > &f2)
const Type * isA(const U &obj)
Attempt dynamic_cast to Type.
Definition typeInfo.H:87
errorManip< error > abort(error &err)
Definition errorManip.H:139
Field< solveScalar > solveScalarField
uint8_t direction
Definition direction.H:49
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
constexpr bool is_contiguous_v
The is_contiguous value of Type (after stripping of qualifiers).
Definition contiguous.H:77
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
UList< label > labelUList
A UList of labels.
Definition UList.H:75
labelList f(nPoints)
dict add("bounds", meshBb)
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299
Spatial transformation functions for primitive fields.