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 | Copyright (C) 2011-2013 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 // Construct by mapping given processorFvPatchField<Type>
71 template<class Type>
73 (
74  const processorFvPatchField<Type>& ptf,
75  const fvPatch& p,
77  const fvPatchFieldMapper& mapper
78 )
79 :
80  coupledFvPatchField<Type>(ptf, p, iF, mapper),
81  procPatch_(refCast<const processorFvPatch>(p)),
82  sendBuf_(0),
83  receiveBuf_(0),
84  outstandingSendRequest_(-1),
85  outstandingRecvRequest_(-1),
86  scalarSendBuf_(0),
87  scalarReceiveBuf_(0)
88 {
89  if (!isA<processorFvPatch>(this->patch()))
90  {
92  (
93  "processorFvPatchField<Type>::processorFvPatchField\n"
94  "(\n"
95  " const processorFvPatchField<Type>& ptf,\n"
96  " const fvPatch& p,\n"
97  " const DimensionedField<Type, volMesh>& iF,\n"
98  " const fvPatchFieldMapper& mapper\n"
99  ")\n"
100  ) << "\n patch type '" << p.type()
101  << "' not constraint type '" << typeName << "'"
102  << "\n for patch " << p.name()
103  << " of field " << this->dimensionedInternalField().name()
104  << " in file " << this->dimensionedInternalField().objectPath()
105  << exit(FatalIOError);
106  }
107  if (debug && !ptf.ready())
108  {
109  FatalErrorIn("processorFvPatchField<Type>::processorFvPatchField(..)")
110  << "On patch " << procPatch_.name() << " outstanding request."
111  << abort(FatalError);
112  }
113 }
114 
115 
116 template<class Type>
118 (
119  const fvPatch& p,
121  const dictionary& dict
122 )
123 :
125  procPatch_(refCast<const processorFvPatch>(p)),
126  sendBuf_(0),
127  receiveBuf_(0),
128  outstandingSendRequest_(-1),
129  outstandingRecvRequest_(-1),
130  scalarSendBuf_(0),
131  scalarReceiveBuf_(0)
132 {
133  if (!isA<processorFvPatch>(p))
134  {
136  (
137  "processorFvPatchField<Type>::processorFvPatchField\n"
138  "(\n"
139  " const fvPatch& p,\n"
140  " const Field<Type>& field,\n"
141  " const dictionary& dict\n"
142  ")\n",
143  dict
144  ) << "\n patch type '" << p.type()
145  << "' not constraint type '" << typeName << "'"
146  << "\n for patch " << p.name()
147  << " of field " << this->dimensionedInternalField().name()
148  << " in file " << this->dimensionedInternalField().objectPath()
149  << exit(FatalIOError);
150  }
151 }
152 
153 
154 template<class Type>
156 (
157  const processorFvPatchField<Type>& ptf
158 )
159 :
162  procPatch_(refCast<const processorFvPatch>(ptf.patch())),
163  sendBuf_(ptf.sendBuf_.xfer()),
164  receiveBuf_(ptf.receiveBuf_.xfer()),
165  outstandingSendRequest_(-1),
166  outstandingRecvRequest_(-1),
167  scalarSendBuf_(ptf.scalarSendBuf_.xfer()),
168  scalarReceiveBuf_(ptf.scalarReceiveBuf_.xfer())
169 {
170  if (debug && !ptf.ready())
171  {
172  FatalErrorIn("processorFvPatchField<Type>::processorFvPatchField(..)")
173  << "On patch " << procPatch_.name() << " outstanding request."
174  << abort(FatalError);
175  }
176 }
177 
178 
179 template<class Type>
181 (
182  const processorFvPatchField<Type>& ptf,
184 )
185 :
186  coupledFvPatchField<Type>(ptf, iF),
187  procPatch_(refCast<const processorFvPatch>(ptf.patch())),
188  sendBuf_(0),
189  receiveBuf_(0),
190  outstandingSendRequest_(-1),
191  outstandingRecvRequest_(-1),
192  scalarSendBuf_(0),
193  scalarReceiveBuf_(0)
194 {
195  if (debug && !ptf.ready())
196  {
197  FatalErrorIn("processorFvPatchField<Type>::processorFvPatchField(..)")
198  << "On patch " << procPatch_.name() << " outstanding request."
199  << abort(FatalError);
200  }
201 }
202 
203 
204 // * * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * //
205 
206 template<class Type>
208 {}
209 
210 
211 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
212 
213 template<class Type>
216 {
217  if (debug && !this->ready())
218  {
219  FatalErrorIn("processorFvPatchField<Type>::patchNeighbourField()")
220  << "On patch " << procPatch_.name()
221  << " outstanding request."
222  << abort(FatalError);
223  }
224  return *this;
225 }
226 
227 
228 template<class Type>
230 (
231  const Pstream::commsTypes commsType
232 )
233 {
234  if (Pstream::parRun())
235  {
236  this->patchInternalField(sendBuf_);
237 
238  if (commsType == Pstream::nonBlocking && !Pstream::floatTransfer)
239  {
240  // Fast path. Receive into *this
241  this->setSize(sendBuf_.size());
242  outstandingRecvRequest_ = UPstream::nRequests();
244  (
245  Pstream::nonBlocking,
246  procPatch_.neighbProcNo(),
247  reinterpret_cast<char*>(this->begin()),
248  this->byteSize(),
249  procPatch_.tag(),
250  procPatch_.comm()
251  );
252 
253  outstandingSendRequest_ = UPstream::nRequests();
255  (
256  Pstream::nonBlocking,
257  procPatch_.neighbProcNo(),
258  reinterpret_cast<const char*>(sendBuf_.begin()),
259  this->byteSize(),
260  procPatch_.tag(),
261  procPatch_.comm()
262  );
263  }
264  else
265  {
266  procPatch_.compressedSend(commsType, sendBuf_);
267  }
268  }
269 }
270 
271 
272 template<class Type>
274 (
275  const Pstream::commsTypes commsType
276 )
277 {
278  if (Pstream::parRun())
279  {
280  if (commsType == Pstream::nonBlocking && !Pstream::floatTransfer)
281  {
282  // Fast path. Received into *this
283 
284  if
285  (
286  outstandingRecvRequest_ >= 0
287  && outstandingRecvRequest_ < Pstream::nRequests()
288  )
289  {
290  UPstream::waitRequest(outstandingRecvRequest_);
291  }
292  outstandingSendRequest_ = -1;
293  outstandingRecvRequest_ = -1;
294  }
295  else
296  {
297  procPatch_.compressedReceive<Type>(commsType, *this);
298  }
299 
300  if (doTransform())
301  {
302  transform(*this, procPatch_.forwardT(), *this);
303  }
304  }
305 }
306 
307 
308 template<class Type>
311 (
312  const scalarField& deltaCoeffs
313 ) const
314 {
315  return deltaCoeffs*(*this - this->patchInternalField());
316 }
317 
318 
319 template<class Type>
321 (
322  scalarField&,
323  const scalarField& psiInternal,
324  const scalarField&,
325  const direction,
326  const Pstream::commsTypes commsType
327 ) const
328 {
329  this->patch().patchInternalField(psiInternal, scalarSendBuf_);
330 
331  if (commsType == Pstream::nonBlocking && !Pstream::floatTransfer)
332  {
333  // Fast path.
334  if (debug && !this->ready())
335  {
337  (
338  "processorFvPatchField<Type>::initInterfaceMatrixUpdate(..)"
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::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::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 (commsType == Pstream::nonBlocking && !Pstream::floatTransfer)
395  {
396  // Fast path.
397  if
398  (
399  outstandingRecvRequest_ >= 0
400  && outstandingRecvRequest_ < Pstream::nRequests()
401  )
402  {
403  UPstream::waitRequest(outstandingRecvRequest_);
404  }
405  // Recv finished so assume sending finished as well.
406  outstandingSendRequest_ = -1;
407  outstandingRecvRequest_ = -1;
408 
409  // Consume straight from scalarReceiveBuf_
410 
411  // Transform according to the transformation tensor
412  transformCoupleField(scalarReceiveBuf_, cmpt);
413 
414  // Multiply the field by coefficients and add into the result
415  forAll(faceCells, elemI)
416  {
417  result[faceCells[elemI]] -= coeffs[elemI]*scalarReceiveBuf_[elemI];
418  }
419  }
420  else
421  {
422  scalarField pnf
423  (
424  procPatch_.compressedReceive<scalar>(commsType, this->size())()
425  );
426 
427  // Transform according to the transformation tensor
428  transformCoupleField(pnf, cmpt);
429 
430  // Multiply the field by coefficients and add into the result
431  forAll(faceCells, elemI)
432  {
433  result[faceCells[elemI]] -= coeffs[elemI]*pnf[elemI];
434  }
435  }
436 
437  const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = true;
438 }
439 
440 
441 template<class Type>
443 (
444  Field<Type>&,
445  const Field<Type>& psiInternal,
446  const scalarField&,
447  const Pstream::commsTypes commsType
448 ) const
449 {
450  this->patch().patchInternalField(psiInternal, sendBuf_);
451 
452  if (commsType == Pstream::nonBlocking && !Pstream::floatTransfer)
453  {
454  // Fast path.
455  if (debug && !this->ready())
456  {
458  (
459  "processorFvPatchField<Type>::initInterfaceMatrixUpdate(..)"
460  ) << "On patch " << procPatch_.name()
461  << " outstanding request."
462  << abort(FatalError);
463  }
464 
465 
466  receiveBuf_.setSize(sendBuf_.size());
467  outstandingRecvRequest_ = UPstream::nRequests();
469  (
470  Pstream::nonBlocking,
471  procPatch_.neighbProcNo(),
472  reinterpret_cast<char*>(receiveBuf_.begin()),
473  receiveBuf_.byteSize(),
474  procPatch_.tag(),
475  procPatch_.comm()
476  );
477 
478  outstandingSendRequest_ = UPstream::nRequests();
480  (
481  Pstream::nonBlocking,
482  procPatch_.neighbProcNo(),
483  reinterpret_cast<const char*>(sendBuf_.begin()),
484  sendBuf_.byteSize(),
485  procPatch_.tag(),
486  procPatch_.comm()
487  );
488  }
489  else
490  {
491  procPatch_.compressedSend(commsType, sendBuf_);
492  }
493 
494  const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = false;
495 }
496 
497 
498 template<class Type>
500 (
501  Field<Type>& result,
502  const Field<Type>&,
503  const scalarField& coeffs,
504  const Pstream::commsTypes commsType
505 ) const
506 {
507  if (this->updatedMatrix())
508  {
509  return;
510  }
511 
512  const labelUList& faceCells = this->patch().faceCells();
513 
514  if (commsType == Pstream::nonBlocking && !Pstream::floatTransfer)
515  {
516  // Fast path.
517  if
518  (
519  outstandingRecvRequest_ >= 0
520  && outstandingRecvRequest_ < Pstream::nRequests()
521  )
522  {
523  UPstream::waitRequest(outstandingRecvRequest_);
524  }
525  // Recv finished so assume sending finished as well.
526  outstandingSendRequest_ = -1;
527  outstandingRecvRequest_ = -1;
528 
529  // Consume straight from receiveBuf_
530 
531  // Transform according to the transformation tensor
532  transformCoupleField(receiveBuf_);
533 
534  // Multiply the field by coefficients and add into the result
535  forAll(faceCells, elemI)
536  {
537  result[faceCells[elemI]] -= coeffs[elemI]*receiveBuf_[elemI];
538  }
539  }
540  else
541  {
542  Field<Type> pnf
543  (
544  procPatch_.compressedReceive<Type>(commsType, this->size())()
545  );
546 
547  // Transform according to the transformation tensor
548  transformCoupleField(pnf);
549 
550  // Multiply the field by coefficients and add into the result
551  forAll(faceCells, elemI)
552  {
553  result[faceCells[elemI]] -= coeffs[elemI]*pnf[elemI];
554  }
555  }
556 
557  const_cast<processorFvPatchField<Type>&>(*this).updatedMatrix() = true;
558 }
559 
560 
561 template<class Type>
563 {
564  if
565  (
566  outstandingSendRequest_ >= 0
567  && outstandingSendRequest_ < Pstream::nRequests()
568  )
569  {
570  bool finished = UPstream::finishedRequest(outstandingSendRequest_);
571  if (!finished)
572  {
573  return false;
574  }
575  }
576  outstandingSendRequest_ = -1;
577 
578  if
579  (
580  outstandingRecvRequest_ >= 0
581  && outstandingRecvRequest_ < Pstream::nRequests()
582  )
583  {
584  bool finished = UPstream::finishedRequest(outstandingRecvRequest_);
585  if (!finished)
586  {
587  return false;
588  }
589  }
590  outstandingRecvRequest_ = -1;
591 
592  return true;
593 }
594 
595 
596 // ************************************************************************* //
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.
unsigned char direction
Definition: direction.H:43
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
This boundary condition enables processor communication across patches.
labelList f(nPoints)
processorFvPatchField(const fvPatch &, const DimensionedField< Type, volMesh > &)
Construct from patch and internal field.
Xfer< List< T > > xfer()
Transfer contents to the Xfer container.
Definition: ListI.H:90
virtual tmp< Field< Type > > snGrad() const
Return patch-normal gradient.
virtual bool ready() const
Is all data available.
virtual void initInterfaceMatrixUpdate(scalarField &result, const scalarField &psiInternal, const scalarField &coeffs, const direction cmpt, const Pstream::commsTypes commsType) const
Initialise neighbour matrix update.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
Foam::fvPatchFieldMapper.
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:137
virtual void initEvaluate(const Pstream::commsTypes commsType)
Initialise the evaluation of the patch field.
runTime write()
dictionary dict
IOerror FatalIOError
Abstract base class for coupled patches.
volScalarField & p
Definition: createFields.H:51
dimensionSet transform(const dimensionSet &)
Definition: dimensionSet.C:465
bool updatedMatrix() const
Whether matrix has been updated.
commsTypes
Types of communications.
Definition: UPstream.H:64
#define forAll(list, i)
Definition: UList.H:421
Spatial transformation functions for primitive fields.
Template functions to aid in the implementation of demand driven data.
Pre-declare SubField and related Field type.
Definition: Field.H:57
errorManip< error > abort(error &err)
Definition: errorManip.H:131
virtual void evaluate(const Pstream::commsTypes commsType)
Evaluate the patch field.
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition: error.H:314
rDeltaT dimensionedInternalField()
points setSize(newPointi)
error FatalError
Abstract base class for processor coupled interfaces.
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:60
virtual tmp< Field< Type > > patchNeighbourField() const
Return neighbour field given internal field.
bool read(const char *, int32_t &)
Definition: int32IO.C:87
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:61
virtual bool ready() const
Is all data available.
const fvPatch & patch() const
Return patch.
Definition: fvPatchField.H:300
#define FatalIOErrorIn(functionName, ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:325
A class for managing temporary objects.
Definition: PtrList.H:118