diff --git a/src/functionObjects/field/particleDistribution/particleDistribution.C b/src/functionObjects/field/particleDistribution/particleDistribution.C index 441afd29e351d8ee63c831d780515bc3bf896834..0cd7827c2557fc3aae4b13d07d4cad70f85c24c1 100644 --- a/src/functionObjects/field/particleDistribution/particleDistribution.C +++ b/src/functionObjects/field/particleDistribution/particleDistribution.C @@ -46,6 +46,29 @@ namespace functionObjects } } + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::functionObjects::particleDistribution::writeFileHeader +( + Ostream& os +) const +{ + writeHeader(os, "Particle distribution"); + writeHeaderValue(os, "Cloud", cloudName_); + forAll(nameVsBinWidth_, i) + { + writeHeaderValue + ( + os, + "Field:" + nameVsBinWidth_[i].first(), + nameVsBinWidth_[i].second() + ); + } + os << endl; +} + + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::functionObjects::particleDistribution::particleDistribution @@ -58,12 +81,12 @@ Foam::functionObjects::particleDistribution::particleDistribution fvMeshFunctionObject(name, runTime, dict), writeFile(runTime, name, typeName, dict), cloudName_("unknown-cloudName"), - fieldNames_(), - tagFieldName_("unknown-tagFieldName"), - distributionBinWidth_(0), + nameVsBinWidth_(), + tagFieldName_("none"), rndGen_(1234, -1) { read(dict); + writeFileHeader(file()); } @@ -80,11 +103,10 @@ bool Foam::functionObjects::particleDistribution::read(const dictionary& dict) if (fvMeshFunctionObject::read(dict) && writeFile::read(dict)) { dict.lookup("cloud") >> cloudName_; - dict.lookup("fields") >> fieldNames_; - dict.lookup("tagField") >> tagFieldName_; - dict.lookup("distributionBinWidth") >> distributionBinWidth_; + dict.lookup("nameVsBinWidth") >> nameVsBinWidth_; + dict.readIfPresent("tagField", tagFieldName_); - Info<< type() << " " << name() << " output:" + Info<< type() << " " << name() << " output:" << nl << " Processing cloud : " << cloudName_ << nl << endl; @@ -107,9 +129,12 @@ bool Foam::functionObjects::particleDistribution::write() if (!mesh_.foundObject<cloud>(cloudName_)) { + wordList cloudNames(mesh_.names<cloud>()); + WarningInFunction << "Unable to find cloud " << cloudName_ - << " in the mesh database" << endl; + << " in the mesh database. Available clouds include:" + << cloudNames << endl; return false; } @@ -152,25 +177,31 @@ bool Foam::functionObjects::particleDistribution::write() } } + file() << "# Time: " << mesh_.time().timeName() << nl; + bool ok = false; - forAll(fieldNames_, i) + forAll(nameVsBinWidth_, i) { - const word fName = fieldNames_[i]; - ok = ok || processField<scalar>(cloudObr, fName, tagAddr); - ok = ok || processField<vector>(cloudObr, fName, tagAddr); - ok = ok || processField<tensor>(cloudObr, fName, tagAddr); - ok = ok || processField<sphericalTensor>(cloudObr, fName, tagAddr); - ok = ok || processField<symmTensor>(cloudObr, fName, tagAddr); - ok = ok || processField<tensor>(cloudObr, fName, tagAddr); + ok = false; + ok = ok || processField<scalar>(cloudObr, i, tagAddr); + ok = ok || processField<vector>(cloudObr, i, tagAddr); + ok = ok || processField<tensor>(cloudObr, i, tagAddr); + ok = ok || processField<sphericalTensor>(cloudObr, i, tagAddr); + ok = ok || processField<symmTensor>(cloudObr, i, tagAddr); + ok = ok || processField<tensor>(cloudObr, i, tagAddr); if (log && !ok) { WarningInFunction - << "Unable to find field " << fName << " in the " - << cloudName_ << " cloud database" << endl; + << "Unable to find field " << nameVsBinWidth_[i].first() + << " in the " << cloudName_ << " cloud database" << endl; } } + if (ok) + { + file() << nl; + } return true; } @@ -180,9 +211,15 @@ void Foam::functionObjects::particleDistribution::generateDistribution ( const word& fieldName, const scalarField& field, + const scalar binWidth, const label tag ) { + if (field.empty()) + { + return; + } + Ostream& os = file(); if (tag != -1) @@ -193,13 +230,11 @@ void Foam::functionObjects::particleDistribution::generateDistribution distributionModels::general distribution ( field, - distributionBinWidth_, + binWidth, rndGen_ ); - distribution.writeData(os); - - os << endl; + os << fieldName << distribution.writeDict(mesh_.time().timeName()); } diff --git a/src/functionObjects/field/particleDistribution/particleDistribution.H b/src/functionObjects/field/particleDistribution/particleDistribution.H index ea4f205a6514504cbf3530b48380e94269254ac7..37ece3aeb98928ce2979054620c35b2fd7e8d232 100644 --- a/src/functionObjects/field/particleDistribution/particleDistribution.H +++ b/src/functionObjects/field/particleDistribution/particleDistribution.H @@ -28,7 +28,7 @@ Group grpFieldFunctionObjects Description - Generates a particle distrbution for lagrangian data. + Generates a particle distrbution for lagrangian data at a given time. Usage \verbatim @@ -38,8 +38,11 @@ Usage libs ("libfieldFunctionObjects.so"); ... cloud "myCloud"; - field "d" - distributionBinWidth 0.1; + nameVsBinWidth + ( + (d 0.1) + (U 10) + ); } \endverbatim @@ -48,8 +51,8 @@ Usage Property | Description | Required | Default value type | Type name: particleDistribution | yes | cloud | Name of cloud to process | Yes | - field | Name of cloud field to process | Yes | - distributionBinWidth | Width of distribution bins | yes | + nameVsBinWidth | List of cloud field vs bin width | Yes | + tagField | Name of cloud field to use to group particles | no | none \endtable See also @@ -69,6 +72,7 @@ SourceFiles #include "writeFile.H" #include "scalarField.H" #include "cachedRandom.H" +#include "Tuple2.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -93,26 +97,24 @@ protected: //- Cloud name word cloudName_; - //- Field name - wordList fieldNames_; + //- List of field name vs. bin width + List<Tuple2<word, scalar>> nameVsBinWidth_; //- Tag field name - used to filter the particles into groups word tagFieldName_; - //- Distribution bin width - scalar distributionBinWidth_; - //- Random number generator - used by distribution models cachedRandom rndGen_; - // Private Member Functions + // Protected Member Functions //- Generate the distribution void generateDistribution ( const word& fieldName, const scalarField& field, + const scalar binWidth, const label tag = -1 ); @@ -121,7 +123,7 @@ protected: bool processField ( const objectRegistry& obr, - const word& fieldName, + const label fieldi, const List<DynamicList<label>>& addr ); @@ -131,6 +133,9 @@ protected: //- Disallow default bitwise assignment void operator=(const particleDistribution&) = delete; + //- Output file header information + virtual void writeFileHeader(Ostream& os) const; + public: diff --git a/src/functionObjects/field/particleDistribution/particleDistributionTemplates.C b/src/functionObjects/field/particleDistribution/particleDistributionTemplates.C index 46cb2186933de7ed9f2b64651d404fa94519de4f..127ff11acc4a80c009246b9cf6dae6d695fa4d79 100644 --- a/src/functionObjects/field/particleDistribution/particleDistributionTemplates.C +++ b/src/functionObjects/field/particleDistribution/particleDistributionTemplates.C @@ -29,10 +29,13 @@ template<class Type> bool Foam::functionObjects::particleDistribution::processField ( const objectRegistry& obr, - const word& fieldName, + const label fieldi, const List<DynamicList<label>>& addr ) { + const word& fieldName = nameVsBinWidth_[fieldi].first(); + const scalar binWidth = nameVsBinWidth_[fieldi].second(); + if (obr.foundObject<IOField<Type>>(fieldName)) { const IOField<Type>& field = @@ -45,7 +48,13 @@ bool Foam::functionObjects::particleDistribution::processField const Field<Type> subField(field, addr[i]); for (direction d = 0; d < pTraits<Type>::nComponents; ++d) { - generateDistribution(fieldName, subField.component(d), i); + generateDistribution + ( + fieldName, + subField.component(d), + binWidth, + i + ); } } } @@ -53,7 +62,8 @@ bool Foam::functionObjects::particleDistribution::processField { for (direction d = 0; d < pTraits<Type>::nComponents; ++d) { - generateDistribution(fieldName, field.component(d)); + const word fName = fieldName + pTraits<Type>::componentNames[d]; + generateDistribution(fName, field.component(d), binWidth); } } diff --git a/src/lagrangian/distributionModels/general/general.C b/src/lagrangian/distributionModels/general/general.C index 0cf368a6ab526e3fce455c3ec2a300ee5c01aeac..052bfbd1fb99e5169d019409dbc5b467057d24a6 100644 --- a/src/lagrangian/distributionModels/general/general.C +++ b/src/lagrangian/distributionModels/general/general.C @@ -42,6 +42,8 @@ namespace distributionModels void Foam::distributionModels::general::initialise() { + static scalar eps = ROOTVSMALL; + const label nEntries = xy_.size(); integral_.setSize(nEntries); @@ -50,7 +52,7 @@ void Foam::distributionModels::general::initialise() integral_[0] = 0.0; for (label i = 1; i < nEntries; i++) { - scalar k = (xy_[i][1] - xy_[i-1][1])/(xy_[i][0] - xy_[i-1][0]); + scalar k = (xy_[i][1] - xy_[i-1][1])/(xy_[i][0] - xy_[i-1][0] + eps); scalar d = xy_[i-1][1] - k*xy_[i-1][0]; scalar y1 = xy_[i][0]*(0.5*k*xy_[i][0] + d); scalar y0 = xy_[i-1][0]*(0.5*k*xy_[i-1][0] + d); @@ -61,12 +63,12 @@ void Foam::distributionModels::general::initialise() scalar sumArea = integral_.last(); - meanValue_ = sumArea/(maxValue() - minValue()); + meanValue_ = sumArea/(maxValue() - minValue() + eps); for (label i=0; i < nEntries; i++) { - xy_[i][1] /= sumArea; - integral_[i] /= sumArea; + xy_[i][1] /= sumArea + eps; + integral_[i] /= sumArea + eps; } } @@ -243,9 +245,19 @@ Foam::dictionary Foam::distributionModels::general::writeDict const word& dictName ) const { -// dictionary dict = distributionModel::writeDict(dictName); + // dictionary dict = distributionModel::writeDict(dictName); dictionary dict(dictName); - dict.add("distribution", xy_); + List<scalar> data(xy_.size()); + forAll(data, i) + { + data[i] = xy_[i][0]; + } + dict.add("x", data); + forAll(data, i) + { + data[i] = xy_[i][1]; + } + dict.add("y", data); return dict; } @@ -253,8 +265,17 @@ Foam::dictionary Foam::distributionModels::general::writeDict void Foam::distributionModels::general::readDict(const dictionary& dict) { -// distributionModel::readDict(dict); - dict.lookup("distribution") >> xy_; + // distributionModel::readDict(dict); + List<scalar> x(dict.lookup("x")); + List<scalar> y(dict.lookup("y")); + + xy_.setSize(x.size()); + forAll(xy_, i) + { + xy_[i][0] = x[i]; + xy_[i][1] = y[i]; + } + initialise(); }