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-2025 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;
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 = UPstream::nProcs(UPstream::worldComm);
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,
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,
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  {
409  {
410  // Store my data on receive buffers so we have some initial data
412  (
413  patchField_.internalField().time(),
414  //patchField_.patch().boundaryMesh().mesh().name(),
416  //patchField_.patch().name(),
419  patchField_.internalField().name(),
421  );
422  }
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 {}
479 
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 {
618  typedef GeometricField<Type, fvPatchField, volMesh> fieldType;
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  {
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  }
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  }
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  gWeightedAverage(patchField_.patch().magSf(), newValues);
792 
793  if (mag(averagePsi) > 0.5*mag(average_))
794  {
795  newValues *= mag(average_)/mag(averagePsi);
796  }
797  else
798  {
799  newValues += (average_ - averagePsi);
800  }
801  }
802 
803  UPstream::msgType(oldTag); // Restore tag
804 
805  return tnewValues;
806 }
807 
808 
809 //template<class Type>
810 //Foam::tmp<Foam::Field<Type>>
811 //Foam::mappedPatchFieldBase<Type>::mappedField() const
812 //{
813 // const GeometricField<Type, fvPatchField, volMesh>& fld = sampleField();
814 // return mappedField<Type>(fld);
815 //}
816 
817 
818 template<class Type>
821 {
822  // Swap to obtain full local values of neighbour internal field
823  auto tnbrIntFld = tmp<Field<Type>>::New();
824  auto& nbrIntFld = tnbrIntFld.ref();
825 
826  if (mapper_.sameWorld())
827  {
828  // Same world so lookup
829  const label nbrPatchID = mapper_.samplePolyPatch().index();
830  const auto& nbrField = this->sampleField();
831  nbrIntFld = nbrField.boundaryField()[nbrPatchID].patchInternalField();
832  }
833  else
834  {
835  // Different world so use my region,patch. Distribution below will
836  // do the reordering
837  nbrIntFld = patchField_.patchInternalField();
838  }
839 
840  // Since we're inside initEvaluate/evaluate there might be processor
841  // comms underway. Change the tag we use.
842  const int oldTag = UPstream::incrMsgType();
843 
844  distribute(fieldName_, nbrIntFld);
845 
846  UPstream::msgType(oldTag); // Restore tag
847 
848  return tnbrIntFld;
849 }
850 
851 
852 template<class Type>
855 {
856  // Swap to obtain full local values of neighbour internal field
857  auto tnbrKDelta = tmp<scalarField>::New();
858  auto& nbrKDelta = tnbrKDelta.ref();
859 
860  if (mapper_.sameWorld())
861  {
862  // Same world so lookup
863  const auto& nbrMesh = refCast<const fvMesh>(this->mapper_.sampleMesh());
864  const label nbrPatchID = mapper_.samplePolyPatch().index();
865  const auto& nbrPatch = nbrMesh.boundary()[nbrPatchID];
866  nbrKDelta = nbrPatch.deltaCoeffs();
867  }
868  else
869  {
870  // Different world so use my region,patch. Distribution below will
871  // do the reordering
872  nbrKDelta = patchField_.patch().deltaCoeffs();
873  }
874 
875 
876  // Since we're inside initEvaluate/evaluate there might be processor
877  // comms underway. Change the tag we use.
878  const int oldTag = UPstream::incrMsgType();
879 
880  distribute(fieldName_ + "_deltaCoeffs", nbrKDelta);
881 
882  UPstream::msgType(oldTag); // Restore tag
883 
884  return tnbrKDelta;
885 }
886 
887 
888 template<class Type>
890 (
891  const word& fieldName,
892  tmp<scalarField>& thisWeights,
893  tmp<scalarField>& nbrWeights
894 ) const
895 {
896  thisWeights = new scalarField(patchField_.patch().deltaCoeffs());
897  if (!fieldName.empty())
898  {
899  thisWeights.ref() *=
900  patchField_.patch().template lookupPatchField<volScalarField>
901  (
902  fieldName
903  ).patchInternalField();
904  }
905 
906 
907  // Swap to obtain full local values of neighbour internal field
908 
909  if (mapper_.sameWorld())
910  {
911  // Same world so lookup
912  const auto& nbrMesh = refCast<const fvMesh>(mapper_.sampleMesh());
913  const label nbrPatchID = mapper_.samplePolyPatch().index();
914  const auto& nbrPatch = nbrMesh.boundary()[nbrPatchID];
915 
916  nbrWeights = new scalarField(nbrPatch.deltaCoeffs());
917 
918  if (!fieldName.empty())
919  {
920  // Weightfield is volScalarField
921  const auto& nbrWeightField =
922  nbrMesh.template lookupObject<volScalarField>(fieldName);
923  nbrWeights.ref() *=
924  nbrWeightField.boundaryField()[nbrPatchID].patchInternalField();
925  }
926  }
927  else
928  {
929  // Different world so use my region,patch. Distribution below will
930  // do the reordering
931  nbrWeights = new scalarField(thisWeights());
932  }
933 
934  // Since we're inside initEvaluate/evaluate there might be processor
935  // comms underway. Change the tag we use.
936  const int oldTag = UPstream::incrMsgType();
937 
938  distribute(fieldName_ + "_weights", nbrWeights.ref());
939 
940  UPstream::msgType(oldTag); // Restore tag
941 }
942 
943 
944 template<class Type>
946 (
947  const fvPatch& p,
949 )
950 {
951  if (!isA<mappedPatchBase>(p.patch()))
952  {
954  << "Incorrect patch type " << p.patch().type()
955  << " for patch " << p.patch().name()
956  << " of field " << iF.name()
957  << " in file " << iF.objectPath() << nl
958  << "Type should be a mappedPatch"
959  << exit(FatalError);
960  }
961  return refCast<const mappedPatchBase>(p.patch());
962 }
963 
964 
965 template<class Type>
966 template<class T>
968 (
969  const word& fieldName,
970  const Field<T>& fld
971 ) const
972 {
973  if (mapper_.sampleDatabase())
974  {
975  // Store my data on receive buffers (reverse of storeField;
976  // i.e. retrieveField will obtain patchField)
977  if (mapper_.mode() == mappedPatchBase::NEARESTPATCHFACE)
978  {
979  initRetrieveField
980  (
981  patchField_.internalField().time(),
982  mapper_.sampleRegion(),
983  mapper_.samplePatch(),
984  mapper_.map().constructMap(),
985  fieldName,
986  fld
987  );
988  }
989  }
990 }
991 
992 
993 template<class Type>
994 void Foam::mappedPatchFieldBase<Type>::write(Ostream& os) const
995 {
996  //os.writeEntry("field", fieldName_);
998  (
999  "field",
1000  patchField_.internalField().name(),
1001  fieldName_
1002  );
1003 
1004  if (setAverage_)
1005  {
1006  os.writeEntry("setAverage", "true");
1007  os.writeEntry("average", average_);
1008  }
1009 
1010  if (mapper_.mode() == mappedPatchBase::NEARESTCELL)
1011  {
1012  os.writeEntry("interpolationScheme", interpolationScheme_);
1013  }
1014 }
1015 
1016 
1017 // ************************************************************************* //
Info<< nl<< "Wrote faMesh in vtk format: "<< writer.output().name()<< nl;}{ vtk::lineWriter writer(aMesh.points(), aMesh.edges(), fileName(aMesh.time().globalPath()/"finiteArea-edges"));writer.writeGeometry();writer.beginCellData(4);writer.writeProcIDs();{ Field< scalar > fld(faMeshTools::flattenEdgeField(aMesh.magLe(), true))
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
Generic GeometricField class.
A primitive field of type <T> with automated input and output.
Definition: IOField.H:53
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:195
fileName objectPath() const
The complete path + object name.
Definition: IOobjectI.H:284
Ostream & writeEntryIfDifferent(const word &key, const T &value1, const T &value2)
Write a keyword/value entry only when the two values differ.
Definition: Ostream.H:336
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
Definition: Ostream.H:321
A List with indirect addressing. Like IndirectList but does not store addressing.
Definition: IndirectList.H:76
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:1787
static int incrMsgType(int val=1) noexcept
Increment the message tag for standard messages.
Definition: UPstream.H:1809
static const Form max
Definition: VectorSpace.H:130
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:132
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:85
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
Definition: fvPatchField.H:353
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:71
Uses the cell value for any location within the cell.
static autoPtr< interpolation< Type > > New(const word &interpolationType, const GeometricField< Type, fvPatchField, volMesh > &psi)
Return a reference to the specified interpolation scheme.
const labelListList & constructMap() const noexcept
From subsetted data to new reconstructed data.
Determines a mapping between patch face centres and mesh cell or face centres and processors they're ...
const mapDistribute & map() const
Return reference to the parallel distribution map.
@ NEARESTCELL
nearest cell containing sample
@ NEARESTPATCHFACE
nearest face on selected patch
@ NEARESTPATCHFACEAMI
nearest patch face + AMI interpolation
@ NEARESTFACE
nearest face
bool sampleDatabase() const noexcept
const word & samplePatch() const
Patch (only if NEARESTPATCHFACE)
sampleMode mode() const noexcept
What to sample.
const word & sampleRegion() const
Region to sample.
Functionality for sampling fields using mappedPatchBase. Every call to mappedField() returns a sample...
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.
const mappedPatchBase & mapper_
Mapping engine.
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.
virtual tmp< Field< Type > > mappedField() const
Map sampleField onto *this patch.
virtual void write(Ostream &os) const
Write.
static const mappedPatchBase & mapper(const fvPatch &p, const DimensionedField< Type, volMesh > &iF)
Check that patch is of correct type.
virtual tmp< scalarField > mappedWeightField() const
Map optional weightField onto *this patch. Default is deltaCoeffs.
virtual tmp< Field< Type > > mappedInternalField() const
Map internal of sampleField onto *this patch.
const GeometricField< Type, fvPatchField, volMesh > & sampleField() const
Field to sample. Either on my or nbr mesh.
mappedPatchFieldBase(const mappedPatchBase &mapper, const fvPatchField< Type > &patchField, const word &fieldName, const bool setAverage, const Type average, const word &interpolationScheme)
Construct from components.
const fvPatchField< Type > & patchField_
Underlying patch field.
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.
void distribute(const word &fieldName, Field< T > &newValues) const
Wrapper for mapDistribute::distribute that knows about dabase mapping.
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.
Registry of regIOobjects.
const polyMesh & mesh() const noexcept
Return the mesh reference.
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition: polyMesh.H:609
A class for managing temporary objects.
Definition: tmp.H:66
static tmp< T > New(Args &&... args)
Construct tmp with forwarding arguments.
Definition: tmp.H:206
T & ref() const
Return non-const reference to the contents of a non-null managed pointer.
Definition: tmpI.H:235
A class for handling words, derived from Foam::string.
Definition: word.H:66
volScalarField & p
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:600
OBJstream os(runTime.globalPath()/outputName)
#define WarningInFunction
Report a warning using Foam::Warning.
tmp< GeometricField< Type, faPatchField, areaMesh > > average(const GeometricField< Type, faePatchField, edgeMesh > &ssf)
Area-weighted average a edgeField creating a areaField.
Definition: facAverage.C:40
const std::string patch
OpenFOAM patch number as a std::string.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
List< labelList > labelListList
List of labelList.
Definition: labelList.H:38
Type gWeightedAverage(const UList< scalar > &weights, const UList< Type > &fld, const label comm)
The global weighted average of a field, using the mag() of the weights.
List< label > labelList
A List of labels.
Definition: List.H:61
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:529
errorManip< error > abort(error &err)
Definition: errorManip.H:139
AMIInterpolation AMIPatchToPatchInterpolation
Patch-to-patch interpolation == Foam::AMIInterpolation.
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:225
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Field< vector > vectorField
Specialisation of Field<T> for vector.
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.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:50
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:286
scalarField samples(nIntervals, Zero)