tabulatedDensity.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-2024 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 "tabulatedDensity.H"
27 #include "unintegrable.H"
28 #include "SubField.H"
30 
31 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
32 
33 namespace Foam
34 {
35 namespace distributions
36 {
39 }
40 }
41 
42 
43 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
44 
46 (
47  const unitConversion& defaultUnits,
48  const dictionary& dict,
49  const label sampleQ,
51 )
52 :
54  (
55  typeName,
56  defaultUnits,
57  dict,
58  sampleQ,
59  std::move(rndGen)
60  )
61 {
62  List<Tuple2<scalar, scalar>> values(dict.lookup("distribution"));
63 
64  // Checks
65  forAll(values, i)
66  {
67  if (i && values[i].first() - values[i - 1].first() < 0)
68  {
70  << typeName << ": The probability density function is not "
71  << "in order" << abort(FatalIOError);
72  }
73 
74  if (values[i].second() < 0)
75  {
77  << typeName << ": The probability density function is not "
78  << "positive" << abort(FatalIOError);
79  }
80  }
81 
82  // Optionally read units
83  unitConversion units(defaultUnits);
84  units.readIfPresent("units", dict);
85 
86  // Copy the coordinates
87  x_.resize(values.size());
88  forAll(values, i)
89  {
90  x_[i] = units.toStandard(values[i].first());
91  }
92 
93  // Copy the PDF. Scale if q != 0.
94  PDF_.resize(values.size());
95  forAll(values, i)
96  {
97  PDF_[i] = integerPow(x_[i], q())*values[i].second();
98  }
99 
100  // Compute the CDF
101  CDF_.resize(values.size());
102  CDF_ = unintegrable::integrate(x_, PDF_);
103 
104  // Normalise the PDF and the CDF
105  PDF_ /= CDF_.last();
106  CDF_ /= CDF_.last();
107 
108  // More checks
110  if (q() != 0) validatePositive(dict);
111 }
112 
113 
115 (
116  const tabulatedDensity& d,
117  const label sampleQ
118 )
119 :
121  x_(d.x_),
122  PDF_(d.PDF_),
123  CDF_(d.CDF_)
124 {
125  if (q() == d.q()) return;
126 
127  // Scale the PDF
128  PDF_ = integerPow(x_, q() - d.q())*d.PDF_;
129 
130  // Compute the CDF
131  CDF_ = unintegrable::integrate(x_, PDF_);
132 
133  // Normalise the PDF and the CDF
134  PDF_ /= CDF_.last();
135  CDF_ /= CDF_.last();
136 }
137 
138 
139 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
140 
142 {}
143 
144 
145 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
146 
148 {
149  return unintegrable::sample(x_, PDF_, CDF_, rndGen_.sample01<scalar>());
150 }
151 
152 
154 {
155  return x_.first();
156 }
157 
158 
160 {
161  return x_.last();
162 }
163 
164 
166 {
167  return unintegrable::integrateX(x_, PDF_)->last();
168 }
169 
170 
172 (
173  Ostream& os,
174  const unitConversion& units
175 ) const
176 {
178 
179  // Recover the PDF
180  scalarField PDF(integerPow(x_, -q())*PDF_);
181 
182  // Normalise the PDF
183  PDF /= unintegrable::integrate(x_, PDF)->last();
184 
185  // Construct and write the values
186  List<Tuple2<scalar, scalar>> values(PDF_.size());
187  forAll(values, i)
188  {
189  values[i].first() = units.toUser(x_[i]);
190  values[i].second() = PDF[i];
191  }
192  writeEntry(os, "distribution", values);
193 }
194 
195 
197 (
198  const label
199 ) const
200 {
201  const scalar x0 = min(), x1 = max(), d = 0.1*(x1 - x0);
202 
203  tmp<scalarField> tResult(new scalarField(x_.size() + 4));
204  scalarField& result = tResult.ref();
205 
206  result[0] = Foam::max(x0 - d, q() < 0 ? x0/2 : rootVSmall);
207  result[1] = x0;
208 
209  SubField<scalar>(result, x_.size(), 2) = x_;
210 
211  result[x_.size() + 2] = x1;
212  result[x_.size() + 3] = x1 + d;
213 
214  return tResult;
215 }
216 
217 
220 {
221  tmp<scalarField> tResult(new scalarField(PDF_.size() + 4, 0));
222  scalarField& result = tResult.ref();
223 
224  SubField<scalar>(result, PDF_.size(), 2) = PDF_;
225 
226  return tResult;
227 }
228 
229 
230 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
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
Pre-declare related SubField type.
Definition: SubField.H:63
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 keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:162
Base class for statistical distributions.
Definition: distribution.H:76
virtual void validatePositive(const dictionary &dict) const
Validate that the lower bound is positive.
Definition: distribution.C:51
label q() const
Return the effective distribution size exponent.
Definition: distribution.H:107
virtual void validateBounds(const dictionary &dict) const
Validate that the bounds are monotonic.
Definition: distribution.C:39
Distribution in which the probability density function is given as a table of values.
virtual scalar min() const
Return the minimum value.
virtual scalar sample() const
Sample the distribution.
virtual tmp< scalarField > PDF(const scalarField &x) const
Return the distribution probability density function.
virtual tmp< scalarField > x(const label n) const
Return coordinates to plot across the range of the distribution.
virtual void write(Ostream &os, const unitConversion &units) const
Write to a stream.
virtual scalar max() const
Return the maximum value.
virtual scalar mean() const
Return the mean value.
tabulatedDensity(const unitConversion &units, const dictionary &dict, const label sampleQ, randomGenerator &&rndGen)
Construct from a dictionary.
scalar sample() const
Sample the distribution.
Definition: unintegrable.C:351
static tmp< scalarField > integrate(const scalarField &x, const scalarField &y)
Integrate the values y with respect to the coordinates x.
Definition: unintegrable.C:34
static tmp< scalarField > integrateX(const scalarField &x, const scalarField &y)
Integrate the values x*y with respect to the coordinates x.
Definition: unintegrable.C:54
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:181
Unit conversion structure. Contains the associated dimensions and the multiplier with which to conver...
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:346
defineTypeNameAndDebug(exponential, 0)
addToRunTimeSelectionTable(distribution, exponential, dictionary)
void write(std::ostream &os, const bool binary, List< floatScalar > &fField)
Write floats ascii or binary.
Namespace for OpenFOAM.
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.
labelList first(const UList< labelPair > &p)
Definition: patchToPatch.C:39
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
const HashTable< unitConversion > & units()
Get the table of unit conversions.
void writeEntry(Ostream &os, const HashTable< T, Key, Hash > &ht)
Definition: HashTableIO.C:96
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
IOerror FatalIOError
dictionary dict
randomGenerator rndGen(653213)