uniformBin.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) 2021-2023 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "uniformBin.H"
30 
31 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
32 
33 namespace Foam
34 {
35 namespace binModels
36 {
39 }
40 }
41 
42 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
43 
45 {
47 
48  // Use geometry limits if not specified by the user
49  {
50  // Determine extents of patches/cells
51  boundBox geomLimits;
52 
53  for (const label patchi : patchIDs_)
54  {
56  (
57  coordSysPtr_->localPosition(pbm[patchi].faceCentres())
58  );
59 
61  geomLimits.add(limits.min(), limits.max());
62  }
63 
64  for (const label zonei : cellZoneIDs_)
65  {
66  const cellZone& cZone = mesh_.cellZones()[zonei];
67  const vectorField pts
68  (
69  coordSysPtr_->localPosition(vectorField(mesh_.C(), cZone))
70  );
71 
72  MinMax<vector> limits(pts);
73  geomLimits.add(limits.min(), limits.max());
74  }
75 
76  // Globally consistent
77  geomLimits.reduce();
78 
79  // Slightly boost max so that region of interest is fully within bounds
80  // TBD: could also adjust min?
81  const vector adjust(1e-4*geomLimits.span());
82  geomLimits.max() += adjust;
83 
84  for (direction cmpt = 0; cmpt < vector::nComponents; ++cmpt)
85  {
86  // Use geometry limits if not specified by the user
87  if (binLimits_.min()[cmpt] == GREAT)
88  {
89  binLimits_.min()[cmpt] = geomLimits.min()[cmpt];
90  }
91  if (binLimits_.max()[cmpt] == GREAT)
92  {
93  binLimits_.max()[cmpt] = geomLimits.max()[cmpt];
94  }
95  }
96  }
97 
98  for (direction cmpt = 0; cmpt < vector::nComponents; ++cmpt)
99  {
100  if (binLimits_.min()[cmpt] > binLimits_.max()[cmpt])
101  {
103  << "Max bounds must be greater than min bounds" << nl
104  << " direction = " << cmpt << nl
105  << " min = " << binLimits_.min()[cmpt] << nl
106  << " max = " << binLimits_.max()[cmpt] << nl
107  << exit(FatalError);
108  }
109 
110  //- Compute bin widths in binning directions
111  binWidth_[cmpt] =
112  (
113  (binLimits_.max()[cmpt] - binLimits_.min()[cmpt])
114  / scalar(nBins_[cmpt])
115  );
116 
117  if (binWidth_[cmpt] <= 0)
118  {
120  << "Bin widths must be greater than zero" << nl
121  << " direction = " << cmpt << nl
122  << " min bound = " << binLimits_.min()[cmpt] << nl
123  << " max bound = " << binLimits_.max()[cmpt] << nl
124  << " bin width = " << binWidth_[cmpt] << nl
125  << exit(FatalError);
126  }
127  }
130 }
131 
132 
134 {
135  labelList binIndices(d.size(), -1);
136 
137  forAll(d, i)
138  {
139  // Avoid elements outside of the bin
140  bool faceInside = true;
141  for (direction cmpt = 0; cmpt < vector::nComponents; ++cmpt)
142  {
143  if
144  (
145  d[i][cmpt] < binLimits_.min()[cmpt]
146  || d[i][cmpt] > binLimits_.max()[cmpt]
147  )
148  {
149  faceInside = false;
150  break;
151  }
152  }
153 
154  if (faceInside)
155  {
156  // Find the bin division corresponding to the element
157  Vector<label> n(Zero);
158  for (direction cmpt = 0; cmpt < vector::nComponents; ++cmpt)
159  {
160  label bini = floor
161  (
162  (d[i][cmpt] - binLimits_.min()[cmpt])/binWidth_[cmpt]
163  );
164 
165  n[cmpt] = min(max(bini, 0), nBins_[cmpt] - 1);
166  }
167 
168  // Order: (e1, e2, e3), the first varies the fastest
169  binIndices[i] = n.x() + nBins_[0]*n.y() + nBins_[0]*nBins_[1]*n.z();
170  }
171  else
172  {
173  binIndices[i] = -1;
174  }
175  }
177  return binIndices;
178 }
179 
180 
182 {
183  faceToBin_.resize_nocopy(mesh_.nBoundaryFaces());
184  faceToBin_ = -1;
185 
186  for (const label patchi : patchIDs_)
187  {
188  const polyPatch& pp = mesh_.boundaryMesh()[patchi];
189  const label i0 = pp.start() - mesh_.nInternalFaces();
190 
191  SubList<label>(faceToBin_, pp.size(), i0) =
192  binAddr(coordSysPtr_->localPosition(pp.faceCentres()));
193  }
194 
195  cellToBin_.resize_nocopy(mesh_.nCells());
196  cellToBin_ = -1;
197 
198  for (const label zonei : cellZoneIDs_)
199  {
200  const cellZone& cZone = mesh_.cellZones()[zonei];
201  labelList bins
202  (
203  binAddr(coordSysPtr_->localPosition(vectorField(mesh_.C(), cZone)))
204  );
205 
206  forAll(cZone, i)
207  {
208  const label celli = cZone[i];
209  cellToBin_[celli] = bins[i];
210  }
211  }
212 }
214 
215 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
216 
218 (
219  const dictionary& dict,
220  const fvMesh& mesh,
221  const word& outputPrefix
222 )
223 :
224  binModel(dict, mesh, outputPrefix),
225  nBins_(Zero),
226  binWidth_(Zero),
227  binLimits_(vector::uniform(GREAT))
228 {
229  read(dict);
230 }
231 
232 
233 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
234 
236 {
237  if (!binModel::read(dict))
238  {
239  return false;
240  }
241 
242  Info<< " Activating a set of uniform bins" << endl;
243 
244  const dictionary& binDict = dict.subDict("binData");
245 
246  nBins_ = binDict.get<Vector<label>>("nBin");
247 
248  for (const label n : nBins_)
249  {
250  nBin_ *= n;
251  }
252 
253  if (nBin_ <= 0)
254  {
255  FatalIOErrorInFunction(binDict)
256  << "Number of bins must be greater than zero" << nl
257  << " e1 bins = " << nBins_.x() << nl
258  << " e2 bins = " << nBins_.y() << nl
259  << " e3 bins = " << nBins_.z()
260  << exit(FatalIOError);
261  }
262 
263  Info<< " - Employing:" << nl
264  << " " << nBins_.x() << " e1 bins," << nl
265  << " " << nBins_.y() << " e2 bins," << nl
266  << " " << nBins_.z() << " e3 bins"
267  << endl;
268 
269  cumulative_ = binDict.getOrDefault<bool>("cumulative", false);
270  Info<< " - cumulative : " << cumulative_ << endl;
271  Info<< " - decomposePatchValues : " << decomposePatchValues_ << endl;
272 
273  const dictionary* minMaxDictPtr = binDict.findDict("minMax");
274 
275  if (minMaxDictPtr)
276  {
277  const auto& minMaxDict = *minMaxDictPtr;
278 
279  for (direction cmpt = 0; cmpt < vector::nComponents; ++cmpt)
280  {
281  const word ei("e" + Foam::name(cmpt));
282 
284 
285  if (minMaxDict.readIfPresent(ei, range))
286  {
287  binLimits_.min()[cmpt] = range.min();
288  binLimits_.max()[cmpt] = range.max();
289 
290  Info<< " - " << ei << " min/max : " << range << nl;
291  }
292  }
293  }
294  Info<< endl;
295 
296  initialise();
298  return true;
299 }
300 
301 
303 {
304  forAll(fieldNames_, i)
305  {
306  const bool ok =
307  (
308  processField<scalar>(i)
309  || processField<vector>(i)
310  || processField<sphericalTensor>(i)
311  || processField<symmTensor>(i)
312  || processField<tensor>(i)
313  );
314 
315  if (!ok)
316  {
318  << "Unable to find field " << fieldNames_[i] << endl;
319  }
320  }
322  writtenHeader_ = true;
323 }
324 
327 {}
328 
329 
331 {
332  setBinsAddressing();
333 }
334 
335 
336 // ************************************************************************* //
const polyBoundaryMesh & pbm
dictionary dict
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
uniformBin(const dictionary &dict, const fvMesh &mesh, const word &outputPrefix)
Construct from components.
Definition: uniformBin.C:213
Calculates binned data in multiple segments according to a specified Cartesian or cylindrical coordin...
Definition: uniformBin.H:157
uint8_t direction
Definition: direction.H:46
MinMax< vector > binLimits_
The geometric min/max bounds for the bins.
Definition: uniformBin.H:178
MinMax< scalar > scalarMinMax
A scalar min/max range.
Definition: MinMax.H:97
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
const fvMesh & mesh_
Reference to the mesh.
Definition: binModel.H:68
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
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:600
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
A min/max value pair with additional methods. In addition to conveniently storing values...
Definition: HashSet.H:72
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:529
virtual void initialise()
Initialise bin properties.
Definition: uniformBin.C:37
A bounding box defined in terms of min/max extrema points.
Definition: boundBox.H:63
virtual void updateMesh(const mapPolyMesh &mpm)
Update for changes of mesh.
Definition: uniformBin.C:321
::Foam::direction nComponents(const expressions::valueTypeCode) noexcept
The number of components associated with given valueTypeCode.
Definition: exprTraits.C:40
const point & min() const noexcept
Minimum describing the bounding box.
Definition: boundBoxI.H:162
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T. FatalIOError if not found, or if the number of tokens is incorrect.
defineTypeNameAndDebug(singleDirectionUniformBin, 0)
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Definition: mapPolyMesh.H:158
Macros for easy insertion into run-time selection tables.
scalar range
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:286
Base class for bin models to handle general bin characteristics.
Definition: binModel.H:57
virtual void movePoints(const polyMesh &mesh)
Update for changes of mesh.
Definition: uniformBin.C:325
auto limits
Definition: setRDeltaT.H:186
const point & max() const noexcept
Maximum describing the bounding box.
Definition: boundBoxI.H:168
void add(const boundBox &bb)
Extend to include the second box.
Definition: boundBoxI.H:323
A non-owning sub-view of a List (allocated or unallocated storage).
Definition: SubList.H:46
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
dynamicFvMesh & mesh
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition: polyMesh.H:609
A class for handling words, derived from Foam::string.
Definition: word.H:63
labelList patchIDs_
Indices of operand patches.
Definition: binModel.H:94
virtual labelList binAddr(const vectorField &d) const
Return list of bin indices corresponding to positions given by d.
Definition: uniformBin.C:128
Vector< scalar > vector
Definition: vector.H:57
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
void reduce()
Inplace parallel reduction of min/max values.
Definition: boundBox.C:178
A polyBoundaryMesh is a polyPatch list with registered IO, a reference to the associated polyMesh...
autoPtr< coordinateSystem > coordSysPtr_
Local coordinate system of bins.
Definition: binModel.H:84
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
addToRunTimeSelectionTable(binModel, singleDirectionUniformBin, dictionary)
A subset of mesh cells.
Definition: cellZone.H:58
vector binWidth_
Equidistant bin widths in binning directions.
Definition: uniformBin.H:173
#define WarningInFunction
Report a warning using Foam::Warning.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:629
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
virtual bool read(const dictionary &dict)
Read the dictionary.
Definition: uniformBin.C:230
virtual bool read(const dictionary &dict)
Read the dictionary.
Definition: binModel.C:125
const cellZoneMesh & cellZones() const noexcept
Return cell zone mesh.
Definition: polyMesh.H:679
vector span() const
The bounding box span (from minimum to maximum)
Definition: boundBoxI.H:192
messageStream Info
Information stream (stdout output on master, null elsewhere)
label n
Field< vector > vectorField
Specialisation of Field<T> for vector.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:75
const volVectorField & C() const
Return cell centres as volVectorField.
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
labelList cellZoneIDs_
Indices of operand cell zones.
Definition: binModel.H:104
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:69
virtual void setBinsAddressing()
Set/cache the bin addressing.
Definition: uniformBin.C:176
Vector< label > nBins_
Numbers of bins in binning directions.
Definition: uniformBin.H:168
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
Namespace for OpenFOAM.
virtual void apply()
Apply bins.
Definition: uniformBin.C:297
const pointField & pts
const dictionary * findDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary pointer if present (and it is a dictionary) otherwise return nullptr...
Definition: dictionaryI.H:124
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127