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 
60  MinMax<vector> limits(pts);
61 
62  geomLimits.add(limits.min());
63  geomLimits.add(limits.max());
64  }
65 
66  for (const label zonei : cellZoneIDs_)
67  {
68  const cellZone& cZone = mesh_.cellZones()[zonei];
69  const vectorField pts
70  (
71  coordSysPtr_->localPosition(vectorField(mesh_.C(), cZone))
72  );
73 
74  MinMax<vector> limits(pts);
75 
76  geomLimits.add(limits.min());
77  geomLimits.add(limits.max());
78  }
79 
80  // Globally consistent
81  geomLimits.reduce();
82 
83  // Slightly boost max so that region of interest is fully within bounds
84  // TBD: could also adjust min?
85  const vector adjust(1e-4*geomLimits.span());
86  geomLimits.max() += adjust;
87 
88  for (direction cmpt = 0; cmpt < vector::nComponents; ++cmpt)
89  {
90  // Use geometry limits if not specified by the user
91  if (binLimits_.min()[cmpt] == GREAT)
92  {
93  binLimits_.min()[cmpt] = geomLimits.min()[cmpt];
94  }
95  if (binLimits_.max()[cmpt] == GREAT)
96  {
97  binLimits_.max()[cmpt] = geomLimits.max()[cmpt];
98  }
99  }
100  }
101 
102  for (direction cmpt = 0; cmpt < vector::nComponents; ++cmpt)
103  {
104  if (binLimits_.min()[cmpt] > binLimits_.max()[cmpt])
105  {
107  << "Max bounds must be greater than min bounds" << nl
108  << " direction = " << cmpt << nl
109  << " min = " << binLimits_.min()[cmpt] << nl
110  << " max = " << binLimits_.max()[cmpt] << nl
111  << exit(FatalError);
112  }
113 
114  //- Compute bin widths in binning directions
115  binWidth_[cmpt] =
116  (
117  (binLimits_.max()[cmpt] - binLimits_.min()[cmpt])
118  / scalar(nBins_[cmpt])
119  );
120 
121  if (binWidth_[cmpt] <= 0)
122  {
124  << "Bin widths must be greater than zero" << nl
125  << " direction = " << cmpt << nl
126  << " min bound = " << binLimits_.min()[cmpt] << nl
127  << " max bound = " << binLimits_.max()[cmpt] << nl
128  << " bin width = " << binWidth_[cmpt] << nl
129  << exit(FatalError);
130  }
131  }
134 }
135 
136 
138 {
139  labelList binIndices(d.size(), -1);
140 
141  forAll(d, i)
142  {
143  // Avoid elements outside of the bin
144  bool faceInside = true;
145  for (direction cmpt = 0; cmpt < vector::nComponents; ++cmpt)
146  {
147  if
148  (
149  d[i][cmpt] < binLimits_.min()[cmpt]
150  || d[i][cmpt] > binLimits_.max()[cmpt]
151  )
152  {
153  faceInside = false;
154  break;
155  }
156  }
157 
158  if (faceInside)
159  {
160  // Find the bin division corresponding to the element
161  Vector<label> n(Zero);
162  for (direction cmpt = 0; cmpt < vector::nComponents; ++cmpt)
163  {
164  label bini = floor
165  (
166  (d[i][cmpt] - binLimits_.min()[cmpt])/binWidth_[cmpt]
167  );
168 
169  n[cmpt] = min(max(bini, 0), nBins_[cmpt] - 1);
170  }
171 
172  // Order: (e1, e2, e3), the first varies the fastest
173  binIndices[i] = n.x() + nBins_[0]*n.y() + nBins_[0]*nBins_[1]*n.z();
174  }
175  else
176  {
177  binIndices[i] = -1;
178  }
179  }
181  return binIndices;
182 }
183 
184 
186 {
187  faceToBin_.resize_nocopy(mesh_.nBoundaryFaces());
188  faceToBin_ = -1;
189 
190  for (const label patchi : patchIDs_)
191  {
192  const polyPatch& pp = mesh_.boundaryMesh()[patchi];
193  const label i0 = pp.start() - mesh_.nInternalFaces();
194 
195  SubList<label>(faceToBin_, pp.size(), i0) =
196  binAddr(coordSysPtr_->localPosition(pp.faceCentres()));
197  }
198 
199  cellToBin_.resize_nocopy(mesh_.nCells());
200  cellToBin_ = -1;
201 
202  for (const label zonei : cellZoneIDs_)
203  {
204  const cellZone& cZone = mesh_.cellZones()[zonei];
205  labelList bins
206  (
207  binAddr(coordSysPtr_->localPosition(vectorField(mesh_.C(), cZone)))
208  );
209 
210  forAll(cZone, i)
211  {
212  const label celli = cZone[i];
213  cellToBin_[celli] = bins[i];
214  }
215  }
216 }
218 
219 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
220 
222 (
223  const dictionary& dict,
224  const fvMesh& mesh,
225  const word& outputPrefix
226 )
227 :
228  binModel(dict, mesh, outputPrefix),
229  nBins_(Zero),
230  binWidth_(Zero),
231  binLimits_(vector::uniform(GREAT))
232 {
233  read(dict);
234 }
235 
236 
237 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
238 
240 {
241  if (!binModel::read(dict))
242  {
243  return false;
244  }
245 
246  Info<< " Activating a set of uniform bins" << endl;
247 
248  const dictionary& binDict = dict.subDict("binData");
249 
250  nBins_ = binDict.get<Vector<label>>("nBin");
251 
252  for (const label n : nBins_)
253  {
254  nBin_ *= n;
255  }
256 
257  if (nBin_ <= 0)
258  {
259  FatalIOErrorInFunction(binDict)
260  << "Number of bins must be greater than zero" << nl
261  << " e1 bins = " << nBins_.x() << nl
262  << " e2 bins = " << nBins_.y() << nl
263  << " e3 bins = " << nBins_.z()
264  << exit(FatalIOError);
265  }
266 
267  Info<< " - Employing:" << nl
268  << " " << nBins_.x() << " e1 bins," << nl
269  << " " << nBins_.y() << " e2 bins," << nl
270  << " " << nBins_.z() << " e3 bins"
271  << endl;
272 
273  cumulative_ = binDict.getOrDefault<bool>("cumulative", false);
274  Info<< " - cumulative : " << cumulative_ << endl;
275  Info<< " - decomposePatchValues : " << decomposePatchValues_ << endl;
276 
277  const dictionary* minMaxDictPtr = binDict.findDict("minMax");
278 
279  if (minMaxDictPtr)
280  {
281  const auto& minMaxDict = *minMaxDictPtr;
282 
283  for (direction cmpt = 0; cmpt < vector::nComponents; ++cmpt)
284  {
285  const word ei("e" + Foam::name(cmpt));
286 
288 
289  if (minMaxDict.readIfPresent(ei, range))
290  {
291  binLimits_.min()[cmpt] = range.min();
292  binLimits_.max()[cmpt] = range.max();
293 
294  Info<< " - " << ei << " min/max : " << range << nl;
295  }
296  }
297  }
298  Info<< endl;
299 
300  initialise();
302  return true;
303 }
304 
305 
307 {
308  forAll(fieldNames_, i)
309  {
310  const bool ok =
311  (
312  processField<scalar>(i)
313  || processField<vector>(i)
314  || processField<sphericalTensor>(i)
315  || processField<symmTensor>(i)
316  || processField<tensor>(i)
317  );
318 
319  if (!ok)
320  {
322  << "Unable to find field " << fieldNames_[i] << endl;
323  }
324  }
326  writtenHeader_ = true;
327 }
328 
331 {}
332 
333 
335 {
336  setBinsAddressing();
337 }
338 
339 
340 // ************************************************************************* //
const polyBoundaryMesh & pbm
dictionary dict
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
uniformBin(const dictionary &dict, const fvMesh &mesh, const word &outputPrefix)
Construct from components.
Definition: uniformBin.C:217
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:598
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:531
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:325
::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:157
Macros for easy insertion into run-time selection tables.
scalar range
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
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:329
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 List obtained as a section of another List.
Definition: SubList.H:50
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:608
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:132
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 additional search methods and registered IO...
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:627
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:234
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:678
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:74
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:180
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:301
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 a sub-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