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 -------------------------------------------------------------------------------
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 
29 #include "processorFvPatchField.H"
30 #include "processorFvPatch.H"
31 #include "demandDrivenData.H"
32 #include "transformField.H"
33 
34 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
35 
36 template<class Type>
38 (
39  const fvPatch& p,
41 )
42 :
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 
54 template<class Type>
56 (
57  const fvPatch& p,
59  const Field<Type>& f
60 )
61 :
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 
73 template<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()
98  << exit(FatalIOError);
99  }
100 
101  // If the value is not supplied set to the internal field
102  if (!dict.found("value"))
103  {
104  fvPatchField<Type>::operator=(this->patchInternalField());
105  }
106 }
107 
108 
109 template<class Type>
111 (
112  const processorFvPatchField<Type>& ptf,
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 
145 template<class Type>
147 (
148  const processorFvPatchField<Type>& ptf
149 )
150 :
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 
170 template<class Type>
172 (
173  const processorFvPatchField<Type>& ptf,
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 
197 template<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 
212 template<class Type>
214 (
215  const Pstream::commsTypes commsType
216 )
217 {
218  if (Pstream::parRun())
219  {
220  this->patchInternalField(sendBuf_);
221 
222  if
223  (
224  commsType == Pstream::commsTypes::nonBlocking
225  && !Pstream::floatTransfer
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  (
240  Pstream::commsTypes::nonBlocking,
241  procPatch_.neighbProcNo(),
242  this->data_bytes(),
243  this->size_bytes(),
244  procPatch_.tag(),
245  procPatch_.comm()
246  );
247 
248  outstandingSendRequest_ = UPstream::nRequests();
250  (
251  Pstream::commsTypes::nonBlocking,
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 
267 template<class Type>
269 (
270  const Pstream::commsTypes commsType
271 )
272 {
273  if (Pstream::parRun())
274  {
275  if
276  (
277  commsType == Pstream::commsTypes::nonBlocking
278  && !Pstream::floatTransfer
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 
307 template<class Type>
310 (
311  const scalarField& deltaCoeffs
312 ) const
313 {
314  return deltaCoeffs*(*this - this->patchInternalField());
315 }
316 
317 
318 template<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  (
343  commsType == Pstream::commsTypes::nonBlocking
344  && !Pstream::floatTransfer
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  (
361  Pstream::commsTypes::nonBlocking,
362  procPatch_.neighbProcNo(),
363  scalarReceiveBuf_.data_bytes(),
364  scalarReceiveBuf_.size_bytes(),
365  procPatch_.tag(),
366  procPatch_.comm()
367  );
368 
369  outstandingSendRequest_ = UPstream::nRequests();
371  (
372  Pstream::commsTypes::nonBlocking,
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 
389 template<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  (
411  commsType == Pstream::commsTypes::nonBlocking
412  && !Pstream::floatTransfer
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  {
447  solveScalarField pnf
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 
470 template<class Type>
472 (
473  Field<Type>&,
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  (
493  commsType == Pstream::commsTypes::nonBlocking
494  && !Pstream::floatTransfer
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  (
511  Pstream::commsTypes::nonBlocking,
512  procPatch_.neighbProcNo(),
513  receiveBuf_.data_bytes(),
514  receiveBuf_.size_bytes(),
515  procPatch_.tag(),
516  procPatch_.comm()
517  );
518 
519  outstandingSendRequest_ = UPstream::nRequests();
521  (
522  Pstream::commsTypes::nonBlocking,
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 
539 template<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  (
560  commsType == Pstream::commsTypes::nonBlocking
561  && !Pstream::floatTransfer
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 
603 template<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 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::fvPatchField
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
Definition: volSurfaceMapping.H:51
Foam::lduAddressing
The class contains the addressing required by the lduMatrix: upper, lower and losort.
Definition: lduAddressing.H:114
setSize
points setSize(newPointi)
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::processorFvPatchField::updateInterfaceMatrix
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.
Definition: processorFvPatchField.C:391
processorFvPatch.H
processorFvPatchField.H
Foam::processorFvPatchField::processorFvPatchField
processorFvPatchField(const fvPatch &, const DimensionedField< Type, volMesh > &)
Construct from patch and internal field.
Definition: processorFvPatchField.C:38
Foam::processorFvPatchField
This boundary condition enables processor communication across patches.
Definition: processorFvPatchField.H:66
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:61
demandDrivenData.H
Template functions to aid in the implementation of demand driven data.
Foam::FatalIOError
IOerror FatalIOError
Foam::processorFvPatchField::initEvaluate
virtual void initEvaluate(const Pstream::commsTypes commsType)
Initialise the evaluation of the patch field.
Definition: processorFvPatchField.C:214
Foam::transform
dimensionSet transform(const dimensionSet &ds)
Return the argument; transformations do not change the dimensions.
Definition: dimensionSet.C:521
transformField.H
Spatial transformation functions for primitive fields.
Foam::processorFvPatchField::initInterfaceMatrixUpdate
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.
Definition: processorFvPatchField.C:320
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::blockMeshTools::read
void read(Istream &, label &val, const dictionary &)
In-place read with dictionary lookup.
Definition: blockMeshTools.C:57
Foam::Field
Generic templated field type.
Definition: Field.H:63
Foam::processorFvPatchField::evaluate
virtual void evaluate(const Pstream::commsTypes commsType)
Evaluate the patch field.
Definition: processorFvPatchField.C:269
Foam::fvPatch
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:65
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
Foam::lduInterfaceField::updatedMatrix
bool updatedMatrix() const
Whether matrix has been updated.
Definition: lduInterfaceField.H:119
Foam::add
void add(FieldField< Field1, typename typeOfSum< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
Definition: FieldFieldFunctions.C:939
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::UPstream::commsTypes
commsTypes
Types of communications.
Definition: UPstream.H:69
Foam::processorFvPatchField::patchNeighbourField
virtual tmp< Field< Type > > patchNeighbourField() const
Return neighbour field given internal field.
Definition: processorFvPatchField.C:199
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
f
labelList f(nPoints)
Foam::foamVersion::patch
const std::string patch
OpenFOAM patch number as a std::string.
Foam::coupledFvPatchField
Abstract base class for coupled patches.
Definition: coupledFvPatchField.H:57
Foam::processorFvPatchField::ready
virtual bool ready() const
Is all data available.
Definition: processorFvPatchField.C:604
Foam::UList< label >
Foam::direction
uint8_t direction
Definition: direction.H:52
Foam::vtk::write
void write(vtk::formatter &fmt, const Type &val, const label n=1)
Component-wise write of a value (N times)
Definition: foamVtkOutputTemplates.C:36
Foam::lduAddressing::patchAddr
virtual const labelUList & patchAddr(const label patchNo) const =0
Return patch to internal addressing given patch number.
FatalIOErrorInFunction
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
Foam::fvPatchFieldMapper
Foam::fvPatchFieldMapper.
Definition: fvPatchFieldMapper.H:47
patchId
label patchId(-1)
Foam::fvPatchField::patch
const fvPatch & patch() const
Return patch.
Definition: fvPatchField.H:357
Foam::coupledFvPatchField::snGrad
virtual tmp< Field< Type > > snGrad() const
Return patch-normal gradient.
Definition: coupledFvPatchField.H:151
Foam::processorLduInterfaceField
Abstract base class for processor coupled interfaces.
Definition: processorLduInterfaceField.H:52
Foam::faceCells
Smooth ATC in cells next to a set of patches supplied by type.
Definition: faceCells.H:56
Foam::DimensionedField
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
Definition: DimensionedField.H:54
Foam::is_contiguous
A template class to specify that a data type can be considered as being contiguous in memory.
Definition: contiguous.H:75