processorFvPatchField.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "processorFvPatchField.H"
27 #include "processorFvPatch.H"
28 #include "demandDrivenData.H"
29 #include "transformField.H"
30 
31 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
32 
33 template<class Type>
35 (
36  const fvPatch& p,
38 )
39 :
41  procPatch_(refCast<const processorFvPatch>(p)),
42  sendBuf_(0),
43  receiveBuf_(0),
44  outstandingSendRequest_(-1),
45  outstandingRecvRequest_(-1),
46  scalarSendBuf_(0),
47  scalarReceiveBuf_(0)
48 {}
49 
50 
51 template<class Type>
53 (
54  const fvPatch& p,
56  const Field<Type>& f
57 )
58 :
60  procPatch_(refCast<const processorFvPatch>(p)),
61  sendBuf_(0),
62  receiveBuf_(0),
63  outstandingSendRequest_(-1),
64  outstandingRecvRequest_(-1),
65  scalarSendBuf_(0),
66  scalarReceiveBuf_(0)
67 {}
68 
69 
70 template<class Type>
72 (
73  const fvPatch& p,
75  const dictionary& dict
76 )
77 :
78  coupledFvPatchField<Type>(p, iF, dict, dict.found("value")),
79  procPatch_(refCast<const processorFvPatch>(p)),
80  sendBuf_(0),
81  receiveBuf_(0),
82  outstandingSendRequest_(-1),
83  outstandingRecvRequest_(-1),
84  scalarSendBuf_(0),
85  scalarReceiveBuf_(0)
86 {
87  if (!isA<processorFvPatch>(p))
88  {
90  (
91  dict
92  ) << "\n patch type '" << p.type()
93  << "' not constraint type '" << typeName << "'"
94  << "\n for patch " << p.name()
95  << " of field " << this->internalField().name()
96  << " in file " << this->internalField().objectPath()
97  << exit(FatalIOError);
98  }
99 
100  // If the value is not supplied set to the internal field
101  if (!dict.found("value"))
102  {
103  fvPatchField<Type>::operator=(this->patchInternalField());
104  }
105 }
106 
107 
108 template<class Type>
110 (
111  const processorFvPatchField<Type>& ptf,
112  const fvPatch& p,
114  const fvPatchFieldMapper& mapper
115 )
116 :
117  coupledFvPatchField<Type>(ptf, p, iF, mapper),
118  procPatch_(refCast<const processorFvPatch>(p)),
119  sendBuf_(0),
120  receiveBuf_(0),
121  outstandingSendRequest_(-1),
122  outstandingRecvRequest_(-1),
123  scalarSendBuf_(0),
124  scalarReceiveBuf_(0)
125 {
126  if (!isA<processorFvPatch>(this->patch()))
127  {
129  << "' not constraint type '" << typeName << "'"
130  << "\n for patch " << p.name()
131  << " of field " << this->internalField().name()
132  << " in file " << this->internalField().objectPath()
133  << exit(FatalIOError);
134  }
135  if (debug && !ptf.ready())
136  {
138  << "On patch " << procPatch_.name() << " outstanding request."
139  << abort(FatalError);
140  }
141 }
142 
143 
144 template<class Type>
146 (
147  const processorFvPatchField<Type>& ptf
148 )
149 :
152  procPatch_(refCast<const processorFvPatch>(ptf.patch())),
153  sendBuf_(ptf.sendBuf_.xfer()),
154  receiveBuf_(ptf.receiveBuf_.xfer()),
155  outstandingSendRequest_(-1),
156  outstandingRecvRequest_(-1),
157  scalarSendBuf_(ptf.scalarSendBuf_.xfer()),
158  scalarReceiveBuf_(ptf.scalarReceiveBuf_.xfer())
159 {
160  if (debug && !ptf.ready())
161  {
163  << "On patch " << procPatch_.name() << " outstanding request."
164  << abort(FatalError);
165  }
166 }
167 
168 
169 template<class Type>
171 (
172  const processorFvPatchField<Type>& ptf,
174 )
175 :
176  coupledFvPatchField<Type>(ptf, iF),
177  procPatch_(refCast<const processorFvPatch>(ptf.patch())),
178  sendBuf_(0),
179  receiveBuf_(0),
180  outstandingSendRequest_(-1),
181  outstandingRecvRequest_(-1),
182  scalarSendBuf_(0),
183  scalarReceiveBuf_(0)
184 {
185  if (debug && !ptf.ready())
186  {
188  << "On patch " << procPatch_.name() << " outstanding request."
189  << abort(FatalError);
190  }
191 }
192 
193 
194 // * * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * //
195 
196 template<class Type>
198 {}
199 
200 
201 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
202 
203 template<class Type>
206 {
207  if (debug && !this->ready())
208  {
210  << "On patch " << procPatch_.name()
211  << " outstanding request."
212  << abort(FatalError);
213  }
214  return *this;
215 }
216 
217 
218 template<class Type>
220 (
221  const Pstream::commsTypes commsType
222 )
223 {
224  if (Pstream::parRun())
225  {
226  this->patchInternalField(sendBuf_);
227 
228  if
229  (
230  commsType == Pstream::commsTypes::nonBlocking
231  && !Pstream::floatTransfer
232  )
233  {
234  // Fast path. Receive into *this
235  this->setSize(sendBuf_.size());
236  outstandingRecvRequest_ = UPstream::nRequests();
238  (
239  Pstream::commsTypes::nonBlocking,
240  procPatch_.neighbProcNo(),
241  reinterpret_cast<char*>(this->begin()),
242  this->byteSize(),
243  procPatch_.tag(),
244  procPatch_.comm()
245  );
246 
247  outstandingSendRequest_ = UPstream::nRequests();
249  (
250  Pstream::commsTypes::nonBlocking,
251  procPatch_.neighbProcNo(),
252  reinterpret_cast<const char*>(sendBuf_.begin()),
253  this->byteSize(),
254  procPatch_.tag(),
255  procPatch_.comm()
256  );
257  }
258  else
259  {
260  procPatch_.compressedSend(commsType, sendBuf_);
261  }
262  }
263 }
264 
265 
266 template<class Type>
268 (
269  const Pstream::commsTypes commsType
270 )
271 {
272  if (Pstream::parRun())
273  {
274  if
275  (
276  commsType == Pstream::commsTypes::nonBlocking
277  && !Pstream::floatTransfer
278  )
279  {
280  // Fast path. Received into *this
281 
282  if
283  (
284  outstandingRecvRequest_ >= 0
285  && outstandingRecvRequest_ < Pstream::nRequests()
286  )
287  {
288  UPstream::waitRequest(outstandingRecvRequest_);
289  }
290  outstandingSendRequest_ = -1;
291  outstandingRecvRequest_ = -1;
292  }
293  else
294  {
295  procPatch_.compressedReceive<Type>(commsType, *this);
296  }
297 
298  if (doTransform())
299  {
300  transform(*this, procPatch_.forwardT(), *this);
301  }
302  }
303 }
304 
305 
306 template<class Type>
309 (
310  const scalarField& deltaCoeffs
311 ) const
312 {
313  return deltaCoeffs*(*this - this->patchInternalField());
314 }
315 
316 
317 template<class Type>
319 (
320  scalarField&,
321  const scalarField& psiInternal,
322  const scalarField&,
323  const direction,
324  const Pstream::commsTypes commsType
325 ) const
326 {
327  this->patch().patchInternalField(psiInternal, scalarSendBuf_);
328 
329  if
330  (
331  commsType == Pstream::commsTypes::nonBlocking
332  && !Pstream::floatTransfer
333  )
334  {
335  // Fast path.
336  if (debug && !this->ready())
337  {
339  << "On patch " << procPatch_.name()
340  << " outstanding request."
341  << abort(FatalError);
342  }
343 
344 
345  scalarReceiveBuf_.setSize(scalarSendBuf_.size());
346  outstandingRecvRequest_ = UPstream::nRequests();
348  (
349  Pstream::commsTypes::nonBlocking,
350  procPatch_.neighbProcNo(),
351  reinterpret_cast<char*>(scalarReceiveBuf_.begin()),
352  scalarReceiveBuf_.byteSize(),
353  procPatch_.tag(),
354  procPatch_.comm()
355  );
356 
357  outstandingSendRequest_ = UPstream::nRequests();
359  (
360  Pstream::commsTypes::nonBlocking,
361  procPatch_.neighbProcNo(),
362  reinterpret_cast<const char*>(scalarSendBuf_.begin()),
363  scalarSendBuf_.byteSize(),
364  procPatch_.tag(),
365  procPatch_.comm()
366  );
367  }
368  else
369  {
370  procPatch_.compressedSend(commsType, scalarSendBuf_);
371  }
372 
373  const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = false;
374 }
375 
376 
377 template<class Type>
379 (
380  scalarField& result,
381  const scalarField&,
382  const scalarField& coeffs,
383  const direction cmpt,
384  const Pstream::commsTypes commsType
385 ) const
386 {
387  if (this->updatedMatrix())
388  {
389  return;
390  }
391 
392  const labelUList& faceCells = this->patch().faceCells();
393 
394  if
395  (
396  commsType == Pstream::commsTypes::nonBlocking
397  && !Pstream::floatTransfer
398  )
399  {
400  // Fast path.
401  if
402  (
403  outstandingRecvRequest_ >= 0
404  && outstandingRecvRequest_ < Pstream::nRequests()
405  )
406  {
407  UPstream::waitRequest(outstandingRecvRequest_);
408  }
409  // Recv finished so assume sending finished as well.
410  outstandingSendRequest_ = -1;
411  outstandingRecvRequest_ = -1;
412 
413  // Consume straight from scalarReceiveBuf_
414 
415  // Transform according to the transformation tensor
416  transformCoupleField(scalarReceiveBuf_, cmpt);
417 
418  // Multiply the field by coefficients and add into the result
419  forAll(faceCells, elemI)
420  {
421  result[faceCells[elemI]] -= coeffs[elemI]*scalarReceiveBuf_[elemI];
422  }
423  }
424  else
425  {
426  scalarField pnf
427  (
428  procPatch_.compressedReceive<scalar>(commsType, this->size())()
429  );
430 
431  // Transform according to the transformation tensor
432  transformCoupleField(pnf, cmpt);
433 
434  // Multiply the field by coefficients and add into the result
435  forAll(faceCells, elemI)
436  {
437  result[faceCells[elemI]] -= coeffs[elemI]*pnf[elemI];
438  }
439  }
440 
441  const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = true;
442 }
443 
444 
445 template<class Type>
447 (
448  Field<Type>&,
449  const Field<Type>& psiInternal,
450  const scalarField&,
451  const Pstream::commsTypes commsType
452 ) const
453 {
454  this->patch().patchInternalField(psiInternal, sendBuf_);
455 
456  if
457  (
458  commsType == Pstream::commsTypes::nonBlocking
459  && !Pstream::floatTransfer
460  )
461  {
462  // Fast path.
463  if (debug && !this->ready())
464  {
466  << "On patch " << procPatch_.name()
467  << " outstanding request."
468  << abort(FatalError);
469  }
470 
471 
472  receiveBuf_.setSize(sendBuf_.size());
473  outstandingRecvRequest_ = UPstream::nRequests();
475  (
476  Pstream::commsTypes::nonBlocking,
477  procPatch_.neighbProcNo(),
478  reinterpret_cast<char*>(receiveBuf_.begin()),
479  receiveBuf_.byteSize(),
480  procPatch_.tag(),
481  procPatch_.comm()
482  );
483 
484  outstandingSendRequest_ = UPstream::nRequests();
486  (
487  Pstream::commsTypes::nonBlocking,
488  procPatch_.neighbProcNo(),
489  reinterpret_cast<const char*>(sendBuf_.begin()),
490  sendBuf_.byteSize(),
491  procPatch_.tag(),
492  procPatch_.comm()
493  );
494  }
495  else
496  {
497  procPatch_.compressedSend(commsType, sendBuf_);
498  }
499 
500  const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = false;
501 }
502 
503 
504 template<class Type>
506 (
507  Field<Type>& result,
508  const Field<Type>&,
509  const scalarField& coeffs,
510  const Pstream::commsTypes commsType
511 ) const
512 {
513  if (this->updatedMatrix())
514  {
515  return;
516  }
517 
518  const labelUList& faceCells = this->patch().faceCells();
519 
520  if
521  (
522  commsType == Pstream::commsTypes::nonBlocking
523  && !Pstream::floatTransfer
524  )
525  {
526  // Fast path.
527  if
528  (
529  outstandingRecvRequest_ >= 0
530  && outstandingRecvRequest_ < Pstream::nRequests()
531  )
532  {
533  UPstream::waitRequest(outstandingRecvRequest_);
534  }
535  // Recv finished so assume sending finished as well.
536  outstandingSendRequest_ = -1;
537  outstandingRecvRequest_ = -1;
538 
539  // Consume straight from receiveBuf_
540 
541  // Transform according to the transformation tensor
542  transformCoupleField(receiveBuf_);
543 
544  // Multiply the field by coefficients and add into the result
545  forAll(faceCells, elemI)
546  {
547  result[faceCells[elemI]] -= coeffs[elemI]*receiveBuf_[elemI];
548  }
549  }
550  else
551  {
552  Field<Type> pnf
553  (
554  procPatch_.compressedReceive<Type>(commsType, this->size())()
555  );
556 
557  // Transform according to the transformation tensor
558  transformCoupleField(pnf);
559 
560  // Multiply the field by coefficients and add into the result
561  forAll(faceCells, elemI)
562  {
563  result[faceCells[elemI]] -= coeffs[elemI]*pnf[elemI];
564  }
565  }
566 
567  const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = true;
568 }
569 
570 
571 template<class Type>
573 {
574  if
575  (
576  outstandingSendRequest_ >= 0
577  && outstandingSendRequest_ < Pstream::nRequests()
578  )
579  {
580  bool finished = UPstream::finishedRequest(outstandingSendRequest_);
581  if (!finished)
582  {
583  return false;
584  }
585  }
586  outstandingSendRequest_ = -1;
587 
588  if
589  (
590  outstandingRecvRequest_ >= 0
591  && outstandingRecvRequest_ < Pstream::nRequests()
592  )
593  {
594  bool finished = UPstream::finishedRequest(outstandingRecvRequest_);
595  if (!finished)
596  {
597  return false;
598  }
599  }
600  outstandingRecvRequest_ = -1;
601 
602  return true;
603 }
604 
605 
606 // ************************************************************************* //
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
bool updatedMatrix() const
Whether matrix has been updated.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
virtual void initEvaluate(const Pstream::commsTypes commsType)
Initialise the evaluation of the patch field.
error FatalError
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:137
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
Xfer< List< T > > xfer()
Transfer contents to the Xfer container.
Definition: ListI.H:177
commsTypes
Types of communications.
Definition: UPstream.H:64
uint8_t direction
Definition: direction.H:45
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:61
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
Definition: fvPatchField.H:66
void read(Istream &, label &, const dictionary &)
In-place read with dictionary lookup.
virtual void initInterfaceMatrixUpdate(scalarField &result, const scalarField &psiInternal, const scalarField &coeffs, const direction cmpt, const Pstream::commsTypes commsType) const
Initialise neighbour matrix update.
points setSize(newPointi)
Spatial transformation functions for primitive fields.
void write(Ostream &, const label, const dictionary &)
Write with dictionary lookup.
Abstract base class for processor coupled interfaces.
Pre-declare SubField and related Field type.
Definition: Field.H:57
Foam::fvPatchFieldMapper.
virtual bool ready() const
Is all data available.
errorManip< error > abort(error &err)
Definition: errorManip.H:131
Abstract base class for coupled patches.
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:61
const fvPatch & patch() const
Return patch.
Definition: fvPatchField.H:340
virtual void evaluate(const Pstream::commsTypes commsType)
Evaluate the patch field.
labelList f(nPoints)
Template functions to aid in the implementation of demand driven data.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:331
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
virtual void updateInterfaceMatrix(scalarField &result, const scalarField &psiInternal, const scalarField &coeffs, const direction cmpt, const Pstream::commsTypes commsType) const
Update result field based on interface functionality.
This boundary condition enables processor communication across patches.
volScalarField & p
A class for managing temporary objects.
Definition: PtrList.H:53
virtual bool ready() const
Is all data available.
virtual tmp< Field< Type > > patchNeighbourField() const
Return neighbour field given internal field.
virtual tmp< Field< Type > > snGrad() const
Return patch-normal gradient.
processorFvPatchField(const fvPatch &, const DimensionedField< Type, volMesh > &)
Construct from patch and internal field.
dimensionSet transform(const dimensionSet &)
Definition: dimensionSet.C:477
IOerror FatalIOError