multiFixedValue.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2026 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "multiFixedValue.H"
28 
29 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
30 
31 namespace Foam
32 {
33 namespace distributions
34 {
37 }
38 }
39 
40 
41 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
42 
44 (
45  const unitSet& defaultUnits,
46  const dictionary& dict,
47  const label sampleQ,
49 )
50 :
52  (
53  typeName,
54  defaultUnits,
55  dict,
56  sampleQ,
57  std::move(rndGen)
58  ),
59  reader_
60  (
61  TableReader<scalar, scalar>::New
62  (
63  word::null,
64  {defaultUnits, units::any},
65  dict
66  )
67  )
68 {
70  reader_->read({defaultUnits, units::any}, dict, "values");
71 
72  // Sort
74  (
75  values,
77  {
78  return a.first() < b.first();
79  }
80  );
81 
82  // Checks
83  for (label i = 1; i < values.size(); ++ i)
84  {
85  if (values[i].second() < 0)
86  {
88  << typeName << ": The probabilities are not all positive "
89  << abort(FatalIOError);
90  }
91  }
92 
93  // Copy the coordinates
94  x_.resize(values.size());
95  forAll(values, i)
96  {
97  x_[i] = values[i].first();
98  }
99 
100  // Copy the probabilities. Scale if q != 0.
101  P_.resize(values.size());
102  forAll(values, i)
103  {
104  P_[i] = integerPow(x_[i], q())*values[i].second();
105  }
106 
107  // Compute the cumulative sum of the probabilities
108  sumP_.resize(values.size() + 1);
109  sumP_[0] = 0;
110  forAll(values, i)
111  {
112  sumP_[i + 1] = sumP_[i] + P_[i];
113  }
114 
115  // Normalise
116  P_ /= sumP_.last();
117  sumP_ /= sumP_.last();
118 }
119 
120 
122 (
123  const multiFixedValue& d,
124  const label sampleQ
125 )
126 :
128  reader_(d.reader_, false),
129  x_(d.x_),
130  P_(d.P_),
131  sumP_(d.sumP_)
132 {
133  if (q() == d.q()) return;
134 
135  // Scale the probabilities
136  P_ = integerPow(x_, q() - d.q())*d.P_;
137 
138  // Compute the cumulative sum of the probabilities
139  sumP_.resize(x_.size() + 1);
140  sumP_[0] = 0;
141  forAll(x_, i)
142  {
143  sumP_[i + 1] = sumP_[i] + P_[i];
144  }
145 
146  // Normalise
147  P_ /= sumP_.last();
148  sumP_ /= sumP_.last();
149 }
150 
151 
152 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
153 
155 {}
156 
157 
158 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
159 
161 {
162  const scalar S = rndGen_.sample01<scalar>();
163 
164  label i = 0;
165  for (; i < sumP_.size() - 1 && sumP_[i + 1] < S; ++ i);
166 
167  return x_[i];
168 }
169 
170 
172 {
173  return x_.first();
174 }
175 
176 
178 {
179  return x_.last();
180 }
181 
182 
184 {
185  return sum(x_*P_);
186 }
187 
188 
191 (
192  const scalarField& x,
193  const label e,
194  const bool
195 ) const
196 {
197  tmp<scalarField> tResult(new scalarField(x.size()));
198  scalarField& result = tResult.ref();
199 
200  label i = 0;
201 
202  while (i < x.size() && x[i] < x_[0])
203  {
204  result[i] = 0;
205  i ++;
206  }
207 
208  scalar integral_PDFxPowE_0_j = P_[0]*integerPow(x_[0], e);
209 
210  for (label j = 0; j < x_.size() - 1; ++ j)
211  {
212  while (i < x.size() && x[i] < x_[j + 1])
213  {
214  result[i] = integral_PDFxPowE_0_j;
215  i ++;
216  }
217 
218  integral_PDFxPowE_0_j += P_[j + 1]*integerPow(x_[j + 1], e);
219  }
220 
221  while (i < x.size())
222  {
223  result[i] = integral_PDFxPowE_0_j;
224  i ++;
225  }
226 
227  return tResult;
228 }
229 
230 
232 (
233  Ostream& os,
234  const unitSet& units
235 ) const
236 {
238 
239  // Recover the probabilities
240  scalarField P(integerPow(x_, -q())*P_);
241 
242  // Normalise the probabilities
243  P /= sum(P);
244 
245  // Construct and write the values
246  List<Tuple2<scalar, scalar>> values(P_.size());
247  forAll(values, i)
248  {
249  values[i].first() = x_[i];
250  values[i].second() = P[i];
251  }
252  reader_->write(os, {units, units::any}, values, "values");
253 }
254 
255 
258 {
259  tmp<scalarField> tResult(new scalarField(3*x_.size()));
260  scalarField& result = tResult.ref();
261 
262  forAll(x_, i)
263  {
264  result[3*i] = result[3*i + 1] = result[3*i + 2] = x_[i];
265  }
266 
267  return tResult;
268 }
269 
270 
273 {
274  tmp<scalarField> tResult(new scalarField(3*x_.size()));
275  scalarField& result = tResult.ref();
276 
277  forAll(x_, i)
278  {
279  result[3*i] = result[3*i + 2] = 0;
280  result[3*i + 1] = P_[i]/rootVSmall;
281  }
282 
283  return tResult;
284 }
285 
286 
287 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
Macros for easy insertion into run-time selection tables.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:91
void resize(const label)
Alias for setSize(const label)
Definition: ListI.H:138
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
Base class to read table data for tables.
Definition: TableReader.H:51
A 2-tuple for storing two objects of different types.
Definition: Tuple2.H:66
const Type1 & first() const
Return first.
Definition: Tuple2.H:119
T & first()
Return the first element of the list.
Definition: UListI.H:114
T & last()
Return the last element of the list.
Definition: UListI.H:128
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
Base class for statistical distributions.
Definition: distribution.H:76
label q() const
Return the effective distribution size exponent.
Definition: distribution.H:107
Distribution which comprises a list of fixed values with given probabilities. The probabilities are n...
virtual tmp< scalarField > integralPDFxPow(const scalarField &x, const label e, const bool consistent=false) const
Return the integral of the PDF multiplied by an integer power of x.
virtual scalar min() const
Return the minimum value.
virtual scalar sample() const
Sample the distribution.
virtual tmp< scalarField > plotPDF(const scalarField &x) const
Return values to plot the probability density function.
multiFixedValue(const unitSet &units, const dictionary &dict, const label sampleQ, randomGenerator &&rndGen)
Construct from a dictionary.
virtual void write(Ostream &os, const unitSet &units) const
Write to a stream.
virtual scalar max() const
Return the maximum value.
virtual scalar mean() const
Return the mean value.
virtual tmp< scalarField > plotX(const label n) const
Return coordinates to plot across the range of the distribution.
Random number generator.
A class for managing temporary objects.
Definition: tmp.H:55
T & ref() const
Return non-const reference or generate a fatal error.
Definition: tmpI.H:197
Template function which returns the un-mangled name of a given type. Useful for types which do not ha...
Unit conversion structure. Contains the associated dimensions and the multiplier with which to conver...
Definition: unitSet.H:68
A class for handling words, derived from string.
Definition: word.H:63
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:346
volScalarField & b
Definition: createFields.H:27
defineTypeNameAndDebug(exponential, 0)
addToRunTimeSelectionTable(distribution, exponential, dictionary)
tmp< fvMatrix< Type > > S(const Pair< tmp< volScalarField::Internal >> &, const VolField< Type > &)
const unitSet any
void write(std::ostream &os, const bool binary, List< floatScalar > &fField)
Write floats ascii or binary.
Namespace for OpenFOAM.
const doubleScalar e
Definition: doubleScalar.H:106
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
errorManip< error > abort(error &err)
Definition: errorManip.H:131
scalar integerPow(const scalar x, const label e)
Compute the power of the number x to the integer e.
Definition: scalarI.H:30
labelList second(const UList< labelPair > &p)
Definition: patchToPatch.C:49
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
void sort(UList< T > &)
Definition: UList.C:115
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
IOerror FatalIOError
tmp< DimensionedField< TypeR, GeoMesh, Field > > New(const tmp< DimensionedField< TypeR, GeoMesh, Field >> &tdf1, const word &name, const dimensionSet &dimensions)
dictionary dict
randomGenerator rndGen(653213)