distributions: Generalise usage

The distributions have been extended in various ways to permit usage in
a greater variety of situations...

The distributions now have write methods which allow a distribution to
be written into a field file for restart, therby permitting their usage
in boundary conditions and similar. Their read methods now also support
dimension-checked unit conversions for all their parameters.

An additional selector has been added that allows a distribution to be
re-constructed with a different sample size exponent.

The distributions now own their random generator, thereby simplifying
their usage and preventing the need for a (potentially dangling)
reference member. This makes sense now as the random generators do not
rely on global state; individual sub-models can and should own their own
random generator and manage its initialisation and restart. This
principle should be extended to other parts of the code in future.
This commit is contained in:
Will Bainbridge
2024-06-11 10:46:59 +01:00
parent 125902a872
commit e1e0e258c8
55 changed files with 695 additions and 244 deletions

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org \\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2023 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2024 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -57,14 +57,14 @@ dripping::dripping
dict.optionalSubDict(typeName + "Coeffs") dict.optionalSubDict(typeName + "Coeffs")
.lookupOrDefault("minParticlesPerParcel", 1) .lookupOrDefault("minParticlesPerParcel", 1)
), ),
rndGen_(label(0)),
parcelDistribution_ parcelDistribution_
( (
distribution::New distribution::New
( (
dimLength,
dict.optionalSubDict(typeName + "Coeffs") dict.optionalSubDict(typeName + "Coeffs")
.subDict("parcelDistribution"), .subDict("parcelDistribution"),
rndGen_, 0,
0 0
) )
) )

View File

@ -96,9 +96,6 @@ class dripping
//- Minimum number of droplets per parcel //- Minimum number of droplets per parcel
scalar minParticlesPerParcel_; scalar minParticlesPerParcel_;
//- Random number generator
randomGenerator rndGen_;
//- Parcel size PDF model //- Parcel size PDF model
const autoPtr<distribution> parcelDistribution_; const autoPtr<distribution> parcelDistribution_;

View File

@ -1,5 +1,5 @@
type RosinRammler; type RosinRammler;
min 0.001; min 1 [mm];
max 0.015; max 15 [mm];
d 0.014; d 14 [mm];
n 2; n 2 [];

View File

@ -59,15 +59,12 @@ int main(int argc, char *argv[])
static const label nSampled = 100; static const label nSampled = 100;
static const label nSamples = 10000000; static const label nSamples = 10000000;
// Initialise the random number generator
randomGenerator rndGen(clock::getTime());
// Create a zero-size-exponent, zero-sampling-size-exponent distribution // Create a zero-size-exponent, zero-sampling-size-exponent distribution
// from which to get X-coordinates // from which to get X-coordinates
dict.set("Q", 0); dict.set("Q", 0);
autoPtr<distribution> distribution00Ptr autoPtr<distribution> distribution00Ptr
( (
distribution::New(dict, rndGen, 0) distribution::New(unitAny, dict, 0, clock::getTime())
); );
// Get the X-coordinates for the plots // Get the X-coordinates for the plots
@ -105,7 +102,7 @@ int main(int argc, char *argv[])
( (
Q == 0 Q == 0
? distribution00Ptr->clone(0) ? distribution00Ptr->clone(0)
: distribution::New(dict, rndGen, 0) : distribution::New(unitAny, dict, 0, clock::getTime(), false, false)
); );
// Resize // Resize
@ -152,14 +149,19 @@ int main(int argc, char *argv[])
for (label sampleQ = 0; sampleQ <= nQ; ++ sampleQ) for (label sampleQ = 0; sampleQ <= nQ; ++ sampleQ)
{ {
// Create a Q-size-exponent, Q-sampling-size-exponent distribution // Create a Q-size-exponent, Q-sampling-size-exponent distribution
Info<< incrIndent;
autoPtr<distribution> distributionQSampleQPtr autoPtr<distribution> distributionQSampleQPtr
( (
distributionQ0Ptr->clone(sampleQ) distributionQ0Ptr->clone(sampleQ)
); );
distributionQSampleQPtr->mean(); {
distributionQSampleQPtr->report(); OStringStream oss;
Info<< decrIndent; distributionQSampleQPtr->write(oss, unitAny);
writeEntry(oss, "sampleQ", sampleQ);
writeEntry(oss, "min", distributionQSampleQPtr->min());
writeEntry(oss, "mean", distributionQSampleQPtr->mean());
writeEntry(oss, "max", distributionQSampleQPtr->max());
Info<< dictionary(IStringStream(oss.str())());
}
// Resize // Resize
const label QSampleQi = yNames.size(); const label QSampleQi = yNames.size();

View File

@ -1,5 +1,6 @@
type tabulatedCumulative; type tabulatedCumulative;
values units [mm];
distribution
( (
(1 0) (1 0)
(1.73 0.0281384) (1.73 0.0281384)

View File

@ -1,5 +1,6 @@
type tabulatedDensity; type tabulatedDensity;
values units [mm];
distribution
( (
(1 0.0025) (1 0.0025)
(1.73 0.0528) (1.73 0.0528)

View File

@ -24,17 +24,7 @@
mkDir(pdfPath); mkDir(pdfPath);
randomGenerator rndGen(label(0)); autoPtr<distribution> p(distribution::New(unitAny, pdfDictionary, 0, 0));
autoPtr<distribution> p
(
distribution::New
(
pdfDictionary,
rndGen,
0
)
);
const scalar xMin = p->min(); const scalar xMin = p->min();
const scalar xMax = p->max(); const scalar xMax = p->max();

View File

@ -73,27 +73,28 @@ Foam::tmp<Foam::scalarField> Foam::distributions::RosinRammler::Phi
Foam::distributions::RosinRammler::RosinRammler Foam::distributions::RosinRammler::RosinRammler
( (
const unitConversion& units,
const dictionary& dict, const dictionary& dict,
randomGenerator& rndGen, const label sampleQ,
const label sampleQ randomGenerator&& rndGen
) )
: :
FieldDistribution<unintegrableForNonZeroQ, RosinRammler> FieldDistribution<unintegrableForNonZeroQ, RosinRammler>
( (
typeName, typeName,
units,
dict, dict,
rndGen, sampleQ,
sampleQ std::move(rndGen)
), ),
min_(dict.lookupBackwardsCompatible<scalar>({"min", "minValue"})), min_(dict.lookupBackwardsCompatible<scalar>({"min", "minValue"}, units)),
max_(dict.lookupBackwardsCompatible<scalar>({"max", "maxValue"})), max_(dict.lookupBackwardsCompatible<scalar>({"max", "maxValue"}, units)),
d_(dict.lookup<scalar>("d")), d_(dict.lookup<scalar>("d", units)),
n_(dict.lookup<scalar>("n")) n_(dict.lookup<scalar>("n", unitless))
{ {
validateBounds(dict); validateBounds(dict);
validatePositive(dict); validatePositive(dict);
mean(); mean();
report();
} }
@ -147,6 +148,21 @@ Foam::scalar Foam::distributions::RosinRammler::max() const
} }
void Foam::distributions::RosinRammler::write
(
Ostream& os,
const unitConversion& units
) const
{
FieldDistribution<unintegrableForNonZeroQ, RosinRammler>::write(os, units);
writeEntry(os, "min", units, min_);
writeEntry(os, "max", units, max_);
writeEntry(os, "d", units, d_);
writeEntry(os, "n", unitless, n_);
}
Foam::tmp<Foam::scalarField> Foam::tmp<Foam::scalarField>
Foam::distributions::RosinRammler::x(const label n) const Foam::distributions::RosinRammler::x(const label n) const
{ {

View File

@ -124,9 +124,10 @@ public:
//- Construct from a dictionary //- Construct from a dictionary
RosinRammler RosinRammler
( (
const unitConversion& units,
const dictionary& dict, const dictionary& dict,
randomGenerator& rndGen, const label sampleQ,
const label sampleQ randomGenerator&& rndGen
); );
//- Construct copy //- Construct copy
@ -157,6 +158,9 @@ public:
//- Return the maximum value //- Return the maximum value
virtual scalar max() const; virtual scalar max() const;
//- Write to a stream
virtual void write(Ostream& os, const unitConversion& units) const;
//- Return coordinates to plot across the range of the distribution //- Return coordinates to plot across the range of the distribution
virtual tmp<scalarField> x(const label n) const; virtual tmp<scalarField> x(const label n) const;
}; };

View File

@ -76,14 +76,15 @@ Foam::distribution::clipPDF
Foam::distribution::distribution Foam::distribution::distribution
( (
const word& name, const word& name,
const unitConversion& units,
const dictionary& dict, const dictionary& dict,
randomGenerator& rndGen, const label sampleQ,
const label sampleQ randomGenerator&& rndGen
) )
: :
rndGen_(rndGen),
Q_(dict.lookup<scalar>("Q")), Q_(dict.lookup<scalar>("Q")),
sampleQ_(sampleQ) sampleQ_(sampleQ),
rndGen_("rndGen", dict, std::move(rndGen))
{ {
if (Q_ < 0) if (Q_ < 0)
{ {
@ -103,22 +104,22 @@ Foam::distribution::distribution
Foam::distribution::distribution Foam::distribution::distribution
( (
randomGenerator& rndGen,
const label Q, const label Q,
const label sampleQ const label sampleQ,
randomGenerator&& rndGen
) )
: :
rndGen_(rndGen),
Q_(Q), Q_(Q),
sampleQ_(sampleQ) sampleQ_(sampleQ),
rndGen_(rndGen)
{} {}
Foam::distribution::distribution(const distribution& d, const label sampleQ) Foam::distribution::distribution(const distribution& d, const label sampleQ)
: :
rndGen_(d.rndGen_),
Q_(d.Q_), Q_(d.Q_),
sampleQ_(sampleQ) sampleQ_(sampleQ),
rndGen_(d.rndGen_)
{} {}
@ -130,10 +131,16 @@ Foam::distribution::~distribution()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::distribution::report() const void Foam::distribution::write(Ostream& os, const unitConversion& units) const
{ {
Info<< indent << "min/average/max value = " << min() << '/' << mean() writeEntry(os, "type", type());
<< '/' << max() << endl; writeEntry(os, "Q", Q_);
}
void Foam::distribution::writeState(Ostream& os) const
{
writeEntry(os, "rndGen", rndGen_);
} }
@ -163,4 +170,24 @@ Foam::tmp<Foam::scalarField> Foam::distribution::x(const label n) const
} }
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
void Foam::writeEntry
(
Ostream& os,
const unitConversion& units,
const distribution& d,
const bool write,
const bool writeState
)
{
os << nl << indent << token::BEGIN_BLOCK << nl << incrIndent;
if (write) d.write(os, units);
if (writeState) d.writeState(os);
os << decrIndent << indent << token::END_BLOCK << endl;
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -79,15 +79,15 @@ protected:
// Protected data // Protected data
//- Reference to a random number generator
randomGenerator& rndGen_;
//- Distribution size exponent //- Distribution size exponent
const label Q_; const label Q_;
//- Sample size exponent //- Sample size exponent
const label sampleQ_; const label sampleQ_;
//- Random number generator
mutable randomGenerator rndGen_;
// Protected Member Functions // Protected Member Functions
@ -130,11 +130,12 @@ public:
distribution, distribution,
dictionary, dictionary,
( (
const unitConversion& units,
const dictionary& dict, const dictionary& dict,
randomGenerator& rndGen, const label sampleQ,
const label sampleQ randomGenerator&& rndGen
), ),
(dict, rndGen, sampleQ) (units, dict, sampleQ, std::move(rndGen))
); );
@ -144,17 +145,18 @@ public:
distribution distribution
( (
const word& name, const word& name,
const unitConversion& units,
const dictionary& dict, const dictionary& dict,
randomGenerator& rndGen, const label sampleQ,
const label sampleQ randomGenerator&& rndGen
); );
//- Construct from components //- Construct from components
distribution distribution
( (
randomGenerator& rndGen,
const label Q, const label Q,
const label sampleQ const label sampleQ,
randomGenerator&& rndGen
); );
//- Construct copy //- Construct copy
@ -170,11 +172,33 @@ public:
} }
//- Selector // Selectors
//- Select from dictionary and a random generator
static autoPtr<distribution> New static autoPtr<distribution> New
( (
const unitConversion& units,
const dictionary& dict, const dictionary& dict,
randomGenerator& rndGen, const label sampleQ,
randomGenerator&& rndGen,
const bool report = true
);
//- Select from a dictionary and a random generator seed and global flag
static autoPtr<distribution> New
(
const unitConversion& units,
const dictionary& dict,
const label sampleQ,
const randomGenerator::seed& s,
const bool global = false,
const bool report = true
);
//- Re-select with a different sample size exponent
static autoPtr<distribution> New
(
autoPtr<distribution>& dPtr,
const label sampleQ const label sampleQ
); );
@ -204,8 +228,11 @@ public:
//- Return the mean value //- Return the mean value
virtual scalar mean() const = 0; virtual scalar mean() const = 0;
//- Report //- Write to a stream
void report() const; virtual void write(Ostream& os, const unitConversion& units) const;
//- Write the state to a stream
virtual void writeState(Ostream& os) const;
//- Return coordinates to plot across the range of the distribution //- Return coordinates to plot across the range of the distribution
virtual tmp<scalarField> x(const label n) const; virtual tmp<scalarField> x(const label n) const;
@ -225,6 +252,16 @@ FOR_ALL_FIELD_TYPES(DISTRIBUTION_TEMPLATED_SAMPLE_TYPE);
#undef DISTRIBUTION_TEMPLATED_SAMPLE_TYPE #undef DISTRIBUTION_TEMPLATED_SAMPLE_TYPE
void writeEntry
(
Ostream& os,
const unitConversion&,
const distribution& d,
const bool write = true,
const bool writeState = true
);
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class FieldDistribution Declaration Class FieldDistribution Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -263,31 +300,10 @@ public:
//- Sample the distribution into components of a primitive type //- Sample the distribution into components of a primitive type
template<class Type> template<class Type>
Type sample() const Type sample() const;
{
Type value;
for (direction i = 0; i < pTraits<Type>::nComponents; ++ i)
{
setComponent(value, i) =
static_cast<const Derived&>(*this).sample();
}
return value;
}
//- Sample the distribution into a field //- Sample the distribution into a field
virtual tmp<scalarField> sample(const label n) const virtual tmp<scalarField> sample(const label n) const;
{
tmp<scalarField> tResult(new scalarField(n));
scalarField& result = tResult.ref();
forAll(result, i)
{
result[i] =
static_cast<const Derived&>(*this).sample();
}
return tResult;
}
}; };
@ -297,6 +313,12 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "distributionTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif #endif
// ************************************************************************* // // ************************************************************************* //

View File

@ -29,14 +29,19 @@ License
Foam::autoPtr<Foam::distribution> Foam::distribution::New Foam::autoPtr<Foam::distribution> Foam::distribution::New
( (
const unitConversion& units,
const dictionary& dict, const dictionary& dict,
randomGenerator& rndGen, const label sampleQ,
const label sampleQ randomGenerator&& rndGen,
const bool report
) )
{ {
const word distributionType(dict.lookup("type")); const word distributionType(dict.lookup("type"));
if (report)
{
Info<< "Selecting " << typeName << " type " << distributionType << endl; Info<< "Selecting " << typeName << " type " << distributionType << endl;
}
dictionaryConstructorTable::iterator cstrIter = dictionaryConstructorTable::iterator cstrIter =
dictionaryConstructorTablePtr_->find(distributionType); dictionaryConstructorTablePtr_->find(distributionType);
@ -50,22 +55,62 @@ Foam::autoPtr<Foam::distribution> Foam::distribution::New
<< exit(FatalError); << exit(FatalError);
} }
Info<< incrIndent;
autoPtr<distribution> distributionPtr autoPtr<distribution> distributionPtr
( (
cstrIter() cstrIter()
( (
units,
dict.optionalSubDict(distributionType + "Distribution"), dict.optionalSubDict(distributionType + "Distribution"),
rndGen, sampleQ,
sampleQ std::move(rndGen)
) )
); );
Info<< decrIndent; if (report)
{
Info<< incrIndent << indent
<< "min/average/max value = "
<< distributionPtr->min() << '/'
<< distributionPtr->mean() << '/'
<< distributionPtr->max()
<< decrIndent << endl;
}
return distributionPtr; return distributionPtr;
} }
Foam::autoPtr<Foam::distribution> Foam::distribution::New
(
const unitConversion& units,
const dictionary& dict,
const label sampleQ,
const randomGenerator::seed& s,
const bool global,
const bool report
)
{
return New(units, dict, sampleQ, randomGenerator(s, global), report);
}
Foam::autoPtr<Foam::distribution> Foam::distribution::New
(
autoPtr<distribution>& dPtr,
const label sampleQ
)
{
if (dPtr->sampleQ_ == sampleQ)
{
return autoPtr<distribution>(dPtr.ptr());
}
else
{
autoPtr<distribution> result(dPtr->clone(sampleQ));
dPtr.clear();
return result;
}
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -0,0 +1,63 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2024 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "distribution.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Base, class Derived>
template<class Type>
Type Foam::FieldDistribution<Base, Derived>::sample() const
{
Type value;
for (direction i = 0; i < pTraits<Type>::nComponents; ++ i)
{
setComponent(value, i) =
static_cast<const Derived&>(*this).sample();
}
return value;
}
template<class Base, class Derived>
Foam::tmp<Foam::scalarField> Foam::FieldDistribution<Base, Derived>::sample
(
const label n
) const
{
tmp<scalarField> tResult(new scalarField(n));
scalarField& result = tResult.ref();
forAll(result, i)
{
result[i] =
static_cast<const Derived&>(*this).sample();
}
return tResult;
}
// ************************************************************************* //

View File

@ -71,26 +71,27 @@ Foam::tmp<Foam::scalarField> Foam::distributions::exponential::Phi
Foam::distributions::exponential::exponential Foam::distributions::exponential::exponential
( (
const unitConversion& units,
const dictionary& dict, const dictionary& dict,
randomGenerator& rndGen, const label sampleQ,
const label sampleQ randomGenerator&& rndGen
) )
: :
FieldDistribution<unintegrableForNonZeroQ, exponential> FieldDistribution<unintegrableForNonZeroQ, exponential>
( (
typeName, typeName,
units,
dict, dict,
rndGen, sampleQ,
sampleQ std::move(rndGen)
), ),
min_(dict.lookupBackwardsCompatible<scalar>({"min", "minValue"})), min_(dict.lookupBackwardsCompatible<scalar>({"min", "minValue"}, units)),
max_(dict.lookupBackwardsCompatible<scalar>({"max", "maxValue"})), max_(dict.lookupBackwardsCompatible<scalar>({"max", "maxValue"}, units)),
lambda_(dict.lookup<scalar>("lambda")) lambda_(dict.lookup<scalar>("lambda", unitless))
{ {
validateBounds(dict); validateBounds(dict);
validatePositive(dict); validatePositive(dict);
mean(); mean();
report();
} }
@ -143,6 +144,20 @@ Foam::scalar Foam::distributions::exponential::max() const
} }
void Foam::distributions::exponential::write
(
Ostream& os,
const unitConversion& units
) const
{
FieldDistribution<unintegrableForNonZeroQ, exponential>::write(os, units);
writeEntry(os, "min", units, min_);
writeEntry(os, "max", units, max_);
writeEntry(os, "lambda", unitless, lambda_);
}
Foam::tmp<Foam::scalarField> Foam::tmp<Foam::scalarField>
Foam::distributions::exponential::x(const label n) const Foam::distributions::exponential::x(const label n) const
{ {

View File

@ -114,9 +114,10 @@ public:
//- Construct from a dictionary //- Construct from a dictionary
exponential exponential
( (
const unitConversion& units,
const dictionary& dict, const dictionary& dict,
randomGenerator& rndGen, const label sampleQ,
const label sampleQ randomGenerator&& rndGen
); );
//- Construct copy //- Construct copy
@ -147,6 +148,9 @@ public:
//- Return the maximum value //- Return the maximum value
virtual scalar max() const; virtual scalar max() const;
//- Write to a stream
virtual void write(Ostream& os, const unitConversion& units) const;
//- Return coordinates to plot across the range of the distribution //- Return coordinates to plot across the range of the distribution
virtual tmp<scalarField> x(const label n) const; virtual tmp<scalarField> x(const label n) const;
}; };

View File

@ -42,16 +42,20 @@ namespace distributions
Foam::distributions::fixedValue::fixedValue Foam::distributions::fixedValue::fixedValue
( (
const unitConversion& units,
const dictionary& dict, const dictionary& dict,
randomGenerator& rndGen, const label,
const label randomGenerator&& rndGen
) )
: :
FieldDistribution<distribution, fixedValue>(rndGen, -labelMax, -labelMax), FieldDistribution<distribution, fixedValue>
value_(dict.lookup<scalar>("value")) (
{ -labelMax,
report(); -labelMax,
} std::move(rndGen)
),
value_(dict.lookup<scalar>("value", units))
{}
Foam::distributions::fixedValue::fixedValue Foam::distributions::fixedValue::fixedValue
@ -97,6 +101,18 @@ Foam::scalar Foam::distributions::fixedValue::mean() const
} }
void Foam::distributions::fixedValue::write
(
Ostream& os,
const unitConversion& units
) const
{
FieldDistribution<distribution, fixedValue>::write(os, units);
writeEntry(os, "value", units, value_);
}
Foam::tmp<Foam::scalarField> Foam::tmp<Foam::scalarField>
Foam::distributions::fixedValue::x(const label n) const Foam::distributions::fixedValue::x(const label n) const
{ {

View File

@ -81,9 +81,10 @@ public:
//- Construct from a dictionary //- Construct from a dictionary
fixedValue fixedValue
( (
const unitConversion& units,
const dictionary& dict, const dictionary& dict,
randomGenerator& rndGen, const label sampleQ,
const label sampleQ randomGenerator&& rndGen
); );
//- Construct copy //- Construct copy
@ -117,6 +118,9 @@ public:
//- Return the mean value //- Return the mean value
virtual scalar mean() const; virtual scalar mean() const;
//- Write to a stream
virtual void write(Ostream& os, const unitConversion& units) const;
//- Return coordinates to plot across the range of the distribution //- Return coordinates to plot across the range of the distribution
virtual tmp<scalarField> x(const label n) const; virtual tmp<scalarField> x(const label n) const;

View File

@ -112,35 +112,37 @@ Foam::tmp<Foam::scalarField> Foam::distributions::multiNormal::Phi
Foam::distributions::multiNormal::multiNormal Foam::distributions::multiNormal::multiNormal
( (
const unitConversion& units,
const dictionary& dict, const dictionary& dict,
randomGenerator& rndGen, const label sampleQ,
const label sampleQ randomGenerator&& rndGen
) )
: :
FieldDistribution<unintegrableForNonZeroQ, multiNormal> FieldDistribution<unintegrableForNonZeroQ, multiNormal>
( (
typeName, typeName,
units,
dict, dict,
rndGen, sampleQ,
sampleQ std::move(rndGen)
), ),
cumulativeStrengths_(readCumulativeStrengths(dict)) cumulativeStrengths_(readCumulativeStrengths(dict))
{ {
const scalar min const scalar min
( (
dict.lookupBackwardsCompatible<scalar>({"min", "minValue"}) dict.lookupBackwardsCompatible<scalar>({"min", "minValue"}, units)
); );
const scalar max const scalar max
( (
dict.lookupBackwardsCompatible<scalar>({"max", "maxValue"}) dict.lookupBackwardsCompatible<scalar>({"max", "maxValue"}, units)
); );
const scalarList mu const scalarList mu
( (
dict.lookupBackwardsCompatible<scalarList>({"mu", "expectation"}) dict.lookupBackwardsCompatible<scalarList>({"mu", "expectation"}, units)
); );
const scalarList sigma const scalarList sigma
( (
dict.lookup<scalarList>("sigma") dict.lookup<scalarList>("sigma", units)
); );
if if
@ -164,9 +166,9 @@ Foam::distributions::multiNormal::multiNormal
i, i,
new normal new normal
( (
rndGen_,
0, 0,
0, 0,
rndGen_.generator(),
-1, -1,
min, min,
max, max,
@ -179,7 +181,6 @@ Foam::distributions::multiNormal::multiNormal
validateBounds(dict); validateBounds(dict);
if (q() != 0) validatePositive(dict); if (q() != 0) validatePositive(dict);
mean(); mean();
report();
} }
@ -200,9 +201,9 @@ Foam::distributions::multiNormal::multiNormal
i, i,
new normal new normal
( (
rndGen_,
0, 0,
0, 0,
randomGenerator(d.distributions_[i].rndGen_),
-1, -1,
d.distributions_[i].min_, d.distributions_[i].min_,
d.distributions_[i].max_, d.distributions_[i].max_,
@ -257,6 +258,29 @@ Foam::scalar Foam::distributions::multiNormal::max() const
} }
void Foam::distributions::multiNormal::write
(
Ostream& os,
const unitConversion& units
) const
{
FieldDistribution<unintegrableForNonZeroQ, multiNormal>::write(os, units);
writeEntry(os, "min", units, distributions_[0].min());
writeEntry(os, "max", units, distributions_[0].max());
scalarList mu(distributions_.size()), sigma(distributions_.size());
forAll(distributions_, i)
{
mu[i] = distributions_[i].mu();
sigma[i] = distributions_[i].sigma();
}
writeEntry(os, "mu", units, mu);
writeEntry(os, "sigma", units, sigma);
}
Foam::tmp<Foam::scalarField> Foam::tmp<Foam::scalarField>
Foam::distributions::multiNormal::x(const label n) const Foam::distributions::multiNormal::x(const label n) const
{ {

View File

@ -118,9 +118,10 @@ public:
//- Construct from a dictionary //- Construct from a dictionary
multiNormal multiNormal
( (
const unitConversion& units,
const dictionary& dict, const dictionary& dict,
randomGenerator& rndGen, const label sampleQ,
const label sampleQ randomGenerator&& rndGen
); );
//- Construct copy //- Construct copy
@ -151,6 +152,9 @@ public:
//- Return the maximum value //- Return the maximum value
virtual scalar max() const; virtual scalar max() const;
//- Write stream
virtual void write(Ostream& os, const unitConversion& units) const;
//- Return coordinates to plot across the range of the distribution //- Return coordinates to plot across the range of the distribution
virtual tmp<scalarField> x(const label n) const; virtual tmp<scalarField> x(const label n) const;
}; };

View File

@ -87,35 +87,36 @@ Foam::scalar Foam::distributions::normal::sampleForZeroQ(const scalar s) const
Foam::distributions::normal::normal Foam::distributions::normal::normal
( (
const unitConversion& units,
const dictionary& dict, const dictionary& dict,
randomGenerator& rndGen, const label sampleQ,
const label sampleQ randomGenerator&& rndGen
) )
: :
FieldDistribution<unintegrableForNonZeroQ, normal> FieldDistribution<unintegrableForNonZeroQ, normal>
( (
typeName, typeName,
units,
dict, dict,
rndGen, sampleQ,
sampleQ std::move(rndGen)
), ),
min_(dict.lookupBackwardsCompatible<scalar>({"min", "minValue"})), min_(dict.lookupBackwardsCompatible<scalar>({"min", "minValue"}, units)),
max_(dict.lookupBackwardsCompatible<scalar>({"max", "maxValue"})), max_(dict.lookupBackwardsCompatible<scalar>({"max", "maxValue"}, units)),
mu_(dict.lookupBackwardsCompatible<scalar>({"mu", "expectation"})), mu_(dict.lookupBackwardsCompatible<scalar>({"mu", "expectation"}, units)),
sigma_(dict.lookup<scalar>("sigma")) sigma_(dict.lookup<scalar>("sigma", units))
{ {
validateBounds(dict); validateBounds(dict);
if (q() != 0) validatePositive(dict); if (q() != 0) validatePositive(dict);
mean(); mean();
report();
} }
Foam::distributions::normal::normal Foam::distributions::normal::normal
( (
randomGenerator& rndGen,
const label Q, const label Q,
const label sampleQ, const label sampleQ,
randomGenerator&& rndGen,
const label n, const label n,
const scalar min, const scalar min,
const scalar max, const scalar max,
@ -123,7 +124,13 @@ Foam::distributions::normal::normal
const scalar sigma const scalar sigma
) )
: :
FieldDistribution<unintegrableForNonZeroQ, normal>(rndGen, Q, sampleQ, n), FieldDistribution<unintegrableForNonZeroQ, normal>
(
Q,
sampleQ,
std::move(rndGen),
n
),
min_(min), min_(min),
max_(max), max_(max),
mu_(mu), mu_(mu),
@ -195,6 +202,21 @@ Foam::scalar Foam::distributions::normal::mean() const
} }
void Foam::distributions::normal::write
(
Ostream& os,
const unitConversion& units
) const
{
FieldDistribution<unintegrableForNonZeroQ, normal>::write(os, units);
writeEntry(os, "min", units, min_);
writeEntry(os, "max", units, max_);
writeEntry(os, "mu", units, mu_);
writeEntry(os, "sigma", units, sigma_);
}
Foam::tmp<Foam::scalarField> Foam::tmp<Foam::scalarField>
Foam::distributions::normal::x(const label n) const Foam::distributions::normal::x(const label n) const
{ {

View File

@ -126,17 +126,18 @@ public:
//- Construct from a dictionary //- Construct from a dictionary
normal normal
( (
const unitConversion& units,
const dictionary& dict, const dictionary& dict,
randomGenerator& rndGen, const label sampleQ,
const label sampleQ randomGenerator&& rndGen
); );
//- Construct from components //- Construct from components
normal normal
( (
randomGenerator& rndGen,
const label Q, const label Q,
const label sampleQ, const label sampleQ,
randomGenerator&& rndGen,
const label n, const label n,
const scalar min, const scalar min,
const scalar max, const scalar max,
@ -175,6 +176,21 @@ public:
//- Return the mean value //- Return the mean value
virtual scalar mean() const; virtual scalar mean() const;
//- Return the mean value
inline scalar mu() const
{
return mu_;
}
//- Return the standard deviation
inline scalar sigma() const
{
return sigma_;
}
//- Write to a stream
virtual void write(Ostream& os, const unitConversion& units) const;
//- Return coordinates to plot across the range of the distribution //- Return coordinates to plot across the range of the distribution
virtual tmp<scalarField> x(const label n) const; virtual tmp<scalarField> x(const label n) const;
}; };

View File

@ -64,15 +64,25 @@ Foam::scalar Foam::distributions::standardNormal::approxErfInv(const scalar y)
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::distributions::standardNormal::standardNormal(randomGenerator& rndGen) Foam::distributions::standardNormal::standardNormal(randomGenerator&& rndGen)
: :
FieldDistribution<distribution, standardNormal>(rndGen, 0, 0) FieldDistribution<distribution, standardNormal>(0, 0, std::move(rndGen))
{}
Foam::distributions::standardNormal::standardNormal
(
const randomGenerator::seed& s,
const bool global
)
:
standardNormal(randomGenerator(s, global))
{} {}
Foam::distributions::standardNormal::standardNormal(const standardNormal& d) Foam::distributions::standardNormal::standardNormal(const standardNormal& d)
: :
FieldDistribution<distribution, standardNormal>(d.rndGen_, 0, 0) FieldDistribution<distribution, standardNormal>(d, 0)
{} {}

View File

@ -87,7 +87,14 @@ public:
// Constructors // Constructors
//- Construct from a random generator //- Construct from a random generator
standardNormal(randomGenerator& rndGen); standardNormal(randomGenerator&& rndGen);
//- Construct from a seed
standardNormal
(
const randomGenerator::seed& s,
const bool global = false
);
//- Construct copy //- Construct copy
standardNormal(const standardNormal& d); standardNormal(const standardNormal& d);

View File

@ -44,20 +44,22 @@ namespace distributions
Foam::distributions::tabulatedCumulative::tabulatedCumulative Foam::distributions::tabulatedCumulative::tabulatedCumulative
( (
const unitConversion& defaultUnits,
const dictionary& dict, const dictionary& dict,
randomGenerator& rndGen, const label sampleQ,
const label sampleQ randomGenerator&& rndGen
) )
: :
FieldDistribution<distribution, tabulatedCumulative> FieldDistribution<distribution, tabulatedCumulative>
( (
typeName, typeName,
defaultUnits,
dict, dict,
rndGen, sampleQ,
sampleQ std::move(rndGen)
) )
{ {
List<Pair<scalar>> values(dict.lookup("distribution")); List<Tuple2<scalar, scalar>> values(dict.lookup("distribution"));
// Checks // Checks
if (values.first().second() != 0) if (values.first().second() != 0)
@ -84,11 +86,15 @@ Foam::distributions::tabulatedCumulative::tabulatedCumulative
} }
} }
// Optionally read units
unitConversion units(defaultUnits);
units.readIfPresent("units", dict);
// Copy the coordinates // Copy the coordinates
x_.resize(values.size()); x_.resize(values.size());
forAll(values, i) forAll(values, i)
{ {
x_[i] = values[i].first(); x_[i] = units.toStandard(values[i].first());
} }
// Set the CDF. Copy if q == 0. Re-integrated if q != 0. // Set the CDF. Copy if q == 0. Re-integrated if q != 0.
@ -115,7 +121,6 @@ Foam::distributions::tabulatedCumulative::tabulatedCumulative
// More checks // More checks
validateBounds(dict); validateBounds(dict);
if (q() != 0) validatePositive(dict); if (q() != 0) validatePositive(dict);
report();
} }
@ -185,6 +190,39 @@ Foam::scalar Foam::distributions::tabulatedCumulative::mean() const
} }
void Foam::distributions::tabulatedCumulative::write
(
Ostream& os,
const unitConversion& units
) const
{
FieldDistribution<distribution, tabulatedCumulative>::write(os, units);
// Recover the CDF
scalarField CDF(CDF_.size());
CDF[0] = 0;
for (label i = 1; i < CDF_.size(); ++ i)
{
CDF[i] =
CDF[i - 1]
+ integerPow((x_[i] + x_[i - 1])/2, -q())
*(CDF_[i] - CDF_[i - 1]);
}
// Normalise the CDF
CDF /= CDF.last();
// Construct and write the values
List<Tuple2<scalar, scalar>> values(CDF_.size());
forAll(values, i)
{
values[i].first() = units.toUser(x_[i]);
values[i].second() = CDF[i];
}
writeEntry(os, "distribution", values);
}
Foam::tmp<Foam::scalarField> Foam::distributions::tabulatedCumulative::x Foam::tmp<Foam::scalarField> Foam::distributions::tabulatedCumulative::x
( (
const label const label

View File

@ -102,9 +102,10 @@ public:
//- Construct from a dictionary //- Construct from a dictionary
tabulatedCumulative tabulatedCumulative
( (
const unitConversion& units,
const dictionary& dict, const dictionary& dict,
randomGenerator& rndGen, const label sampleQ,
const label sampleQ randomGenerator&& rndGen
); );
//- Construct copy //- Construct copy
@ -141,6 +142,9 @@ public:
//- Return the mean value //- Return the mean value
virtual scalar mean() const; virtual scalar mean() const;
//- Write to a stream
virtual void write(Ostream& os, const unitConversion& units) const;
//- Return coordinates to plot across the range of the distribution //- Return coordinates to plot across the range of the distribution
virtual tmp<scalarField> x(const label n) const; virtual tmp<scalarField> x(const label n) const;

View File

@ -44,20 +44,22 @@ namespace distributions
Foam::distributions::tabulatedDensity::tabulatedDensity Foam::distributions::tabulatedDensity::tabulatedDensity
( (
const unitConversion& defaultUnits,
const dictionary& dict, const dictionary& dict,
randomGenerator& rndGen, const label sampleQ,
const label sampleQ randomGenerator&& rndGen
) )
: :
FieldDistribution<distribution, tabulatedDensity> FieldDistribution<distribution, tabulatedDensity>
( (
typeName, typeName,
defaultUnits,
dict, dict,
rndGen, sampleQ,
sampleQ std::move(rndGen)
) )
{ {
List<Pair<scalar>> values(dict.lookup("distribution")); List<Tuple2<scalar, scalar>> values(dict.lookup("distribution"));
// Checks // Checks
forAll(values, i) forAll(values, i)
@ -77,11 +79,15 @@ Foam::distributions::tabulatedDensity::tabulatedDensity
} }
} }
// Optionally read units
unitConversion units(defaultUnits);
units.readIfPresent("units", dict);
// Copy the coordinates // Copy the coordinates
x_.resize(values.size()); x_.resize(values.size());
forAll(values, i) forAll(values, i)
{ {
x_[i] = values[i].first(); x_[i] = units.toStandard(values[i].first());
} }
// Copy the PDF. Scale if q != 0. // Copy the PDF. Scale if q != 0.
@ -102,7 +108,6 @@ Foam::distributions::tabulatedDensity::tabulatedDensity
// More checks // More checks
validateBounds(dict); validateBounds(dict);
if (q() != 0) validatePositive(dict); if (q() != 0) validatePositive(dict);
report();
} }
@ -163,6 +168,31 @@ Foam::scalar Foam::distributions::tabulatedDensity::mean() const
} }
void Foam::distributions::tabulatedDensity::write
(
Ostream& os,
const unitConversion& units
) const
{
FieldDistribution<distribution, tabulatedDensity>::write(os, units);
// Recover the PDF
scalarField PDF(integerPow(x_, -q())*PDF_);
// Normalise the PDF
PDF /= unintegrable::integrate(x_, PDF)->last();
// Construct and write the values
List<Tuple2<scalar, scalar>> values(PDF_.size());
forAll(values, i)
{
values[i].first() = units.toUser(x_[i]);
values[i].second() = PDF[i];
}
writeEntry(os, "distribution", values);
}
Foam::tmp<Foam::scalarField> Foam::distributions::tabulatedDensity::x Foam::tmp<Foam::scalarField> Foam::distributions::tabulatedDensity::x
( (
const label const label

View File

@ -103,9 +103,10 @@ public:
//- Construct from a dictionary //- Construct from a dictionary
tabulatedDensity tabulatedDensity
( (
const unitConversion& units,
const dictionary& dict, const dictionary& dict,
randomGenerator& rndGen, const label sampleQ,
const label sampleQ randomGenerator&& rndGen
); );
//- Construct copy //- Construct copy
@ -139,6 +140,9 @@ public:
//- Return the mean value //- Return the mean value
virtual scalar mean() const; virtual scalar mean() const;
//- Write to a stream
virtual void write(Ostream& os, const unitConversion& units) const;
//- Return coordinates to plot across the range of the distribution //- Return coordinates to plot across the range of the distribution
virtual tmp<scalarField> x(const label n) const; virtual tmp<scalarField> x(const label n) const;

View File

@ -57,20 +57,27 @@ Foam::scalar Foam::distributions::uniform::Phi(const scalar x) const
Foam::distributions::uniform::uniform Foam::distributions::uniform::uniform
( (
const unitConversion& units,
const dictionary& dict, const dictionary& dict,
randomGenerator& rndGen, const label sampleQ,
const label sampleQ randomGenerator&& rndGen
) )
: :
FieldDistribution<distribution, uniform>(typeName, dict, rndGen, sampleQ), FieldDistribution<distribution, uniform>
min_(dict.lookupBackwardsCompatible<scalar>({"min", "minValue"})), (
max_(dict.lookupBackwardsCompatible<scalar>({"max", "maxValue"})), typeName,
units,
dict,
sampleQ,
std::move(rndGen)
),
min_(dict.lookupBackwardsCompatible<scalar>({"min", "minValue"}, units)),
max_(dict.lookupBackwardsCompatible<scalar>({"max", "maxValue"}, units)),
Phi0_(Phi(min_)), Phi0_(Phi(min_)),
Phi1_(Phi(max_)) Phi1_(Phi(max_))
{ {
validateBounds(dict); validateBounds(dict);
if (q() != 0) validatePositive(dict); if (q() != 0) validatePositive(dict);
report();
} }
@ -137,6 +144,19 @@ Foam::scalar Foam::distributions::uniform::mean() const
} }
void Foam::distributions::uniform::write
(
Ostream& os,
const unitConversion& units
) const
{
distribution::write(os, units);
writeEntry(os, "min", units, min_);
writeEntry(os, "max", units, max_);
}
Foam::tmp<Foam::scalarField> Foam::tmp<Foam::scalarField>
Foam::distributions::uniform::PDF(const scalarField& x) const Foam::distributions::uniform::PDF(const scalarField& x) const
{ {

View File

@ -99,9 +99,10 @@ public:
//- Construct from a dictionary //- Construct from a dictionary
uniform uniform
( (
const unitConversion& units,
const dictionary& dict, const dictionary& dict,
randomGenerator& rndGen, const label sampleQ,
const label sampleQ randomGenerator&& rndGen
); );
//- Construct copy //- Construct copy
@ -135,6 +136,9 @@ public:
//- Return the mean value //- Return the mean value
virtual scalar mean() const; virtual scalar mean() const;
//- Write to a stream
virtual void write(Ostream& os, const unitConversion& units) const;
//- Return the distribution probability density function //- Return the distribution probability density function
virtual tmp<scalarField> PDF(const scalarField& x) const; virtual tmp<scalarField> PDF(const scalarField& x) const;
}; };

View File

@ -305,25 +305,26 @@ Foam::distributions::unintegrable::Phi01() const
Foam::distributions::unintegrable::unintegrable Foam::distributions::unintegrable::unintegrable
( (
const word& name, const word& name,
const unitConversion& units,
const dictionary& dict, const dictionary& dict,
randomGenerator& rndGen, const label sampleQ,
const label sampleQ randomGenerator&& rndGen
) )
: :
distribution(name, dict, rndGen, sampleQ), distribution(name, units, dict, sampleQ, std::move(rndGen)),
n_((1<<dict.lookupOrDefault<label>("level", 16)) + 1) n_((1<<dict.lookupOrDefault<label>("level", 16)) + 1)
{} {}
Foam::distributions::unintegrable::unintegrable Foam::distributions::unintegrable::unintegrable
( (
randomGenerator& rndGen,
const label Q, const label Q,
const label sampleQ, const label sampleQ,
randomGenerator&& rndGen,
const label n const label n
) )
: :
distribution(rndGen, Q, sampleQ), distribution(Q, sampleQ, std::move(rndGen)),
n_(n) n_(n)
{} {}
@ -373,6 +374,22 @@ Foam::scalar Foam::distributions::unintegrable::mean() const
} }
void Foam::distributions::unintegrable::write
(
Ostream& os,
const unitConversion& units
) const
{
distribution::write(os, units);
// Recover the level
label n = n_ - 1, level = 0;
while (n >>= 1) ++ level;
writeEntryIfDifferent(os, "level", 16, level);
}
Foam::tmp<Foam::scalarField> Foam::distributions::unintegrable::PDF Foam::tmp<Foam::scalarField> Foam::distributions::unintegrable::PDF
( (
const scalarField& x const scalarField& x

View File

@ -187,17 +187,18 @@ public:
unintegrable unintegrable
( (
const word& name, const word& name,
const unitConversion& units,
const dictionary& dict, const dictionary& dict,
randomGenerator& rndGen, const label sampleQ,
const label sampleQ randomGenerator&& rndGen
); );
//- Construct from components //- Construct from components
unintegrable unintegrable
( (
randomGenerator& rndGen,
const label Q, const label Q,
const label sampleQ, const label sampleQ,
randomGenerator&& rndGen,
const label n const label n
); );
@ -220,6 +221,9 @@ public:
//- Return the mean value //- Return the mean value
virtual scalar mean() const; virtual scalar mean() const;
//- Write to a stream
virtual void write(Ostream& os, const unitConversion& units) const;
//- Return coordinates to plot across the range of the distribution //- Return coordinates to plot across the range of the distribution
using distribution::x; using distribution::x;

View File

@ -30,7 +30,6 @@ License
#include "constants.H" #include "constants.H"
#include "zeroGradientFvPatchFields.H" #include "zeroGradientFvPatchFields.H"
#include "polyMeshTetDecomposition.H" #include "polyMeshTetDecomposition.H"
#include "standardNormal.H"
using namespace Foam::constant; using namespace Foam::constant;
@ -651,6 +650,7 @@ Foam::DSMCCloud<ParcelType>::DSMCCloud
), ),
constProps_(), constProps_(),
rndGen_(label(149382906)), rndGen_(label(149382906)),
stdNormal_(rndGen_.generator()),
boundaryT_ boundaryT_
( (
volScalarField volScalarField
@ -905,6 +905,7 @@ Foam::DSMCCloud<ParcelType>::DSMCCloud
), ),
constProps_(), constProps_(),
rndGen_(label(971501)), rndGen_(label(971501)),
stdNormal_(rndGen_.generator()),
boundaryT_ boundaryT_
( (
volScalarField volScalarField
@ -1043,7 +1044,7 @@ Foam::vector Foam::DSMCCloud<ParcelType>::equipartitionLinearVelocity
{ {
return return
sqrt(physicoChemical::k.value()*temperature/mass) sqrt(physicoChemical::k.value()*temperature/mass)
*distributions::standardNormal(rndGen_).sample<vector>(); *stdNormal_.sample<vector>();
} }

View File

@ -40,6 +40,7 @@ SourceFiles
#include "IOdictionary.H" #include "IOdictionary.H"
#include "autoPtr.H" #include "autoPtr.H"
#include "randomGenerator.H" #include "randomGenerator.H"
#include "standardNormal.H"
#include "fvMesh.H" #include "fvMesh.H"
#include "volFields.H" #include "volFields.H"
#include "scalarIOField.H" #include "scalarIOField.H"
@ -143,6 +144,9 @@ class DSMCCloud
//- Random number generator //- Random number generator
randomGenerator rndGen_; randomGenerator rndGen_;
//- Standard normal distribution
distributions::standardNormal stdNormal_;
// boundary value fields // boundary value fields
@ -267,9 +271,12 @@ public:
inline const typename ParcelType::constantProperties& inline const typename ParcelType::constantProperties&
constProps(label typeId) const; constProps(label typeId) const;
//- Return references to the random object //- Return reference to the random generator
inline randomGenerator& rndGen(); inline randomGenerator& rndGen();
//- Return reference to the standard normal distribution
inline distributions::standardNormal& stdNormal();
// References to the boundary fields for surface data collection // References to the boundary fields for surface data collection

View File

@ -124,6 +124,14 @@ inline Foam::randomGenerator& Foam::DSMCCloud<ParcelType>::rndGen()
} }
template<class ParcelType>
inline Foam::distributions::standardNormal&
Foam::DSMCCloud<ParcelType>::stdNormal()
{
return stdNormal_;
}
template<class ParcelType> template<class ParcelType>
inline Foam::volScalarField::Boundary& inline Foam::volScalarField::Boundary&
Foam::DSMCCloud<ParcelType>::qBF() Foam::DSMCCloud<ParcelType>::qBF()

View File

@ -146,8 +146,8 @@ void Foam::FreeStream<CloudType>::inflow()
const scalar deltaT = mesh.time().deltaTValue(); const scalar deltaT = mesh.time().deltaTValue();
randomGenerator& rndGen(cloud.rndGen()); randomGenerator& rndGen = cloud.rndGen();
distributions::standardNormal stdNormal(rndGen); distributions::standardNormal& stdNormal = cloud.stdNormal();
scalar sqrtPi = sqrt(pi); scalar sqrtPi = sqrt(pi);

View File

@ -81,8 +81,8 @@ void Foam::MaxwellianThermal<CloudType>::correct
CloudType& cloud(this->owner()); CloudType& cloud(this->owner());
randomGenerator& rndGen(cloud.rndGen()); randomGenerator& rndGen = cloud.rndGen();
distributions::standardNormal stdNormal(rndGen); distributions::standardNormal& stdNormal = cloud.stdNormal();
while (mag(Ut) < small) while (mag(Ut) < small)
{ {

View File

@ -79,8 +79,8 @@ void Foam::MixedDiffuseSpecular<CloudType>::correct
CloudType& cloud(this->owner()); CloudType& cloud(this->owner());
randomGenerator& rndGen(cloud.rndGen()); randomGenerator& rndGen = cloud.rndGen();
distributions::standardNormal stdNormal(rndGen); distributions::standardNormal& stdNormal = cloud.stdNormal();
if (diffuseFraction_ > rndGen.scalar01()) if (diffuseFraction_ > rndGen.scalar01())
{ {

View File

@ -1080,7 +1080,8 @@ Foam::moleculeCloud::moleculeCloud
cellOccupancy_(mesh_.nCells()), cellOccupancy_(mesh_.nCells()),
il_(mesh_, pot_.pairPotentials().rCutMax(), false), il_(mesh_, pot_.pairPotentials().rCutMax(), false),
constPropList_(), constPropList_(),
rndGen_(clock::getTime()) rndGen_(clock::getTime()),
stdNormal_(rndGen_.generator())
{ {
if (readFields) if (readFields)
{ {
@ -1110,7 +1111,8 @@ Foam::moleculeCloud::moleculeCloud
pot_(pot), pot_(pot),
il_(mesh_, 0.0, false), il_(mesh_, 0.0, false),
constPropList_(), constPropList_(),
rndGen_(clock::getTime()) rndGen_(clock::getTime()),
stdNormal_(rndGen_.generator())
{ {
if (readFields) if (readFields)
{ {

View File

@ -43,6 +43,7 @@ SourceFiles
#include "InteractionLists.H" #include "InteractionLists.H"
#include "labelVector.H" #include "labelVector.H"
#include "randomGenerator.H" #include "randomGenerator.H"
#include "standardNormal.H"
#include "fileName.H" #include "fileName.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -72,6 +73,8 @@ class moleculeCloud
randomGenerator rndGen_; randomGenerator rndGen_;
distributions::standardNormal stdNormal_;
// Private Member Functions // Private Member Functions
@ -193,6 +196,8 @@ public:
inline randomGenerator& rndGen(); inline randomGenerator& rndGen();
inline distributions::standardNormal& stdNormal();
// Member Functions // Member Functions

View File

@ -24,7 +24,6 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "constants.H" #include "constants.H"
#include "standardNormal.H"
using namespace Foam::constant; using namespace Foam::constant;
@ -304,7 +303,7 @@ inline Foam::vector Foam::moleculeCloud::equipartitionLinearVelocity
{ {
return return
sqrt(physicoChemical::k.value()*temperature/mass) sqrt(physicoChemical::k.value()*temperature/mass)
*distributions::standardNormal(rndGen_).sample<vector>(); *stdNormal_.sample<vector>();
} }
@ -316,24 +315,22 @@ inline Foam::vector Foam::moleculeCloud::equipartitionAngularMomentum
{ {
scalar sqrtKbT = sqrt(physicoChemical::k.value()*temperature); scalar sqrtKbT = sqrt(physicoChemical::k.value()*temperature);
distributions::standardNormal stdNormal(rndGen_);
if (cP.linearMolecule()) if (cP.linearMolecule())
{ {
return sqrtKbT*vector return sqrtKbT*vector
( (
0.0, 0.0,
sqrt(cP.momentOfInertia().yy())*stdNormal.sample(), sqrt(cP.momentOfInertia().yy())*stdNormal_.sample(),
sqrt(cP.momentOfInertia().zz())*stdNormal.sample() sqrt(cP.momentOfInertia().zz())*stdNormal_.sample()
); );
} }
else else
{ {
return sqrtKbT*vector return sqrtKbT*vector
( (
sqrt(cP.momentOfInertia().xx())*stdNormal.sample(), sqrt(cP.momentOfInertia().xx())*stdNormal_.sample(),
sqrt(cP.momentOfInertia().yy())*stdNormal.sample(), sqrt(cP.momentOfInertia().yy())*stdNormal_.sample(),
sqrt(cP.momentOfInertia().zz())*stdNormal.sample() sqrt(cP.momentOfInertia().zz())*stdNormal_.sample()
); );
} }
} }
@ -387,4 +384,10 @@ inline Foam::randomGenerator& Foam::moleculeCloud::rndGen()
} }
inline Foam::distributions::standardNormal& Foam::moleculeCloud::stdNormal()
{
return stdNormal_;
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -239,8 +239,6 @@ void Foam::MomentumCloud<CloudType>::cloudReset(MomentumCloud<CloudType>& c)
{ {
CloudType::cloudReset(c); CloudType::cloudReset(c);
rndGen_ = c.rndGen_;
forces_.transfer(c.forces_); forces_.transfer(c.forces_);
functions_.transfer(c.functions_); functions_.transfer(c.functions_);
@ -302,6 +300,7 @@ Foam::MomentumCloud<CloudType>::MomentumCloud
), ),
cpuLoad_(particleProperties_.lookupOrDefault("cpuLoad", false)), cpuLoad_(particleProperties_.lookupOrDefault("cpuLoad", false)),
rndGen_(0), rndGen_(0),
stdNormal_(rndGen_.generator()),
cellOccupancyPtr_(), cellOccupancyPtr_(),
cellLengthScale_(mag(cbrt(this->mesh().V()))), cellLengthScale_(mag(cbrt(this->mesh().V()))),
rho_(rho), rho_(rho),
@ -414,6 +413,7 @@ Foam::MomentumCloud<CloudType>::MomentumCloud
subModelProperties_(c.subModelProperties_), subModelProperties_(c.subModelProperties_),
cpuLoad_(c.cpuLoad_), cpuLoad_(c.cpuLoad_),
rndGen_(c.rndGen_), rndGen_(c.rndGen_),
stdNormal_(c.stdNormal_),
cellOccupancyPtr_(nullptr), cellOccupancyPtr_(nullptr),
cellLengthScale_(c.cellLengthScale_), cellLengthScale_(c.cellLengthScale_),
rho_(c.rho_), rho_(c.rho_),
@ -504,6 +504,7 @@ Foam::MomentumCloud<CloudType>::MomentumCloud
subModelProperties_(dictionary::null), subModelProperties_(dictionary::null),
cpuLoad_(c.cpuLoad_), cpuLoad_(c.cpuLoad_),
rndGen_(0), rndGen_(0),
stdNormal_(rndGen_.generator()),
cellOccupancyPtr_(nullptr), cellOccupancyPtr_(nullptr),
cellLengthScale_(c.cellLengthScale_), cellLengthScale_(c.cellLengthScale_),
rho_(c.rho_), rho_(c.rho_),

View File

@ -56,6 +56,7 @@ SourceFiles
#include "timeIOdictionary.H" #include "timeIOdictionary.H"
#include "autoPtr.H" #include "autoPtr.H"
#include "randomGenerator.H" #include "randomGenerator.H"
#include "standardNormal.H"
#include "fvMesh.H" #include "fvMesh.H"
#include "volFields.H" #include "volFields.H"
#include "fvMatrices.H" #include "fvMatrices.H"
@ -161,6 +162,9 @@ protected:
//- Random number generator - used by some injection routines //- Random number generator - used by some injection routines
mutable randomGenerator rndGen_; mutable randomGenerator rndGen_;
//- Standard normal distribution
mutable distributions::standardNormal stdNormal_;
//- Cell occupancy information for each parcel, (demand driven) //- Cell occupancy information for each parcel, (demand driven)
autoPtr<List<DynamicList<parcelType*>>> cellOccupancyPtr_; autoPtr<List<DynamicList<parcelType*>>> cellOccupancyPtr_;
@ -367,9 +371,12 @@ public:
// Cloud data // Cloud data
//- Return reference to the random object //- Return reference to the random generator
inline randomGenerator& rndGen() const; inline randomGenerator& rndGen() const;
//- Return reference to the standard normal distribution
inline distributions::standardNormal& stdNormal() const;
//- Return the cell occupancy information for each //- Return the cell occupancy information for each
// parcel, non-const access, the caller is // parcel, non-const access, the caller is
// responsible for updating it for its own purposes // responsible for updating it for its own purposes

View File

@ -366,6 +366,14 @@ inline Foam::randomGenerator& Foam::MomentumCloud<CloudType>::rndGen() const
} }
template<class CloudType>
inline Foam::distributions::standardNormal&
Foam::MomentumCloud<CloudType>::stdNormal() const
{
return stdNormal_;
}
template<class CloudType> template<class CloudType>
inline Foam::List<Foam::DynamicList<typename CloudType::particleType*>>& inline Foam::List<Foam::DynamicList<typename CloudType::particleType*>>&
Foam::MomentumCloud<CloudType>::cellOccupancy() Foam::MomentumCloud<CloudType>::cellOccupancy()

View File

@ -101,7 +101,7 @@ Foam::vector Foam::GradientDispersionRAS<CloudType>::update
scalar& tTurb scalar& tTurb
) )
{ {
distributions::standardNormal stdNormal(this->owner().rndGen()); distributions::standardNormal& stdNormal = this->owner().stdNormal();
const scalar cps = 0.16432; const scalar cps = 0.16432;

View File

@ -73,7 +73,7 @@ Foam::vector Foam::StochasticDispersionRAS<CloudType>::update
) )
{ {
randomGenerator& rndGen = this->owner().rndGen(); randomGenerator& rndGen = this->owner().rndGen();
distributions::standardNormal stdNormal(rndGen); distributions::standardNormal& stdNormal = this->owner().stdNormal();
const scalar cps = 0.16432; const scalar cps = 0.16432;

View File

@ -173,9 +173,10 @@ Foam::CellZoneInjection<CloudType>::CellZoneInjection
( (
distribution::New distribution::New
( (
dimLength,
this->coeffDict().subDict("sizeDistribution"), this->coeffDict().subDict("sizeDistribution"),
owner.rndGen(), this->sizeSampleQ(),
this->sizeSampleQ() owner.rndGen().generator()
) )
) )
{ {

View File

@ -199,9 +199,10 @@ Foam::ConeInjection<CloudType>::ConeInjection
( (
distribution::New distribution::New
( (
dimLength,
this->coeffDict().subDict("sizeDistribution"), this->coeffDict().subDict("sizeDistribution"),
owner.rndGen(), this->sizeSampleQ(),
this->sizeSampleQ() owner.rndGen().generator()
) )
), ),
dInner_(vGreat), dInner_(vGreat),

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org \\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2023 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2024 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -83,9 +83,10 @@ Foam::FieldActivatedInjection<CloudType>::FieldActivatedInjection
( (
distribution::New distribution::New
( (
dimLength,
this->coeffDict().subDict("sizeDistribution"), this->coeffDict().subDict("sizeDistribution"),
owner.rndGen(), this->sizeSampleQ(),
this->sizeSampleQ() owner.rndGen().generator()
) )
) )
{ {

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org \\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2023 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2024 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -63,9 +63,10 @@ Foam::ManualInjection<CloudType>::ManualInjection
( (
distribution::New distribution::New
( (
dimLength,
this->coeffDict().subDict("sizeDistribution"), this->coeffDict().subDict("sizeDistribution"),
owner.rndGen(), this->sizeSampleQ(),
this->sizeSampleQ() owner.rndGen().generator()
) )
), ),
ignoreOutOfBounds_ ignoreOutOfBounds_

View File

@ -61,9 +61,10 @@ Foam::PatchFlowRateInjection<CloudType>::PatchFlowRateInjection
( (
distribution::New distribution::New
( (
dimLength,
this->coeffDict().subDict("sizeDistribution"), this->coeffDict().subDict("sizeDistribution"),
owner.rndGen(), this->sizeSampleQ(),
this->sizeSampleQ() owner.rndGen().generator()
) )
) )
{} {}

View File

@ -98,9 +98,10 @@ Foam::PatchInjection<CloudType>::PatchInjection
( (
distribution::New distribution::New
( (
dimLength,
this->coeffDict().subDict("sizeDistribution"), this->coeffDict().subDict("sizeDistribution"),
owner.rndGen(), this->sizeSampleQ(),
this->sizeSampleQ() owner.rndGen().generator()
) )
) )
{ {

View File

@ -70,7 +70,6 @@ Foam::BrownianMotionForce<CloudType>::BrownianMotionForce
) )
: :
ParticleForce<CloudType>(owner, mesh, dict, typeName, true), ParticleForce<CloudType>(owner, mesh, dict, typeName, true),
rndGen_(owner.rndGen()),
lambda_(this->coeffs().template lookup<scalar>("lambda")), lambda_(this->coeffs().template lookup<scalar>("lambda")),
turbulence_(readBool(this->coeffs().lookup("turbulence"))), turbulence_(readBool(this->coeffs().lookup("turbulence"))),
kPtr_(nullptr), kPtr_(nullptr),
@ -85,7 +84,6 @@ Foam::BrownianMotionForce<CloudType>::BrownianMotionForce
) )
: :
ParticleForce<CloudType>(bmf), ParticleForce<CloudType>(bmf),
rndGen_(bmf.rndGen_),
lambda_(bmf.lambda_), lambda_(bmf.lambda_),
turbulence_(bmf.turbulence_), turbulence_(bmf.turbulence_),
kPtr_(nullptr), kPtr_(nullptr),
@ -172,7 +170,7 @@ Foam::forceSuSp Foam::BrownianMotionForce<CloudType>::calcCoupled
} }
randomGenerator& rndGen = this->owner().rndGen(); randomGenerator& rndGen = this->owner().rndGen();
distributions::standardNormal stdNormal(rndGen); distributions::standardNormal& stdNormal = this->owner().stdNormal();
// To generate a cubic distribution (i.e., 3 independent directions): // To generate a cubic distribution (i.e., 3 independent directions):
// value.Su() = f*stdNormal.sample<vector>(); // value.Su() = f*stdNormal.sample<vector>();

View File

@ -64,9 +64,6 @@ class BrownianMotionForce
{ {
// Private Data // Private Data
//- Reference to the cloud random number generator
randomGenerator& rndGen_;
//- Molecular free path length [m] //- Molecular free path length [m]
const scalar lambda_; const scalar lambda_;

View File

@ -25,7 +25,6 @@ License
#include "OUprocess.H" #include "OUprocess.H"
#include "Kmesh.H" #include "Kmesh.H"
#include "standardNormal.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -36,13 +35,11 @@ namespace Foam
complexVector OUprocess::WeinerProcess(const scalar deltaT) const complexVector OUprocess::WeinerProcess(const scalar deltaT) const
{ {
distributions::standardNormal stdNormal(rndGen_);
return sqrt(deltaT)*complexVector return sqrt(deltaT)*complexVector
( (
complex(stdNormal.sample(), stdNormal.sample()), complex(stdNormal_.sample(), stdNormal_.sample()),
complex(stdNormal.sample(), stdNormal.sample()), complex(stdNormal_.sample(), stdNormal_.sample()),
complex(stdNormal.sample(), stdNormal.sample()) complex(stdNormal_.sample(), stdNormal_.sample())
); );
} }
@ -56,7 +53,7 @@ OUprocess::OUprocess
const dictionary& OUdict const dictionary& OUdict
) )
: :
rndGen_(label(0)), stdNormal_(0),
Kmesh_(kmesh), Kmesh_(kmesh),
OUfield_(Kmesh_.size()), OUfield_(Kmesh_.size()),

View File

@ -37,7 +37,7 @@ SourceFiles
#include "complexFields.H" #include "complexFields.H"
#include "scalar.H" #include "scalar.H"
#include "randomGenerator.H" #include "standardNormal.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -54,7 +54,7 @@ class OUprocess
{ {
// Private Data // Private Data
mutable randomGenerator rndGen_; const distributions::standardNormal stdNormal_;
const Kmesh& Kmesh_; const Kmesh& Kmesh_;
mutable complexVectorField OUfield_; mutable complexVectorField OUfield_;