surfaceFieldValue.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) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2017-2020 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 "surfaceFieldValue.H"
30 #include "fvMesh.H"
31 #include "emptyPolyPatch.H"
32 #include "coupledPolyPatch.H"
33 #include "sampledSurface.H"
34 #include "mergePoints.H"
35 #include "indirectPrimitivePatch.H"
36 #include "PatchTools.H"
38 
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 
41 namespace Foam
42 {
43 namespace functionObjects
44 {
45 namespace fieldValues
46 {
47  defineTypeNameAndDebug(surfaceFieldValue, 0);
48  addToRunTimeSelectionTable(fieldValue, surfaceFieldValue, dictionary);
49  addToRunTimeSelectionTable(functionObject, surfaceFieldValue, dictionary);
50 }
51 }
52 }
53 
54 
55 const Foam::Enum
56 <
58 >
60 ({
61  { regionTypes::stFaceZone, "faceZone" },
62  { regionTypes::stPatch, "patch" },
63  { regionTypes::stObject, "functionObjectSurface" },
64  { regionTypes::stSampled, "sampledSurface" },
65 });
66 
67 
68 const Foam::Enum
69 <
71 >
73 ({
74  // Normal operations
75  { operationType::opNone, "none" },
76  { operationType::opMin, "min" },
77  { operationType::opMax, "max" },
78  { operationType::opSum, "sum" },
79  { operationType::opSumMag, "sumMag" },
80  { operationType::opSumDirection, "sumDirection" },
81  { operationType::opSumDirectionBalance, "sumDirectionBalance" },
82  { operationType::opAverage, "average" },
83  { operationType::opAreaAverage, "areaAverage" },
84  { operationType::opAreaIntegrate, "areaIntegrate" },
85  { operationType::opCoV, "CoV" },
86  { operationType::opAreaNormalAverage, "areaNormalAverage" },
87  { operationType::opAreaNormalIntegrate, "areaNormalIntegrate" },
88  { operationType::opUniformity, "uniformity" },
89 
90  // Using weighting
91  { operationType::opWeightedSum, "weightedSum" },
92  { operationType::opWeightedAverage, "weightedAverage" },
93  { operationType::opWeightedAreaAverage, "weightedAreaAverage" },
94  { operationType::opWeightedAreaIntegrate, "weightedAreaIntegrate" },
95  { operationType::opWeightedUniformity, "weightedUniformity" },
96 
97  // Using absolute weighting
98  { operationType::opAbsWeightedSum, "absWeightedSum" },
99  { operationType::opAbsWeightedAverage, "absWeightedAverage" },
100  { operationType::opAbsWeightedAreaAverage, "absWeightedAreaAverage" },
101  { operationType::opAbsWeightedAreaIntegrate, "absWeightedAreaIntegrate" },
102  { operationType::opAbsWeightedUniformity, "absWeightedUniformity" },
103 });
104 
105 const Foam::Enum
106 <
108 >
110 ({
111  { postOperationType::postOpNone, "none" },
112  { postOperationType::postOpMag, "mag" },
113  { postOperationType::postOpSqrt, "sqrt" },
114 });
115 
116 
117 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
118 
121 {
122  if (stObject == regionType_)
123  {
125  }
126 
127  return mesh_;
128 }
129 
130 
131 void Foam::functionObjects::fieldValues::surfaceFieldValue::setFaceZoneFaces()
132 {
133  const label zoneId = mesh_.faceZones().findZoneID(regionName_);
134 
135  if (zoneId < 0)
136  {
138  << type() << " " << name() << ": "
139  << regionTypeNames_[regionType_] << '(' << regionName_ << "):" << nl
140  << " Unknown face zone name: " << regionName_
141  << ". Valid face zones are: " << mesh_.faceZones().names()
142  << nl << exit(FatalError);
143  }
144 
145  const faceZone& fZone = mesh_.faceZones()[zoneId];
146 
147  DynamicList<label> faceIds(fZone.size());
148  DynamicList<label> facePatchIds(fZone.size());
149  DynamicList<bool> faceFlip(fZone.size());
150 
151  forAll(fZone, i)
152  {
153  const label facei = fZone[i];
154 
155  label faceId = -1;
156  label facePatchId = -1;
157  if (mesh_.isInternalFace(facei))
158  {
159  faceId = facei;
160  facePatchId = -1;
161  }
162  else
163  {
164  facePatchId = mesh_.boundaryMesh().whichPatch(facei);
165  const polyPatch& pp = mesh_.boundaryMesh()[facePatchId];
166  if (isA<coupledPolyPatch>(pp))
167  {
168  if (refCast<const coupledPolyPatch>(pp).owner())
169  {
170  faceId = pp.whichFace(facei);
171  }
172  else
173  {
174  faceId = -1;
175  }
176  }
177  else if (!isA<emptyPolyPatch>(pp))
178  {
179  faceId = facei - pp.start();
180  }
181  else
182  {
183  faceId = -1;
184  facePatchId = -1;
185  }
186  }
187 
188  if (faceId >= 0)
189  {
190  faceIds.append(faceId);
191  facePatchIds.append(facePatchId);
192  faceFlip.append(fZone.flipMap()[i] ? true : false);
193  }
194  }
195 
196  faceId_.transfer(faceIds);
197  facePatchId_.transfer(facePatchIds);
198  faceFlip_.transfer(faceFlip);
199  nFaces_ = returnReduce(faceId_.size(), sumOp<label>());
200 
201  if (debug)
202  {
203  Pout<< "Original face zone size = " << fZone.size()
204  << ", new size = " << faceId_.size() << endl;
205  }
206 }
207 
208 
209 void Foam::functionObjects::fieldValues::surfaceFieldValue::setPatchFaces()
210 {
211  const label patchid = mesh_.boundaryMesh().findPatchID(regionName_);
212 
213  if (patchid < 0)
214  {
216  << type() << " " << name() << ": "
217  << regionTypeNames_[regionType_] << '(' << regionName_ << "):" << nl
218  << " Unknown patch name: " << regionName_
219  << ". Valid patch names are: "
220  << mesh_.boundaryMesh().names() << nl
221  << exit(FatalError);
222  }
223 
224  const polyPatch& pp = mesh_.boundaryMesh()[patchid];
225 
226  label nFaces = pp.size();
227  if (isA<emptyPolyPatch>(pp))
228  {
229  nFaces = 0;
230  }
231 
232  faceId_.setSize(nFaces);
233  facePatchId_.setSize(nFaces);
234  faceFlip_.setSize(nFaces);
235  nFaces_ = returnReduce(faceId_.size(), sumOp<label>());
236 
237  forAll(faceId_, facei)
238  {
239  faceId_[facei] = facei;
240  facePatchId_[facei] = patchid;
241  faceFlip_[facei] = false;
242  }
243 }
244 
245 
246 void Foam::functionObjects::fieldValues::surfaceFieldValue::combineMeshGeometry
247 (
248  faceList& faces,
250 ) const
251 {
252  List<faceList> allFaces(Pstream::nProcs());
253  List<pointField> allPoints(Pstream::nProcs());
254 
255  labelList globalFacesIs(faceId_);
256  forAll(globalFacesIs, i)
257  {
258  if (facePatchId_[i] != -1)
259  {
260  const label patchi = facePatchId_[i];
261  globalFacesIs[i] += mesh_.boundaryMesh()[patchi].start();
262  }
263  }
264 
265  // Add local faces and points to the all* lists
267  (
268  IndirectList<face>(mesh_.faces(), globalFacesIs),
269  mesh_.points()
270  );
271  allFaces[Pstream::myProcNo()] = pp.localFaces();
272  allPoints[Pstream::myProcNo()] = pp.localPoints();
273 
274  Pstream::gatherList(allFaces);
276 
277  // Renumber and flatten
278  label nFaces = 0;
279  label nPoints = 0;
280  forAll(allFaces, proci)
281  {
282  nFaces += allFaces[proci].size();
283  nPoints += allPoints[proci].size();
284  }
285 
286  faces.setSize(nFaces);
287  points.setSize(nPoints);
288 
289  nFaces = 0;
290  nPoints = 0;
291 
292  // My own data first
293  {
294  const faceList& fcs = allFaces[Pstream::myProcNo()];
295  for (const face& f : fcs)
296  {
297  face& newF = faces[nFaces++];
298  newF.setSize(f.size());
299  forAll(f, fp)
300  {
301  newF[fp] = f[fp] + nPoints;
302  }
303  }
304 
305  const pointField& pts = allPoints[Pstream::myProcNo()];
306  for (const point& pt : pts)
307  {
308  points[nPoints++] = pt;
309  }
310  }
311 
312  // Other proc data follows
313  forAll(allFaces, proci)
314  {
315  if (proci != Pstream::myProcNo())
316  {
317  const faceList& fcs = allFaces[proci];
318  for (const face& f : fcs)
319  {
320  face& newF = faces[nFaces++];
321  newF.setSize(f.size());
322  forAll(f, fp)
323  {
324  newF[fp] = f[fp] + nPoints;
325  }
326  }
327 
328  const pointField& pts = allPoints[proci];
329  for (const point& pt : pts)
330  {
331  points[nPoints++] = pt;
332  }
333  }
334  }
335 
336  // Merge
337  labelList oldToNew;
338  pointField newPoints;
339  bool hasMerged = mergePoints
340  (
341  points,
342  SMALL,
343  false,
344  oldToNew,
345  newPoints
346  );
347 
348  if (hasMerged)
349  {
350  if (debug)
351  {
352  Pout<< "Merged from " << points.size()
353  << " down to " << newPoints.size() << " points" << endl;
354  }
355 
356  points.transfer(newPoints);
357  for (face& f : faces)
358  {
359  inplaceRenumber(oldToNew, f);
360  }
361  }
362 }
363 
364 
365 void Foam::functionObjects::fieldValues::surfaceFieldValue::
366 combineSurfaceGeometry
367 (
368  faceList& faces,
370 ) const
371 {
372  if (stObject == regionType_)
373  {
374  const polySurface& s = dynamicCast<const polySurface>(obr());
375 
376  if (Pstream::parRun())
377  {
378  // Dimension as fraction of surface
379  const scalar mergeDim = 1e-10*boundBox(s.points(), true).mag();
380 
381  labelList pointsMap;
382 
384  (
385  mergeDim,
387  (
388  SubList<face>(s.faces(), s.faces().size()),
389  s.points()
390  ),
391  points,
392  faces,
393  pointsMap
394  );
395  }
396  else
397  {
398  faces = s.faces();
399  points = s.points();
400  }
401  }
402  else if (sampledPtr_.valid())
403  {
404  const sampledSurface& s = sampledPtr_();
405 
406  if (Pstream::parRun())
407  {
408  // Dimension as fraction of mesh bounding box
409  const scalar mergeDim = 1e-10*mesh_.bounds().mag();
410 
411  labelList pointsMap;
412 
414  (
415  mergeDim,
417  (
418  SubList<face>(s.faces(), s.faces().size()),
419  s.points()
420  ),
421  points,
422  faces,
423  pointsMap
424  );
425  }
426  else
427  {
428  faces = s.faces();
429  points = s.points();
430  }
431  }
432 }
433 
434 
435 Foam::scalar
436 Foam::functionObjects::fieldValues::surfaceFieldValue::totalArea() const
437 {
438  scalar totalArea = 0;
439 
440  if (stObject == regionType_)
441  {
442  const polySurface& s = dynamicCast<const polySurface>(obr());
443 
444  totalArea = gSum(s.magSf());
445  }
446  else if (sampledPtr_.valid())
447  {
448  totalArea = gSum(sampledPtr_().magSf());
449  }
450  else
451  {
452  totalArea = gSum(filterField(mesh_.magSf()));
453  }
454 
455  return totalArea;
456 }
457 
458 
459 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
460 
462 {
463  // Only a few operations do not require the Sf field
464  switch (operation_)
465  {
466  case opNone:
467  case opMin:
468  case opMax:
469  case opSum:
470  case opSumMag:
471  case opAverage:
472  {
473  return false;
474  }
475  default:
476  {
477  return true;
478  }
479  }
480 }
481 
482 
484 {
485  if (sampledPtr_.valid())
486  {
487  sampledPtr_->update();
488  }
489 
490  if (!needsUpdate_)
491  {
492  return false;
493  }
494 
495  switch (regionType_)
496  {
497  case stFaceZone:
498  {
499  setFaceZoneFaces();
500  break;
501  }
502  case stPatch:
503  {
504  setPatchFaces();
505  break;
506  }
507  case stObject:
508  {
509  const polySurface& s = dynamicCast<const polySurface>(obr());
510  nFaces_ = returnReduce(s.size(), sumOp<label>());
511  break;
512  }
513  case stSampled:
514  {
515  nFaces_ = returnReduce(sampledPtr_->faces().size(), sumOp<label>());
516  break;
517  }
518 
519  // Compiler warning if we forgot an enumeration
520  }
521 
522  if (nFaces_ == 0)
523  {
525  << type() << " " << name() << ": "
526  << regionTypeNames_[regionType_] << '(' << regionName_ << "):" << nl
527  << " Region has no faces" << exit(FatalError);
528  }
529 
530  totalArea_ = totalArea();
531 
532  Log << " total faces = " << nFaces_ << nl
533  << " total area = " << totalArea_ << nl
534  << endl;
535 
536  writeFileHeader(file());
537 
538  needsUpdate_ = false;
539  return true;
540 }
541 
542 
544 (
545  Ostream& os
546 )
547 {
548  if (canWriteHeader() && (operation_ != opNone))
549  {
550  writeCommented(os, "Region type : ");
551  os << regionTypeNames_[regionType_] << " " << regionName_ << endl;
552 
553  writeHeaderValue(os, "Faces", nFaces_);
554  writeHeaderValue(os, "Area", totalArea_);
555  writeHeaderValue(os, "Scale factor", scaleFactor_);
556 
557  if (weightFieldName_ != "none")
558  {
559  writeHeaderValue(os, "Weight field", weightFieldName_);
560  }
561 
562  writeCommented(os, "Time");
563  if (writeArea_)
564  {
565  os << tab << "Area";
566  }
567 
568  // TBD: add in postOperation information?
569 
570  for (const word& fieldName : fields_)
571  {
572  os << tab << operationTypeNames_[operation_]
573  << "(" << fieldName << ")";
574  }
575 
576  os << endl;
577  }
578 
579  writtenHeader_ = true;
580 }
581 
582 
583 template<>
584 Foam::scalar
586 (
587  const Field<scalar>& values,
588  const vectorField& Sf,
589  const scalarField& weightField
590 ) const
591 {
592  switch (operation_)
593  {
594  case opSumDirection:
595  {
596  const vector n(dict_.get<vector>("direction"));
597  return gSum(pos0(values*(Sf & n))*mag(values));
598  }
599  case opSumDirectionBalance:
600  {
601  const vector n(dict_.get<vector>("direction"));
602  const scalarField nv(values*(Sf & n));
603 
604  return gSum(pos0(nv)*mag(values) - neg(nv)*mag(values));
605  }
606 
607  case opUniformity:
608  case opWeightedUniformity:
609  case opAbsWeightedUniformity:
610  {
611  const scalar areaTotal = gSum(mag(Sf));
612  tmp<scalarField> areaVal(values * mag(Sf));
613 
614  scalar mean, numer;
615 
616  if (canWeight(weightField))
617  {
618  // Weighted quantity = (Weight * phi * dA)
619 
620  tmp<scalarField> weight(weightingFactor(weightField));
621 
622  // Mean weighted value (area-averaged)
623  mean = gSum(weight()*areaVal()) / areaTotal;
624 
625  // Abs. deviation from weighted mean value
626  numer = gSum(mag(weight*areaVal - (mean * mag(Sf))));
627  }
628  else
629  {
630  // Unweighted quantity = (1 * phi * dA)
631 
632  // Mean value (area-averaged)
633  mean = gSum(areaVal()) / areaTotal;
634 
635  // Abs. deviation from mean value
636  numer = gSum(mag(areaVal - (mean * mag(Sf))));
637  }
638 
639  // Uniformity index
640  const scalar ui = 1 - numer/(2*mag(mean*areaTotal) + ROOTVSMALL);
641 
642  return min(max(ui, 0), 1);
643  }
644 
645  default:
646  {
647  // Fall through to other operations
648  return processSameTypeValues(values, Sf, weightField);
649  }
650  }
651 }
652 
653 
654 template<>
657 (
658  const Field<vector>& values,
659  const vectorField& Sf,
660  const scalarField& weightField
661 ) const
662 {
663  switch (operation_)
664  {
665  case opSumDirection:
666  {
667  const vector n(dict_.get<vector>("direction").normalise());
668 
669  const scalarField nv(n & values);
670  return gSum(pos0(nv)*n*(nv));
671  }
672  case opSumDirectionBalance:
673  {
674  const vector n(dict_.get<vector>("direction").normalise());
675 
676  const scalarField nv(n & values);
677  return gSum(pos0(nv)*n*(nv));
678  }
679  case opAreaNormalAverage:
680  {
681  const scalar val = gSum(values & Sf)/gSum(mag(Sf));
682  return vector(val, 0, 0);
683  }
684  case opAreaNormalIntegrate:
685  {
686  const scalar val = gSum(values & Sf);
687  return vector(val, 0, 0);
688  }
689 
690  case opUniformity:
691  case opWeightedUniformity:
692  case opAbsWeightedUniformity:
693  {
694  const scalar areaTotal = gSum(mag(Sf));
695  tmp<scalarField> areaVal(values & Sf);
696 
697  scalar mean, numer;
698 
699  if (canWeight(weightField))
700  {
701  // Weighted quantity = (Weight * phi . dA)
702 
703  tmp<scalarField> weight(weightingFactor(weightField));
704 
705  // Mean weighted value (area-averaged)
706  mean = gSum(weight()*areaVal()) / areaTotal;
707 
708  // Abs. deviation from weighted mean value
709  numer = gSum(mag(weight*areaVal - (mean * mag(Sf))));
710  }
711  else
712  {
713  // Unweighted quantity = (1 * phi . dA)
714 
715  // Mean value (area-averaged)
716  mean = gSum(areaVal()) / areaTotal;
717 
718  // Abs. deviation from mean value
719  numer = gSum(mag(areaVal - (mean * mag(Sf))));
720  }
721 
722  // Uniformity index
723  const scalar ui = 1 - numer/(2*mag(mean*areaTotal) + ROOTVSMALL);
724 
725  return vector(min(max(ui, 0), 1), 0, 0);
726  }
727 
728  default:
729  {
730  // Fall through to other operations
731  return processSameTypeValues(values, Sf, weightField);
732  }
733  }
734 }
735 
736 
737 template<>
740 (
741  const Field<scalar>& weightField
742 ) const
743 {
744  if (usesMag())
745  {
746  return mag(weightField);
747  }
748 
749  // pass through
750  return weightField;
751 }
752 
753 
754 template<>
757 (
758  const Field<scalar>& weightField,
759  const vectorField& Sf
760 ) const
761 {
762  // scalar * Area
763 
764  if (returnReduce(weightField.empty(), andOp<bool>()))
765  {
766  // No weight field - revert to unweighted form
767  return mag(Sf);
768  }
769  else if (usesMag())
770  {
771  return mag(weightField * mag(Sf));
772  }
773 
774  return (weightField * mag(Sf));
775 }
776 
777 
778 template<>
781 (
782  const Field<vector>& weightField,
783  const vectorField& Sf
784 ) const
785 {
786  // vector (dot) Area
787 
788  if (returnReduce(weightField.empty(), andOp<bool>()))
789  {
790  // No weight field - revert to unweighted form
791  return mag(Sf);
792  }
793  else if (usesMag())
794  {
795  return mag(weightField & Sf);
796  }
797 
798  return (weightField & Sf);
799 }
800 
801 
802 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
803 
805 (
806  const word& name,
807  const Time& runTime,
808  const dictionary& dict
809 )
810 :
811  fieldValue(name, runTime, dict, typeName),
812  regionType_(regionTypeNames_.get("regionType", dict)),
813  operation_(operationTypeNames_.get("operation", dict)),
814  postOperation_
815  (
816  postOperationTypeNames_.getOrDefault
817  (
818  "postOperation",
819  dict,
820  postOperationType::postOpNone,
821  true // Failsafe behaviour
822  )
823  ),
824  weightFieldName_("none"),
825  needsUpdate_(true),
826  writeArea_(false),
827  totalArea_(0),
828  nFaces_(0),
829  faceId_(),
830  facePatchId_(),
831  faceFlip_()
832 {
833  read(dict);
834 }
835 
836 
838 (
839  const word& name,
840  const objectRegistry& obr,
841  const dictionary& dict
842 )
843 :
844  fieldValue(name, obr, dict, typeName),
845  regionType_(regionTypeNames_.get("regionType", dict)),
846  operation_(operationTypeNames_.get("operation", dict)),
847  postOperation_
848  (
849  postOperationTypeNames_.getOrDefault
850  (
851  "postOperation",
852  dict,
853  postOperationType::postOpNone,
854  true // Failsafe behaviour
855  )
856  ),
857  weightFieldName_("none"),
858  needsUpdate_(true),
859  writeArea_(false),
860  totalArea_(0),
861  nFaces_(0),
862  faceId_(),
863  facePatchId_(),
864  faceFlip_()
865 {
866  read(dict);
867 }
868 
869 
870 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
871 
873 (
874  const dictionary& dict
875 )
876 {
878 
879  weightFieldName_ = "none";
880  needsUpdate_ = true;
881  writeArea_ = dict.getOrDefault("writeArea", false);
882  totalArea_ = 0;
883  nFaces_ = 0;
884  faceId_.clear();
885  facePatchId_.clear();
886  faceFlip_.clear();
887  sampledPtr_.clear();
888  surfaceWriterPtr_.clear();
889 
890  dict.readEntry("name", regionName_);
891 
892  // Create sampled surface, but leave 'expired' (ie, no update) since it
893  // may depend on fields or data that do not yet exist
894  if (stSampled == regionType_)
895  {
896  sampledPtr_ = sampledSurface::New
897  (
898  name(),
899  mesh_,
900  dict.subDict("sampledSurfaceDict")
901  );
902  }
903 
904  Info<< type() << " " << name() << ":" << nl
905  << " operation = ";
906 
907  if (postOperation_ != postOpNone)
908  {
909  Info<< postOperationTypeNames_[postOperation_] << '('
910  << operationTypeNames_[operation_] << ')' << nl;
911  }
912  else
913  {
914  Info<< operationTypeNames_[operation_] << nl;
915  }
916 
917  if (usesWeight())
918  {
919  if (stSampled == regionType_)
920  {
922  << "Cannot use weighted operation '"
923  << operationTypeNames_[operation_]
924  << "' for sampledSurface"
925  << exit(FatalIOError);
926  }
927 
928  if (dict.readIfPresent("weightField", weightFieldName_))
929  {
930  Info<< " weight field = " << weightFieldName_ << nl;
931  }
932  else
933  {
934  // Suggest possible alternative unweighted operation?
936  << "The '" << operationTypeNames_[operation_]
937  << "' operation is missing a weightField." << nl
938  << "Either provide the weightField, "
939  << "use weightField 'none' to suppress weighting," << nl
940  << "or use a different operation."
941  << exit(FatalIOError);
942  }
943  }
944 
945  // Backwards compatibility for v1612 and older
946  List<word> orientedFields;
947  if (dict.readIfPresent("orientedFields", orientedFields))
948  {
949  fields_.append(orientedFields);
950 
952  << "The 'orientedFields' option is deprecated. These fields can "
953  << "and have been added to the standard 'fields' list."
954  << endl;
955  }
956 
957  if (writeFields_)
958  {
959  const word formatName(dict.get<word>("surfaceFormat"));
960 
961  surfaceWriterPtr_.reset
962  (
964  (
965  formatName,
966  dict.subOrEmptyDict("formatOptions").subOrEmptyDict(formatName)
967  )
968  );
969 
970  if (debug)
971  {
972  surfaceWriterPtr_->verbose() = true;
973  }
974 
975  if (surfaceWriterPtr_->enabled())
976  {
977  Info<< " surfaceFormat = " << formatName << nl;
978  }
979  else
980  {
981  surfaceWriterPtr_->clear();
982  }
983  }
984 
985  Info<< nl << endl;
986 
987  return true;
988 }
989 
990 
992 {
993  if (needsUpdate_ || operation_ != opNone)
994  {
996  }
997 
998  update();
999 
1000  if (operation_ != opNone)
1001  {
1002  writeCurrentTime(file());
1003  }
1004 
1005  if (writeArea_)
1006  {
1007  totalArea_ = totalArea();
1008  Log << " total area = " << totalArea_ << endl;
1009 
1010  if (operation_ != opNone && Pstream::master())
1011  {
1012  file() << tab << totalArea_;
1013  }
1014  }
1015 
1016  // Many operations use the Sf field
1017  vectorField Sf;
1018  if (usesSf())
1019  {
1020  if (stObject == regionType_)
1021  {
1022  const polySurface& s = dynamicCast<const polySurface>(obr());
1023  Sf = s.Sf();
1024  }
1025  else if (sampledPtr_.valid())
1026  {
1027  Sf = sampledPtr_().Sf();
1028  }
1029  else
1030  {
1031  Sf = filterField(mesh_.Sf());
1032  }
1033  }
1034 
1035  // Faces and points for surface format (if specified)
1036  faceList faces;
1038 
1039  if (surfaceWriterPtr_.valid())
1040  {
1041  if (withTopologicalMerge())
1042  {
1043  combineMeshGeometry(faces, points);
1044  }
1045  else
1046  {
1047  combineSurfaceGeometry(faces, points);
1048  }
1049  }
1050 
1051  // Only a few weight types (scalar, vector)
1052  if (weightFieldName_ != "none")
1053  {
1054  if (validField<scalar>(weightFieldName_))
1055  {
1056  scalarField weightField
1057  (
1058  getFieldValues<scalar>(weightFieldName_, true)
1059  );
1060 
1061  // Process the fields
1062  writeAll(Sf, weightField, points, faces);
1063  }
1064  else if (validField<vector>(weightFieldName_))
1065  {
1066  vectorField weightField
1067  (
1068  getFieldValues<vector>(weightFieldName_, true)
1069  );
1070 
1071  // Process the fields
1072  writeAll(Sf, weightField, points, faces);
1073  }
1074  else
1075  {
1077  << "weightField " << weightFieldName_
1078  << " not found or an unsupported type"
1079  << abort(FatalError);
1080  }
1081  }
1082  else
1083  {
1084  // Default is a zero-size scalar weight field (ie, weight = 1)
1085  scalarField weightField;
1086 
1087  // Process the fields
1088  writeAll(Sf, weightField, points, faces);
1089  }
1090 
1091  if (operation_ != opNone)
1092  {
1093  file() << endl;
1094  Log << endl;
1095  }
1096 
1097 
1098  return true;
1099 }
1100 
1101 
1104  const mapPolyMesh& mpm
1105 )
1106 {
1107  needsUpdate_ = true;
1108 }
1109 
1110 
1113  const polyMesh& mesh
1114 )
1115 {
1116  needsUpdate_ = true;
1117 }
1118 
1119 
1120 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:71
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
runTime
engineTime & runTime
Definition: createEngineTime.H:13
Foam::sampledSurface::New
static autoPtr< sampledSurface > New(const word &name, const polyMesh &mesh, const dictionary &dict)
Return a reference to the selected surface.
Definition: sampledSurface.C:64
Foam::Enum
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition: IOstreamOption.H:57
Log
#define Log
Definition: PDRblock.C:34
Foam::Time
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:73
Foam::functionObjects::fieldValues::addToRunTimeSelectionTable
addToRunTimeSelectionTable(functionObject, fieldValueDelta, dictionary)
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
Foam::functionObjects::fieldValue::read
virtual bool read(const dictionary &dict)
Read from dictionary.
Definition: fieldValue.C:89
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:94
s
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;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Definition: gmvOutputSpray.H:25
update
mesh update()
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:59
Foam::functionObjects::fieldValues::surfaceFieldValue::operationType
operationType
Operation type enumeration.
Definition: surfaceFieldValue.H:461
Foam::functionObjects::fieldValues::surfaceFieldValue::read
virtual bool read(const dictionary &dict)
Read from dictionary.
Definition: surfaceFieldValue.C:873
Foam::functionObjects::fieldValues::surfaceFieldValue::postOperationType
postOperationType
Post-operation type enumeration.
Definition: surfaceFieldValue.H:533
PatchTools.H
Foam::DynamicList< label >
Foam::HashTableOps::values
List< T > values(const HashTable< T, Key, Hash > &tbl, const bool doSort=false)
List of values from HashTable, optionally sorted.
Definition: HashOps.H:149
Foam::functionObjects::timeFunctionObject::storedObjects
objectRegistry & storedObjects()
Definition: timeFunctionObject.C:63
Foam::PatchTools::gatherAndMerge
static void gatherAndMerge(const scalar mergeDist, const PrimitivePatch< FaceList, PointField > &p, Field< typename PrimitivePatch< FaceList, PointField >::point_type > &mergedPoints, List< typename PrimitivePatch< FaceList, PointField >::face_type > &mergedFaces, labelList &pointMergeMap)
Gather points and faces onto master and merge into single patch.
Definition: PatchToolsGatherAndMerge.C:38
Foam::UPstream::nProcs
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:427
Foam::read
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition: int32.H:107
Foam::UPstream::parRun
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:415
Foam::functionObjects::fieldValues::defineTypeNameAndDebug
defineTypeNameAndDebug(fieldValueDelta, 0)
Foam::functionObjects::fieldValues::surfaceFieldValue::usesSf
bool usesSf() const
True if the operation needs a surface Sf.
Definition: surfaceFieldValue.C:461
Foam::List::append
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:182
Foam::FatalIOError
IOerror FatalIOError
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:350
Foam::pos0
dimensionedScalar pos0(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:188
Foam::gSum
Type gSum(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:594
Foam::Pout
prefixOSstream Pout
An Ostream wrapper for parallel output to std::cout.
Foam::Vector::normalise
Vector< Cmpt > & normalise()
Normalise the vector by its magnitude.
Definition: VectorI.H:123
Foam::functionObjects::fieldValues::surfaceFieldValue::regionTypeNames_
static const Enum< regionTypes > regionTypeNames_
Region type names.
Definition: surfaceFieldValue.H:449
Foam::functionObjects::fieldValues::surfaceFieldValue::regionType_
regionTypes regionType_
Region type.
Definition: surfaceFieldValue.H:577
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
Foam::inplaceRenumber
void inplaceRenumber(const labelUList &oldToNew, IntListType &input)
Inplace renumber the values (not the indices) of a list.
Definition: ListOpsTemplates.C:61
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
Foam::sumOp
Definition: ops.H:213
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::functionObjects::fieldValues::surfaceFieldValue::surfaceFieldValue
surfaceFieldValue(const word &name, const Time &runTime, const dictionary &dict)
Construct from name, Time and dictionary.
Definition: surfaceFieldValue.C:805
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Foam::functionObjects::fieldValues::surfaceFieldValue::stObject
Calculate with function object surface.
Definition: surfaceFieldValue.H:444
Foam::objectRegistry
Registry of regIOobjects.
Definition: objectRegistry.H:60
Foam::functionObjects::fieldValues::surfaceFieldValue::weightingFactor
tmp< scalarField > weightingFactor(const Field< WeightType > &weightField) const
Weighting factor.
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::polySurface
A surface mesh consisting of general polygon faces and capable of holding fields.
Definition: polySurface.H:67
Foam::functionObjects::fieldValues::surfaceFieldValue::update
bool update()
Update the surface and surface information as required.
Definition: surfaceFieldValue.C:483
coupledPolyPatch.H
Foam::functionObjects::fieldValue::regionName_
word regionName_
Name of region (patch, zone, etc.)
Definition: fieldValue.H:133
Foam::Field< scalar >
Foam::polyPatch::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundaryMesh reference.
Definition: polyPatch.C:307
Foam::faceZone
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:65
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:67
Foam::name
word name(const complex &c)
Return string representation of complex.
Definition: complex.C:76
faceId
label faceId(-1)
sampledSurface.H
Foam::functionObjects::fieldValues::surfaceFieldValue::updateMesh
virtual void updateMesh(const mapPolyMesh &mpm)
Update for changes of mesh.
Definition: surfaceFieldValue.C:1103
Foam::PtrList::setSize
void setSize(const label newLen)
Same as resize()
Definition: PtrListI.H:108
Foam::functionObjects::fieldValues::surfaceFieldValue::regionTypes
regionTypes
Region type enumeration.
Definition: surfaceFieldValue.H:440
Foam::andOp
Definition: ops.H:233
Foam::objectRegistry::lookupObject
const Type & lookupObject(const word &name, const bool recursive=false) const
Definition: objectRegistryTemplates.C:434
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
indirectPrimitivePatch.H
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:121
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
fvMesh.H
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:137
Foam::functionObjects::fieldValues::surfaceFieldValue::obr
const objectRegistry & obr() const
The volume mesh or surface registry being used.
Definition: surfaceFieldValue.C:120
Foam::vector
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:51
Foam::polyPatch::start
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:312
emptyPolyPatch.H
Foam::functionObjects::fieldValues::surfaceFieldValue::movePoints
virtual void movePoints(const polyMesh &mesh)
Update for changes of mesh.
Definition: surfaceFieldValue.C:1112
Foam::mergePoints
label mergePoints(const PointList &points, const scalar mergeTol, const bool verbose, labelList &pointMap, typename PointList::const_reference origin=PointList::value_type::zero)
Sorts and merges points. All points closer than/equal mergeTol get merged.
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:445
Foam::UPstream::master
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:439
Foam::indirectPrimitivePatch
PrimitivePatch< IndirectList< face >, const pointField & > indirectPrimitivePatch
A PrimitivePatch with an IndirectList for the faces, const reference for the point field.
Definition: indirectPrimitivePatch.H:49
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:372
Foam::Pstream::gatherList
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
Definition: gatherScatterList.C:52
Foam::polyPatch::whichFace
label whichFace(const label l) const
Return label of face in patch from global face label.
Definition: polyPatch.H:399
Foam::tab
constexpr char tab
Definition: Ostream.H:384
Foam::nl
constexpr char nl
Definition: Ostream.H:385
Foam::functionObjects::fieldValues::surfaceFieldValue::operationTypeNames_
static const Enum< operationType > operationTypeNames_
Operation type names.
Definition: surfaceFieldValue.H:529
f
labelList f(nPoints)
Foam::faceList
List< face > faceList
A List of faces.
Definition: faceListFwd.H:47
Foam::surfaceWriter::New
static autoPtr< surfaceWriter > New(const word &writeType)
Return a reference to the selected surfaceWriter.
Definition: surfaceWriter.C:64
Foam::Vector< scalar >
Foam::List< word >
Foam::functionObjects::fieldValue
Intermediate class for handling field value-based function objects.
Definition: fieldValue.H:119
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::type
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: MSwindows.C:590
Foam::functionObjects::fvMeshFunctionObject::mesh_
const fvMesh & mesh_
Reference to the fvMesh.
Definition: fvMeshFunctionObject.H:73
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
Foam::functionObjects::fieldValues::surfaceFieldValue::writeFileHeader
virtual void writeFileHeader(Ostream &os)
Output file header information.
Definition: surfaceFieldValue.C:544
mergePoints.H
Merge points. See below.
Foam::mapPolyMesh
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Definition: mapPolyMesh.H:160
Foam::primitivePatch
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
A PrimitivePatch with a SubList addressing for the faces, const reference for the point field.
Definition: primitivePatch.H:51
surfaceFieldValue.H
FatalIOErrorInFunction
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:392
Foam::DelaunayMeshTools::allPoints
tmp< pointField > allPoints(const Triangulation &t)
Extract all points in vertex-index order.
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::functionObjects::fieldValue::write
virtual bool write()
Write.
Definition: fieldValue.C:113
Foam::point
vector point
Point is a vector.
Definition: point.H:43
Foam::functionObjects::fieldValues::surfaceFieldValue::write
virtual bool write()
Calculate and write.
Definition: surfaceFieldValue.C:991
Foam::List::setSize
void setSize(const label newSize)
Alias for resize(const label)
Definition: ListI.H:146
Foam::faceZone::flipMap
const boolList & flipMap() const
Return face flip map.
Definition: faceZone.H:271
Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
Type processValues(const Field< Type > &values, const vectorField &Sf, const Field< WeightType > &weightField) const
Apply the 'operation' to the values. Wrapper around.
Definition: surfaceFieldValueTemplates.C:293
Foam::neg
dimensionedScalar neg(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:199
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:298
Foam::functionObjects::fieldValues::surfaceFieldValue::postOperationTypeNames_
static const Enum< postOperationType > postOperationTypeNames_
Operation type names.
Definition: surfaceFieldValue.H:541