Loading...
Searching...
No Matches
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-------------------------------------------------------------------------------
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\*---------------------------------------------------------------------------*/
30#include "transformField.H"
31
32// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
33
34template<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
48template<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
63template<class Type>
65(
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 {
89 FatalErrorInFunction
90 << "Outstanding request(s) on patch " << procPatch_.name()
91 << abort(FatalError);
92 }
93}
94
95
96template<class Type>
98(
99 const faPatch& p,
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{
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))
123 this->extrapolateInternal(); // Zero-gradient patch values
124 }
125}
126
127
128template<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 {
146 FatalErrorInFunction
147 << "Outstanding request(s) on patch " << procPatch_.name()
148 << abort(FatalError);
149 }
150}
151
152
153template<class Type>
155(
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 {
167 FatalErrorInFunction
168 << "Outstanding request(s) on patch " << procPatch_.name()
169 << abort(FatalError);
170 }
171}
172
173
174// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
175
176template<class Type>
177bool Foam::processorFaPatchField<Type>::all_ready() const
178{
179 return UPstream::finishedRequestPair(recvRequest_, sendRequest_);
180}
181
182
183template<class Type>
185{
186 const bool ok = UPstream::finishedRequest(recvRequest_);
187 if (ok)
188 {
189 recvRequest_ = -1;
190 if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
192 return ok;
193}
194
195
196template<class Type>
199{
200 if (debug && !this->ready())
201 {
203 << "Outstanding request on patch " << procPatch_.name()
205 }
206 return *this;
207}
208
209
210template<class Type>
212(
213 UList<Type>& pnf
214) const
215{
216 if (debug && !this->ready())
217 {
219 << "Outstanding request on patch " << procPatch_.name()
221 }
222 pnf.deepCopy(*this);
223}
224
225
226template<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
278template<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
308template<class Type>
310(
311 UList<Type>& result
312) const
313{
314 // Get patch internal field, store temporarily in result
315 this->patchInternalField(result);
316 const auto& pif = result;
317
318 const Field<Type>& pnf = *this;
319 const auto& deltaCoeffs = this->patch().deltaCoeffs();
320
321 const label len = result.size();
322
323 for (label i = 0; i < len; ++i)
325 result[i] = deltaCoeffs[i]*(pnf[i] - pif[i]);
326 }
327}
328
329
330template<class Type>
332{
333 // OR
334 // auto tfld = tmp<Field<Type>>::New(this->size());
335 // this->snGrad(static_cast<UList<Type>&>(tfld.ref()));
336 // return tfld;
337 return this->patch().deltaCoeffs()*(*this - this->patchInternalField());
338}
339
340
341template<class Type>
343(
344 solveScalarField& result,
345 const bool add,
346 const lduAddressing& lduAddr,
347 const label patchId,
348 const solveScalarField& psiInternal,
349 const scalarField& coeffs,
350 const direction,
351 const Pstream::commsTypes commsType
352) const
353{
354 const labelUList& faceCells = lduAddr.patchAddr(patchId);
355
356 {
357 scalarSendBuf_.resize_nocopy(faceCells.size());
358 scalarRecvBuf_.resize_nocopy(faceCells.size());
359
360 forAll(faceCells, i)
361 {
362 scalarSendBuf_[i] = psiInternal[faceCells[i]];
363 }
364 }
365
366 if (commsType == UPstream::commsTypes::nonBlocking)
367 {
368 // Fast path.
369 if (debug && !this->all_ready())
370 {
372 << "Outstanding request(s) on patch " << procPatch_.name()
373 << abort(FatalError);
374 }
375
376 recvRequest_ = UPstream::nRequests();
378 (
380 procPatch_.neighbProcNo(),
381 scalarRecvBuf_,
382 procPatch_.tag(),
383 procPatch_.comm()
384 );
385
386 sendRequest_ = UPstream::nRequests();
388 (
390 procPatch_.neighbProcNo(),
391 scalarSendBuf_,
392 procPatch_.tag(),
393 procPatch_.comm()
394 );
395 }
396 else
397 {
398 procPatch_.send(commsType, scalarSendBuf_);
400
401 this->updatedMatrix(false);
402}
403
404
405template<class Type>
407(
408 solveScalarField& result,
409 const bool add,
410 const lduAddressing& lduAddr,
411 const label patchId,
412 const solveScalarField&,
413 const scalarField& coeffs,
414 const direction cmpt,
415 const Pstream::commsTypes commsType
416) const
417{
418 if (this->updatedMatrix())
419 {
420 return;
421 }
422
423 const labelUList& faceCells = this->patch().edgeFaces();
424
425 if (commsType == UPstream::commsTypes::nonBlocking)
426 {
427 // Fast path: consume straight from receive buffer
428
429 // Require receive data.
430 // Only update the send request state.
431 UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
432 if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
433 }
434 else
435 {
436 scalarRecvBuf_.resize_nocopy(faceCells.size()); // In general a no-op
437 procPatch_.receive(commsType, scalarRecvBuf_);
438 }
439
440
442 {
443 // Transform non-scalar data according to the transformation tensor
444 transformCoupleField(scalarRecvBuf_, cmpt);
445 }
446
447 // Multiply the field by coefficients and add into the result
448 this->addToInternalField(result, !add, faceCells, coeffs, scalarRecvBuf_);
449
450 this->updatedMatrix(true);
451}
452
453
454template<class Type>
456(
457 Field<Type>& result,
458 const bool add,
459 const lduAddressing& lduAddr,
460 const label patchId,
461 const Field<Type>& psiInternal,
462 const scalarField& coeffs,
463 const Pstream::commsTypes commsType
464) const
465{
466 const labelUList& faceCells = lduAddr.patchAddr(patchId);
467
468 {
469 sendBuf_.resize_nocopy(faceCells.size());
470 recvBuf_.resize_nocopy(faceCells.size());
471
472 forAll(faceCells, i)
473 {
474 sendBuf_[i] = psiInternal[faceCells[i]];
475 }
476 }
477
478
479 if (commsType == UPstream::commsTypes::nonBlocking)
480 {
481 // Fast path.
482 if (debug && !this->all_ready())
483 {
485 << "Outstanding request(s) on patch " << procPatch_.name()
486 << abort(FatalError);
487 }
488
489 recvRequest_ = UPstream::nRequests();
491 (
493 procPatch_.neighbProcNo(),
494 recvBuf_,
495 procPatch_.tag(),
496 procPatch_.comm()
497 );
498
499 sendRequest_ = UPstream::nRequests();
501 (
503 procPatch_.neighbProcNo(),
504 sendBuf_,
505 procPatch_.tag(),
506 procPatch_.comm()
507 );
508 }
509 else
510 {
511 procPatch_.send(commsType, sendBuf_);
513
514 this->updatedMatrix(false);
515}
516
517
518template<class Type>
520(
521 Field<Type>& result,
522 const bool add,
523 const lduAddressing& lduAddr,
524 const label patchId,
525 const Field<Type>&,
526 const scalarField& coeffs,
527 const Pstream::commsTypes commsType
528) const
529{
530 if (this->updatedMatrix())
531 {
532 return;
533 }
534
535 const labelUList& faceCells = this->patch().edgeFaces();
536
537 if (commsType == UPstream::commsTypes::nonBlocking)
538 {
539 // Fast path: consume straight from receive buffer
540
541 // Require receive data.
542 // Only update the send request state.
543 UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
544 if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
545 }
546 else
547 {
548 recvBuf_.resize_nocopy(faceCells.size()); // In general a no-op
549 procPatch_.receive(commsType, recvBuf_);
550 }
551
552
553 // Transform according to the transformation tensor
554 transformCoupleField(recvBuf_);
555
556 // Multiply the field by coefficients and add into the result
557 this->addToInternalField(result, !add, faceCells, coeffs, recvBuf_);
558
559 this->updatedMatrix(true);
560}
561
562
563// ************************************************************************* //
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 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
Author Zeljko Tukovic, FMENA Hrvoje Jasak, Wikki Ltd.
coupledFaPatchField(const faPatch &, const DimensionedField< Type, areaMesh > &)
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
const faPatch & patch() const noexcept
Return the patch.
A FieldMapper for finite-area patch fields.
virtual tmp< Field< Type > > patchInternalField() const
Return internal field next to patch.
const DimensionedField< Type, areaMesh > & 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.
Finite area patch class. Used for 2-D non-Euclidian finite area method.
Definition faPatch.H:76
Smooth ATC in cells next to a set of patches supplied by type.
Definition faceCells.H:55
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
Author Zeljko Tukovic, FMENA Hrvoje Jasak, Wikki Ltd.
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 tmp< Field< Type > > snGrad() const
Return patch-normal gradient.
virtual void initEvaluate(const Pstream::commsTypes commsType)
Initialise the evaluation of the patch field.
processorFaPatchField(const faPatch &, const DimensionedField< Type, areaMesh > &)
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 given internal field.
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
const std::string patch
OpenFOAM patch number as a std::string.
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)
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 ...
bool isType(const U &obj)
Check if typeid of the object and Type are identical.
Definition typeInfo.H:112
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.