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  tmp<Field<Type>> tnbrIntFld(new Field<Type>());
825  Field<Type>& 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  tmp<scalarField> tnbrKDelta(new scalarField());
859  scalarField& 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:598
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.
Definition: areaFieldsFwd.H:50
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:316
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:608
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...
Definition: areaFieldsFwd.H:42
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