mappedPatchFieldBase.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) 2013-2016 OpenFOAM Foundation
9  Copyright (C) 2018-2022 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 "mappedPatchFieldBase.H"
30 #include "mappedPatchBase.H"
31 #include "interpolationCell.H"
32 
33 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
34 
35 template<class Type>
37 (
38  const dictionary& dict,
39  const bool mandatory
40 )
41 {
42  if (mandatory)
43  {
44  return dict.get<Type>("average");
45  }
46 
47  return Zero;
48 }
49 
50 
51 template<class Type>
52 template<class T>
54 (
55  const objectRegistry& obr,
56  const word& region,
57  const word& patch,
58  const label myComm,
59  const labelListList& procToMap,
60  const word& fieldName,
61  const Field<T>& fld
62 ) const
63 {
64  // Store my data onto database
65 
66  const auto& procIDs = UPstream::procID(myComm);
67 
68  forAll(procToMap, ranki)
69  {
70  const labelList& map = procToMap[ranki];
71  const label proci = procIDs[ranki];
72 
73  if (map.size())
74  {
75  const Field<T> subFld(fld, map);
76 
77  auto& subObr = const_cast<objectRegistry&>
78  (
79  mappedPatchBase::subRegistry
80  (
81  obr,
82  mapper_.sendPath(proci)
83  / region
84  / patch
85  )
86  );
87 
89  {
90  Pout<< "*** STORING :"
91  << " field:" << fieldName
92  << " values:" << flatOutput(subFld)
93  << " as:" << subObr.objectPath() << endl;
94  }
95 
96  mappedPatchBase::storeField(subObr, fieldName, subFld);
97  }
98  }
99 }
100 
101 
102 template<class Type>
103 template<class T>
105 (
106  const bool allowUnset,
107  const objectRegistry& obr,
108  const word& region,
109  const word& patch,
110  const label myComm,
111  const labelListList& procToMap,
112  const word& fieldName,
113  Field<T>& fld
114 ) const
115 {
116  const auto& procIDs = UPstream::procID(myComm);
117 
118  bool ok = true;
119 
120  forAll(procToMap, ranki)
121  {
122  const labelList& map = procToMap[ranki];
123  const label proci = procIDs[ranki];
124 
125  if (map.size())
126  {
127  auto& subObr = const_cast<objectRegistry&>
128  (
129  mappedPatchBase::subRegistry
130  (
131  obr,
132  mapper_.receivePath(proci)
133  / region
134  / patch
135  )
136  );
137 
138  const IOField<T>* subFldPtr = subObr.getObjectPtr<IOField<T>>
139  (
140  fieldName
141  );
142  if (subFldPtr)
143  {
144  if (subFldPtr->size() != map.size())
145  {
146  // This is the dummy value inserted at start-up since the
147  // map is always non-zero size (checked above)
148  //Pout<< "*** RETRIEVED DUMMY :"
149  // << " field:" << fieldName
150  // << " subFldPtr:" << subFldPtr->size()
151  // << " map:" << map.size() << endl;
152 
153  ok = false;
154  }
155  else
156  {
157  UIndirectList<T>(fld, map) = *subFldPtr;
158 
160  {
161  Pout<< "*** RETRIEVED :"
162  << " field:" << fieldName
163  << " values:" << flatOutput(fld)
164  << " from:" << subObr.objectPath() << endl;
165  }
166  }
167  }
168  else if (allowUnset)
169  {
171  {
172  WarningInFunction << "Not found"
173  << " field:" << fieldName
174  << " in:" << subObr.objectPath() << endl;
175  }
176 
177  // Store dummy value so the database has something on it.
178  // Note that size 0 should never occur naturally so we can
179  // detect it if necessary.
180  const Field<T> dummyFld(0);
181 
182  mappedPatchBase::storeField(subObr, fieldName, dummyFld);
183 
184  ok = false;
185  }
186  else
187  {
188  // Not found. Make it fail
189  (void)subObr.lookupObject<IOField<T>>(fieldName);
190  ok = false;
191  }
192  }
193  }
194  return ok;
195 }
196 
197 
198 template<class Type>
199 template<class T>
201 (
202  const objectRegistry& obr,
203  const word& region,
204  const word& patch,
205  const labelListList& map,
206  const word& fieldName,
207  const Field<T>& fld
208 ) const
209 {
210  // Old code. Likely not quite correct...
211 
212  // Store my data onto database
213  const label nProcs = Pstream::nProcs(0); // comm_
214 
215  for (label domain = 0; domain < nProcs; domain++)
216  {
217  const labelList& constructMap = map[domain];
218  if (constructMap.size())
219  {
220  auto& subObr = const_cast<objectRegistry&>
221  (
222  mappedPatchBase::subRegistry
223  (
224  obr,
225  mapper_.receivePath(domain)
226  / region
227  / patch
228  )
229  );
230 
231  const Field<T> receiveFld(fld, constructMap);
232 
234  {
235  Pout<< "*** STORING INITIAL :"
236  << " field:" << fieldName << " values:"
237  << flatOutput(receiveFld)
238  << " from:" << flatOutput(fld)
239  << " constructMap:" << flatOutput(constructMap)
240  << " as:" << subObr.objectPath() << endl;
241  }
242 
243  mappedPatchBase::storeField(subObr, fieldName, receiveFld);
244  }
245  }
246 }
247 
248 
249 template<class Type>
250 template<class T>
252 (
253  const word& fieldName,
254  const label myComm,
255  const labelListList& subMap,
256  const label constructSize,
257  const labelListList& constructMap,
258  const labelListList& address,
259  const scalarListList& weights,
260  Field<T>& fld
261 ) const
262 {
263  storeField
264  (
265  patchField_.internalField().time(),
266  patchField_.patch().boundaryMesh().mesh().name(),
267  patchField_.patch().name(),
268  myComm,
269  subMap,
270  fieldName,
271  fld
272  );
273 
274  Field<T> work(constructSize);
275  const bool ok = retrieveField
276  (
277  true, // allow unset
278  patchField_.internalField().time(),
279  mapper_.sampleRegion(),
280  mapper_.samplePatch(),
281  myComm,
282  constructMap,
283  fieldName,
284  work
285  );
286 
287  if (ok)
288  {
289  // Do interpolation
290 
291  fld.setSize(address.size());
292  fld = Zero;
293 
294  const plusEqOp<T> cop;
295  const multiplyWeightedOp<T, plusEqOp<T>> mop(cop);
296 
297  forAll(address, facei)
298  {
299  const labelList& slots = address[facei];
300  const scalarList& w = weights[facei];
301 
302  forAll(slots, i)
303  {
304  mop(fld[facei], facei, work[slots[i]], w[i]);
305  }
306  }
307  }
308  else
309  {
310  // Leave fld intact
311  }
312 
313  return ok;
314 }
315 
316 
317 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
318 
319 template<class Type>
321 (
322  const mappedPatchBase& mapper,
323  const fvPatchField<Type>& patchField,
324  const word& fieldName,
325  const bool setAverage,
326  const Type average,
327  const word& interpolationScheme
328 )
329 :
330  mapper_(mapper),
331  patchField_(patchField),
332  fieldName_(fieldName),
333  setAverage_(setAverage),
334  average_(average),
335  interpolationScheme_(interpolationScheme)
336 {}
337 
338 
339 template<class Type>
341 (
342  const mappedPatchBase& mapper,
343  const fvPatchField<Type>& patchField,
344  const dictionary& dict
345 )
346 :
347  mapper_(mapper),
348  patchField_(patchField),
349  fieldName_
350  (
351  dict.template getOrDefault<word>
352  (
353  "field",
354  patchField_.internalField().name()
355  )
356  ),
357  setAverage_(dict.getOrDefault("setAverage", false)),
358  average_(getAverage(dict, setAverage_)),
359  interpolationScheme_(interpolationCell<Type>::typeName)
360 {
361  if
362  (
363  mapper_.sampleDatabase()
364  && (
365  mapper_.mode() != mappedPatchBase::NEARESTPATCHFACE
366  && mapper_.mode() != mappedPatchBase::NEARESTPATCHFACEAMI
367  )
368  )
369  {
371  << "Mapping using the database only supported for "
372  << "sampleModes "
373  << mappedPatchBase::sampleModeNames_
374  [
375  mappedPatchBase::NEARESTPATCHFACE
376  ]
377  << " and "
378  << mappedPatchBase::sampleModeNames_
379  [
380  mappedPatchBase::NEARESTPATCHFACEAMI
381  ]
382  << exit(FatalError);
383  }
384 
385  if (mapper_.mode() == mappedPatchBase::NEARESTCELL)
386  {
387  dict.readEntry("interpolationScheme", interpolationScheme_);
388  }
389 
390  // Note: in database mode derived boundary conditions need to initialise
391  // fields
392 }
393 
394 
395 template<class Type>
397 (
398  const mappedPatchBase& mapper,
399  const fvPatchField<Type>& patchField,
400  const dictionary& dict,
401  const Field<Type>& fld
402 )
403 :
404  mappedPatchFieldBase<Type>::mappedPatchFieldBase(mapper, patchField, dict)
405 {
406  if (mapper_.sampleDatabase())
407  {
408  if (mapper_.mode() == mappedPatchBase::NEARESTPATCHFACE)
409  {
410  // Store my data on receive buffers so we have some initial data
411  initRetrieveField
412  (
413  patchField_.internalField().time(),
414  //patchField_.patch().boundaryMesh().mesh().name(),
415  mapper_.sampleRegion(),
416  //patchField_.patch().name(),
417  mapper_.samplePatch(),
418  mapper_.map().constructMap(),
419  patchField_.internalField().name(),
420  patchField_
421  );
422  }
423  else if (mapper_.mode() == mappedPatchBase::NEARESTPATCHFACEAMI)
424  {
425  // Depend on fall-back (sorting dummy field) in retrieveField
426  // since it would be too hard to determine the field that gives
427  // the wanted result after interpolation
428  }
429  }
430 }
431 
432 
433 template<class Type>
435 (
436  const mappedPatchBase& mapper,
437  const fvPatchField<Type>& patchField
438 )
439 :
440  mapper_(mapper),
441  patchField_(patchField),
442  fieldName_(patchField_.internalField().name()),
443  setAverage_(false),
444  average_(Zero),
445  interpolationScheme_(interpolationCell<Type>::typeName)
446 {}
447 
448 
449 template<class Type>
451 (
452  const mappedPatchFieldBase<Type>& mapper
453 )
454 :
455  mapper_(mapper.mapper_),
456  patchField_(mapper.patchField_),
457  fieldName_(mapper.fieldName_),
458  setAverage_(mapper.setAverage_),
459  average_(mapper.average_),
460  interpolationScheme_(mapper.interpolationScheme_)
461 {}
462 
463 
464 template<class Type>
466 (
467  const mappedPatchBase& mapper,
468  const fvPatchField<Type>& patchField,
469  const mappedPatchFieldBase<Type>& base
470 )
471 :
472  mapper_(mapper),
473  patchField_(patchField),
474  fieldName_(base.fieldName_),
475  setAverage_(base.setAverage_),
476  average_(base.average_),
477  interpolationScheme_(base.interpolationScheme_)
478 {}
480 
481 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
482 
483 template<class Type>
484 template<class Type2>
487 {
489 
490  if (mapper_.sameRegion())
491  {
492  if (fieldName == patchField_.internalField().name())
493  {
494  // Optimisation: bypass field lookup
495  return
496  dynamic_cast<const fieldType&>
497  (
498  patchField_.internalField()
499  );
500  }
501  else
502  {
503  const fvMesh& thisMesh = patchField_.patch().boundaryMesh().mesh();
504  return thisMesh.template lookupObject<fieldType>(fieldName);
505  }
506  }
507 
508  const fvMesh& nbrMesh = refCast<const fvMesh>(mapper_.sampleMesh());
509  return nbrMesh.template lookupObject<fieldType>(fieldName);
510 }
511 
512 
513 template<class Type>
516 {
517  return sampleField<Type>(fieldName_);
518 }
519 
520 
521 template<class Type>
522 template<class T>
524 (
525  const word& fieldName,
526  Field<T>& fld
527 ) const
528 {
529  if (mapper_.sampleDatabase())
530  {
531  const label myComm = mapper_.getCommunicator(); // Get or create
532 
533  if (mapper_.mode() != mappedPatchBase::NEARESTPATCHFACEAMI)
534  {
535  // Store my data on send buffers
536  storeField
537  (
538  patchField_.internalField().time(),
539  patchField_.patch().boundaryMesh().mesh().name(),
540  patchField_.patch().name(),
541  myComm,
542  mapper_.map().subMap(),
543  fieldName,
544  fld
545  );
546  // Construct my data from receive buffers
547  fld.setSize(mapper_.map().constructSize());
548  retrieveField
549  (
550  true, // allow unset
551  patchField_.internalField().time(),
552  mapper_.sampleRegion(),
553  mapper_.samplePatch(),
554  myComm,
555  mapper_.map().constructMap(),
556  fieldName,
557  fld
558  );
559  }
560  else
561  {
562  const AMIPatchToPatchInterpolation& AMI = mapper_.AMI();
563 
564  // The AMI does an interpolateToSource/ToTarget. This is a
565  // mapDistribute (so using subMap/constructMap) and then a
566  // weighted sum. We'll store the sent data as before and
567  // do the weighted summation after the retrieveField
568 
569  if (mapper_.masterWorld())
570  {
571  // See AMIInterpolation::interpolateToSource. Use tgtMap,
572  // srcAddress, srcWeights
573  storeAndRetrieveField
574  (
575  fieldName,
576  myComm,
577  AMI.srcMap().subMap(),
578  AMI.tgtMap().constructSize(),
579  AMI.tgtMap().constructMap(),
580  AMI.srcAddress(),
581  AMI.srcWeights(),
582  fld
583  );
584  }
585  else
586  {
587  // See AMIInterpolation::interpolateToTarget.
588  // Use srcMap, tgtAddress, tgtWeights
589  storeAndRetrieveField
590  (
591  fieldName,
592  myComm,
593  AMI.tgtMap().subMap(),
594  AMI.srcMap().constructSize(),
595  AMI.srcMap().constructMap(),
596  AMI.tgtAddress(),
597  AMI.tgtWeights(),
598  fld
599  );
600  }
601  }
602  }
603  else
604  {
605  mapper_.distribute(fld);
606  }
607 }
608 
609 
610 template<class Type>
611 //template<class T>
614 (
615 // const GeometricField<T, fvPatchField, volMesh>& fld
616 ) const
617 {
619 
620  // Since we're inside initEvaluate/evaluate there might be processor
621  // comms underway. Change the tag we use.
622  const int oldTag = UPstream::incrMsgType();
623 
624  const fvMesh& thisMesh = patchField_.patch().boundaryMesh().mesh();
625 
626  // Result of obtaining remote values
627  auto tnewValues = tmp<Field<Type>>::New();
628  auto& newValues = tnewValues.ref();
629 
630  switch (mapper_.mode())
631  {
632  case mappedPatchBase::NEARESTCELL:
633  {
634  const fieldType& fld = sampleField();
635  const mapDistribute& distMap = mapper_.map();
636 
637  if (interpolationScheme_ != interpolationCell<Type>::typeName)
638  {
639  if (!mapper_.sameWorld() || mapper_.sampleDatabase())
640  {
642  << "Interpolating cell values from different world"
643  << " or database currently not supported"
644  << exit(FatalError);
645  }
646 
647  const fvMesh& nbrMesh =
648  refCast<const fvMesh>(mapper_.sampleMesh());
649 
650  // Send back sample points to the processor that holds the cell
651  vectorField samples(mapper_.samplePoints());
652 
653  distMap.reverseDistribute
654  (
655  (
656  mapper_.sameRegion()
657  ? thisMesh.nCells()
658  : nbrMesh.nCells()
659  ),
660  point::max,
661  samples
662  );
663 
664  auto interpolator =
666  (
667  interpolationScheme_,
668  fld
669  );
670 
671  const auto& interp = *interpolator;
672 
673  newValues.setSize(samples.size(), pTraits<Type>::max);
674  forAll(samples, celli)
675  {
676  if (samples[celli] != point::max)
677  {
678  newValues[celli] = interp.interpolate
679  (
680  samples[celli],
681  celli
682  );
683  }
684  }
685  }
686  else
687  {
688  newValues = fld;
689  }
690 
691  distribute(fieldName_, newValues);
692 
693  break;
694  }
695  case mappedPatchBase::NEARESTPATCHFACE:
696  case mappedPatchBase::NEARESTPATCHFACEAMI:
697  {
698  if (mapper_.sameWorld())
699  {
700  const fvMesh& nbrMesh =
701  refCast<const fvMesh>(mapper_.sampleMesh());
702  const fieldType& fld = sampleField();
703 
704  const label nbrPatchID =
705  nbrMesh.boundaryMesh().findPatchID(mapper_.samplePatch());
706 
707  if (nbrPatchID < 0)
708  {
710  << "Unable to find sample patch " << mapper_.samplePatch()
711  << " in region " << mapper_.sampleRegion()
712  << " for patch " << patchField_.patch().name() << nl
713  << abort(FatalError);
714  }
715 
716  const auto& nbrField = fld;
717 
718  newValues = nbrField.boundaryField()[nbrPatchID];
719  }
720  else
721  {
722  // Start off from my patch values, let distribute function below
723  // do all the work
724  newValues = patchField_;
725  }
726  distribute(fieldName_, newValues);
727 
728  break;
729  }
730  case mappedPatchBase::NEARESTFACE:
731  {
732  Field<Type> allValues;
733  if (mapper_.sameWorld())
734  {
735  const fvMesh& nbrMesh =
736  refCast<const fvMesh>(mapper_.sampleMesh());
737  const fieldType& fld = sampleField();
738 
739  allValues.setSize(nbrMesh.nFaces(), Zero);
740 
741  const auto& nbrField = fld;
742 
743  for (const fvPatchField<Type>& pf : nbrField.boundaryField())
744  {
745  label faceStart = pf.patch().start();
746 
747  forAll(pf, facei)
748  {
749  allValues[faceStart++] = pf[facei];
750  }
751  }
752  }
753  else
754  {
755  // Start off from my patch values. Let distribute function below
756  // do all the work
757  allValues.setSize(thisMesh.nFaces(), Zero);
758 
759  const fieldType& thisFld = dynamic_cast<const fieldType&>
760  (
761  patchField_.internalField()
762  );
763 
764  for (const fvPatchField<Type>& pf : thisFld.boundaryField())
765  {
766  label faceStart = pf.patch().start();
767 
768  forAll(pf, facei)
769  {
770  allValues[faceStart++] = pf[facei];
771  }
772  }
773  }
774 
775  distribute(fieldName_, allValues);
776  newValues.transfer(allValues);
777 
778  break;
779  }
780  default:
781  {
783  << "Unknown sampling mode: " << mapper_.mode() << nl
784  << abort(FatalError);
785  }
786  }
787 
788  if (setAverage_)
789  {
790  Type averagePsi =
791  gSum(patchField_.patch().magSf()*newValues)
792  /gSum(patchField_.patch().magSf());
793 
794  if (mag(averagePsi) > 0.5*mag(average_))
795  {
796  newValues *= mag(average_)/mag(averagePsi);
797  }
798  else
799  {
800  newValues += (average_ - averagePsi);
801  }
802  }
803 
804  UPstream::msgType(oldTag); // Restore tag
805 
806  return tnewValues;
807 }
808 
809 
810 //template<class Type>
811 //Foam::tmp<Foam::Field<Type>>
812 //Foam::mappedPatchFieldBase<Type>::mappedField() const
813 //{
814 // const GeometricField<Type, fvPatchField, volMesh>& fld = sampleField();
815 // return mappedField<Type>(fld);
816 //}
817 
818 
819 template<class Type>
822 {
823  // Swap to obtain full local values of neighbour internal field
824  auto tnbrIntFld = tmp<Field<Type>>::New();
825  auto& nbrIntFld = tnbrIntFld.ref();
826 
827  if (mapper_.sameWorld())
828  {
829  // Same world so lookup
830  const label nbrPatchID = mapper_.samplePolyPatch().index();
831  const auto& nbrField = this->sampleField();
832  nbrIntFld = nbrField.boundaryField()[nbrPatchID].patchInternalField();
833  }
834  else
835  {
836  // Different world so use my region,patch. Distribution below will
837  // do the reordering
838  nbrIntFld = patchField_.patchInternalField();
839  }
840 
841  // Since we're inside initEvaluate/evaluate there might be processor
842  // comms underway. Change the tag we use.
843  const int oldTag = UPstream::incrMsgType();
844 
845  distribute(fieldName_, nbrIntFld);
846 
847  UPstream::msgType(oldTag); // Restore tag
849  return tnbrIntFld;
850 }
851 
852 
853 template<class Type>
856 {
857  // Swap to obtain full local values of neighbour internal field
858  auto tnbrKDelta = tmp<scalarField>::New();
859  auto& nbrKDelta = tnbrKDelta.ref();
860 
861  if (mapper_.sameWorld())
862  {
863  // Same world so lookup
864  const auto& nbrMesh = refCast<const fvMesh>(this->mapper_.sampleMesh());
865  const label nbrPatchID = mapper_.samplePolyPatch().index();
866  const auto& nbrPatch = nbrMesh.boundary()[nbrPatchID];
867  nbrKDelta = nbrPatch.deltaCoeffs();
868  }
869  else
870  {
871  // Different world so use my region,patch. Distribution below will
872  // do the reordering
873  nbrKDelta = patchField_.patch().deltaCoeffs();
874  }
875 
876 
877  // Since we're inside initEvaluate/evaluate there might be processor
878  // comms underway. Change the tag we use.
879  const int oldTag = UPstream::incrMsgType();
880 
881  distribute(fieldName_ + "_deltaCoeffs", nbrKDelta);
882 
883  UPstream::msgType(oldTag); // Restore tag
885  return tnbrKDelta;
886 }
887 
888 
889 template<class Type>
891 (
892  const word& fieldName,
893  tmp<scalarField>& thisWeights,
894  tmp<scalarField>& nbrWeights
895 ) const
896 {
897  thisWeights = new scalarField(patchField_.patch().deltaCoeffs());
898  if (!fieldName.empty())
899  {
900  thisWeights.ref() *=
901  patchField_.patch().template lookupPatchField<volScalarField>
902  (
903  fieldName
904  ).patchInternalField();
905  }
906 
907 
908  // Swap to obtain full local values of neighbour internal field
909 
910  if (mapper_.sameWorld())
911  {
912  // Same world so lookup
913  const auto& nbrMesh = refCast<const fvMesh>(mapper_.sampleMesh());
914  const label nbrPatchID = mapper_.samplePolyPatch().index();
915  const auto& nbrPatch = nbrMesh.boundary()[nbrPatchID];
916 
917  nbrWeights = new scalarField(nbrPatch.deltaCoeffs());
918 
919  if (!fieldName.empty())
920  {
921  // Weightfield is volScalarField
922  const auto& nbrWeightField =
923  nbrMesh.template lookupObject<volScalarField>(fieldName);
924  nbrWeights.ref() *=
925  nbrWeightField.boundaryField()[nbrPatchID].patchInternalField();
926  }
927  }
928  else
929  {
930  // Different world so use my region,patch. Distribution below will
931  // do the reordering
932  nbrWeights = new scalarField(thisWeights());
933  }
934 
935  // Since we're inside initEvaluate/evaluate there might be processor
936  // comms underway. Change the tag we use.
937  const int oldTag = UPstream::incrMsgType();
938 
939  distribute(fieldName_ + "_weights", nbrWeights.ref());
941  UPstream::msgType(oldTag); // Restore tag
942 }
943 
944 
945 template<class Type>
947 (
948  const fvPatch& p,
950 )
951 {
952  if (!isA<mappedPatchBase>(p.patch()))
953  {
955  << "Incorrect patch type " << p.patch().type()
956  << " for patch " << p.patch().name()
957  << " of field " << iF.name()
958  << " in file " << iF.objectPath() << nl
959  << "Type should be a mappedPatch"
960  << exit(FatalError);
961  }
962  return refCast<const mappedPatchBase>(p.patch());
963 }
964 
965 
966 template<class Type>
967 template<class T>
969 (
970  const word& fieldName,
971  const Field<T>& fld
972 ) const
973 {
974  if (mapper_.sampleDatabase())
975  {
976  // Store my data on receive buffers (reverse of storeField;
977  // i.e. retrieveField will obtain patchField)
978  if (mapper_.mode() == mappedPatchBase::NEARESTPATCHFACE)
979  {
980  initRetrieveField
981  (
982  patchField_.internalField().time(),
983  mapper_.sampleRegion(),
984  mapper_.samplePatch(),
985  mapper_.map().constructMap(),
986  fieldName,
987  fld
988  );
989  }
990  }
991 }
992 
993 
994 template<class Type>
995 void Foam::mappedPatchFieldBase<Type>::write(Ostream& os) const
996 {
997  //os.writeEntry("field", fieldName_);
998  os.writeEntryIfDifferent<word>
999  (
1000  "field",
1001  patchField_.internalField().name(),
1002  fieldName_
1003  );
1004 
1005  if (setAverage_)
1006  {
1007  os.writeEntry("setAverage", "true");
1008  os.writeEntry("average", average_);
1009  }
1010 
1011  if (mapper_.mode() == mappedPatchBase::NEARESTCELL)
1012  {
1013  os.writeEntry("interpolationScheme", interpolationScheme_);
1014  }
1015 }
1016 
1017 
1018 // ************************************************************************* //
label findPatchID(const word &patchName, const bool allowNotFound=true) const
Find patch index given a name, return -1 if not found.
List< scalar > scalarList
List of scalar.
Definition: scalarList.H:32
dictionary dict
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
void initRetrieveField(const objectRegistry &obr, const word &region, const word &patch, const labelListList &map, const word &fieldName, const Field< T > &fld) const
Construct field from registered elements.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
const scalarListList & tgtWeights() const
Return const access to target patch weights.
static const mappedPatchBase & mapper(const fvPatch &p, const DimensionedField< Type, volMesh > &iF)
Check that patch is of correct type.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:608
virtual void write(Ostream &os) const
Write.
virtual tmp< scalarField > mappedWeightField() const
Map optional weightField onto *this patch. Default is deltaCoeffs.
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:195
T & ref() const
Return non-const reference to the contents of a non-null managed pointer.
Definition: tmpI.H:235
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
const mapDistribute & srcMap() const
Source map - valid only if singlePatchProc = -1 This gets source data into a form to be consumed by t...
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
const labelListList & tgtAddress() const
Return const access to target patch addressing.
scalarField samples(nIntervals, Zero)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
tmp< GeometricField< Type, faPatchField, areaMesh > > average(const GeometricField< Type, faePatchField, edgeMesh > &ssf)
Area-weighted average a edgeField creating a areaField.
Definition: facAverage.C:40
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:70
A traits class, which is primarily used for primitives and vector-space.
Definition: pTraits.H:75
virtual tmp< Field< Type > > mappedInternalField() const
Map internal of sampleField onto *this patch.
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
label constructSize() const noexcept
Constructed data size.
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
Generic GeometricField class.
const GeometricField< Type, fvPatchField, volMesh > & sampleField() const
Field to sample. Either on my or nbr mesh.
label nFaces() const noexcept
Number of mesh faces.
List< labelList > labelListList
List of labelList.
Definition: labelList.H:38
fileName objectPath() const
The complete path + object name.
Definition: IOobjectI.H:284
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
void setSize(const label n)
Alias for resize()
Definition: List.H:320
Type gSum(const FieldField< Field, Type > &f)
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
const polyMesh & mesh() const noexcept
Return the mesh reference.
List< scalarList > scalarListList
List of scalarList.
Definition: scalarList.H:35
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition: polyMesh.H:609
A class for handling words, derived from Foam::string.
Definition: word.H:63
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Determines a mapping between patch face centres and mesh cell or face centres and processors they&#39;re ...
errorManip< error > abort(error &err)
Definition: errorManip.H:139
void reverseDistribute(const label constructSize, List< T > &fld, const bool dummyTransform=true, const int tag=UPstream::msgType()) const
Reverse distribute data using default commsType.
bool storeAndRetrieveField(const word &fieldName, const label myComm, const labelListList &subMap, const label constructSize, const labelListList &constructMap, const labelListList &address, const scalarListList &weights, Field< T > &fld) const
Helper : storeField and retrieveField and interpolate. Leaves fld.
const scalarListList & srcWeights() const
Return const access to source patch weights.
int debug
Static debugging option.
virtual tmp< Field< Type > > mappedField() const
Map sampleField onto *this patch.
OBJstream os(runTime.globalPath()/outputName)
mappedPatchFieldBase(const mappedPatchBase &mapper, const fvPatchField< Type > &patchField, const word &fieldName, const bool setAverage, const Type average, const word &interpolationScheme)
Construct from components.
Functionality for sampling fields using mappedPatchBase. Every call to mappedField() returns a sample...
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< ' ';}gmvFile<< nl;for(const word &name :lagrangianScalarNames){ IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
const labelListList & constructMap() const noexcept
From subsetted data to new reconstructed data.
void storeField(const objectRegistry &obr, const word &region, const word &patch, const label myComm, const labelListList &procToMap, const word &fieldName, const Field< T > &fld) const
Store elements of field onto (sub) registry.
Class containing processor-to-processor mapping information.
#define WarningInFunction
Report a warning using Foam::Warning.
label nCells() const noexcept
Number of mesh cells.
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
Interpolation class dealing with transfer of data between two primitive patches with an arbitrary mes...
const std::string patch
OpenFOAM patch number as a std::string.
bool retrieveField(const bool allowUnset, const objectRegistry &obr, const word &region, const word &patch, const label myComm, const labelListList &procToMap, const word &fieldName, Field< T > &fld) const
Construct field from registered elements.
const fvBoundaryMesh & boundary() const noexcept
Return reference to boundary mesh.
Definition: fvMesh.H:395
List< label > labelList
A List of labels.
Definition: List.H:62
const mapDistribute & tgtMap() const
Target map - valid only if singlePatchProc=-1. This gets target data into a form to be consumed by sr...
volScalarField & p
A class for managing temporary objects.
Definition: HashPtrTable.H:50
Registry of regIOobjects.
const labelListList & subMap() const noexcept
From subsetted data back to original data.
const labelListList & srcAddress() const
Return const access to source patch addressing.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
void distribute(const word &fieldName, Field< T > &newValues) const
Wrapper for mapDistribute::distribute that knows about dabase mapping.
Uses the cell value for any location within the cell.
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:225
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127