diff --git a/src/functionObjects/field/Make/files b/src/functionObjects/field/Make/files index 3fd56b2f79a6486e5e459ece5d42cb6e2ec3e419..bc8fe9634f4c0c728d0944603f58972e63a82142 100644 --- a/src/functionObjects/field/Make/files +++ b/src/functionObjects/field/Make/files @@ -66,6 +66,10 @@ surfaceInterpolate/surfaceInterpolate.C regionSizeDistribution/regionSizeDistribution.C histogram/histogram.C +histogram/histogramModels/histogramModel/histogramModel.C +histogram/histogramModels/histogramModel/histogramModelNew.C +histogram/histogramModels/equalBinWidth/equalBinWidth.C +histogram/histogramModels/unequalBinWidth/unequalBinWidth.C fieldExpression/fieldExpression.C components/components.C diff --git a/src/functionObjects/field/histogram/histogram.C b/src/functionObjects/field/histogram/histogram.C index 90e2289cc108a16163ed8201015e656fdae6d502..4bafa9521c4ef58543ceff0078e4a7e643947fa5 100644 --- a/src/functionObjects/field/histogram/histogram.C +++ b/src/functionObjects/field/histogram/histogram.C @@ -27,8 +27,7 @@ License \*---------------------------------------------------------------------------*/ #include "histogram.H" -#include "volFields.H" -#include "ListOps.H" +#include "histogramModel.H" #include "addToRunTimeSelectionTable.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // @@ -52,11 +51,8 @@ Foam::functionObjects::histogram::histogram const dictionary& dict ) : - functionObjects::fvMeshFunctionObject(name, runTime, dict), - functionObjects::writeFile(obr_, name), - max_(-GREAT), - min_(GREAT), - setWriterPtr_(nullptr) + fvMeshFunctionObject(name, runTime, dict), + histogramModelPtr_(nullptr) { read(dict); } @@ -66,30 +62,14 @@ Foam::functionObjects::histogram::histogram bool Foam::functionObjects::histogram::read(const dictionary& dict) { - fvMeshFunctionObject::read(dict); - writeFile::read(dict); - - dict.readEntry("field", fieldName_); - - max_ = dict.getOrDefault<scalar>("max", -GREAT); - min_ = dict.getOrDefault<scalar>("min", GREAT); - dict.readEntry("nBins", nBins_); - - if (nBins_ < 1) + if (!fvMeshFunctionObject::read(dict)) { - FatalErrorInFunction - << "Number of histogram bins = " << nBins_ - << " cannot be negative or zero." - << abort(FatalError); + return false; } - const word writeType(dict.get<word>("setFormat")); + Info<< type() << " " << name() << ":" << endl; - setWriterPtr_ = coordSetWriter::New - ( - writeType, - dict.subOrEmptyDict("formatOptions").optionalSubDict(writeType) - ); + histogramModelPtr_.reset(histogramModel::New(name(), mesh_, dict)); return true; } @@ -103,115 +83,13 @@ bool Foam::functionObjects::histogram::execute() bool Foam::functionObjects::histogram::write() { - Log << type() << " " << name() << " write:" << nl; - - tmp<volScalarField> tfield; - tfield.cref(obr_.cfindObject<volScalarField>(fieldName_)); - - if (tfield) - { - Log << " Looking up field " << fieldName_ << endl; - } - else - { - Log << " Reading field " << fieldName_ << endl; - tfield = tmp<volScalarField>::New - ( - IOobject - ( - fieldName_, - mesh_.time().timeName(), - mesh_, - IOobject::MUST_READ, - IOobject::NO_WRITE - ), - mesh_ - ); - } - const auto& field = tfield(); - - scalar histMax = max_; - scalar histMin = min_; - - if (max_ == -GREAT) - { - // Determine current min and max - histMax = max(field).value(); - - if (min_ == GREAT) - { - histMin = min(field).value(); - } - Log << " Determined histogram bounds from field" - << " min/max(" << fieldName_ << ") = " - << histMin << ' ' << histMax << endl; - } - else if (min_ == GREAT) - { - histMin = 0; - } - - // Calculate the mid-points of bins for the graph axis - pointField xBin(nBins_, Zero); - const scalar delta = (histMax - histMin)/nBins_; + Log << type() << " " << name() << " write:" << endl; + if (!histogramModelPtr_->write(log)) { - scalar x = histMin + 0.5*delta; - for (point& p : xBin) - { - p.x() = x; - x += delta; - } - } - - scalarField dataNormalized(nBins_, Zero); - labelField dataCount(nBins_, Zero); - const scalarField& V = mesh_.V(); - - forAll(field, celli) - { - const label bini = (field[celli] - histMin)/delta; - if (bini >= 0 && bini < nBins_) - { - dataNormalized[bini] += V[celli]; - dataCount[bini]++; - } - } - - Pstream::listCombineGather(dataNormalized, plusEqOp<scalar>()); - Pstream::listCombineGather(dataCount, plusEqOp<label>()); - - if (Pstream::master()) - { - const scalar sumData = sum(dataNormalized); - - if (sumData > SMALL) - { - dataNormalized /= sumData; - - const coordSet coords(fieldName_, "x", xBin, mag(xBin)); - - auto& writer = *setWriterPtr_; - - writer.open - ( - coords, - ( - writeFile::baseTimeDir() - / (coords.name() + coordSetWriter::suffix(fieldName_)) - ) - ); - - Log << " Writing histogram of " << fieldName_ - << " to " << writer.path() << endl; - - writer.nFields(2); - writer.write(fieldName_, dataNormalized); - writer.write(fieldName_ + "Count", dataCount); - - writer.close(true); - } + return false; } + Log << endl; return true; } diff --git a/src/functionObjects/field/histogram/histogram.H b/src/functionObjects/field/histogram/histogram.H index e5e7781f443338942202318e69490f05e1fe8689..304c197539933b342c16f18a784e6776c777c7a8 100644 --- a/src/functionObjects/field/histogram/histogram.H +++ b/src/functionObjects/field/histogram/histogram.H @@ -35,65 +35,58 @@ Description Operands: \table - Operand | Type | Location - input | volScalarField | $FOAM_CASE/\<time\>/\<inpField\> - output file | dat | $FOAM_CASE/postProcessing/\<FO\>/\<time\>/\<file\> - output field | - | - + Operand | Type | Location + input | volScalarField | \<time\>/\<inpField\> + output file | dat | postProcessing/\<FO\>/\<time\>/histogram + output field | - | - \endtable - The set written contains two columns, the first the volume averaged values, - the second the raw bin count. + The data written contains four columns (from left to right): + - time + - mid-point of histogram bin + - histogram counts - number of samples in each bin + - volume-weighted histogram values Usage Minimal example by using \c system/controlDict.functions: \verbatim histogram1 { - // Mandatory entries (unmodifiable) - type histogram; - libs (fieldFunctionObjects); + // Mandatory entries + type histogram; + libs (fieldFunctionObjects); + field <word>; + model <word>; - // Mandatory (inherited) entries (runtime modifiable) - field p; - nBins 100; - setFormat gnuplot; + // Conditional entries - // Optional entries (runtime modifiable) - max 5; - min -5; + // Option-1: when model == equalBinWidth - // Optional (inherited) entries + // Option-2: when model == unequalBinWidth + + // Inherited entries ... } \endverbatim where the entries mean: \table - Property | Description | Type | Req'd | Dflt - type | Type name: histogram | word | yes | - - libs | Library name: fieldFunctionObjects | word | yes | - - field | Name of operand field | word | yes | - - nBins | Number of histogram bins | label | yes | - - setFormat | Output format | word | yes | - - max | Maximum value sampled | scalar | no | fieldMax - min | minimum value sampled | scalar | no | 0.0 + Property | Description | Type | Reqd | Deflt + type | Type name: histogram | word | yes | - + libs | Library name: fieldFunctionObjects | word | yes | - + field | Name of operand field | word | yes | - + model | Name of the histogram model | word | yes | - \endtable - The inherited entries are elaborated in: - - \link functionObject.H \endlink - - \link writeFile.H \endlink - - Usage by the \c postProcess utility is not available. - -Note - If \c max is not provided it will use the field's min and max as the bin - extremes. If \c max is provided but not \c min it will use 0. + Options for the \c model entry: + \verbatim + equalBinWidth | Use equal-bin width + unequalBinWidth | Use unequal-bin widths + \endverbatim -See also - - Foam::functionObject - - Foam::functionObjects::fvMeshFunctionObject - - Foam::functionObjects::writeFile - - ExtendedCodeGuide::functionObjects::field::histogram + The inherited entries are elaborated in: + - \link functionObject.H \endlink + - \link writeFile.H \endlink SourceFiles histogram.C @@ -104,41 +97,30 @@ SourceFiles #define Foam_functionObjects_histogram_H #include "fvMeshFunctionObject.H" -#include "writeFile.H" -#include "coordSetWriter.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam { + +// Forward Declarations +class histogramModel; + namespace functionObjects { /*---------------------------------------------------------------------------*\ - Class histogram Declaration + Class histogram Declaration \*---------------------------------------------------------------------------*/ class histogram : - public functionObjects::fvMeshFunctionObject, - public functionObjects::writeFile + public fvMeshFunctionObject { // Private Data - //- Number of bins - label nBins_; - - //- Name of field - word fieldName_; - - //- Maximum value - scalar max_; - - //- Minimum value - scalar min_; - - //- Output formatter to write - mutable autoPtr<coordSetWriter> setWriterPtr_; + //- Histogram model + autoPtr<histogramModel> histogramModelPtr_; public: @@ -170,8 +152,8 @@ public: // Member Functions - //- Read the histogram data - virtual bool read(const dictionary&); + //- Read the top-level dictionary + virtual bool read(const dictionary& dict); //- Execute (effectively no-op) virtual bool execute(); diff --git a/src/functionObjects/field/histogram/histogramModels/equalBinWidth/equalBinWidth.C b/src/functionObjects/field/histogram/histogramModels/equalBinWidth/equalBinWidth.C new file mode 100644 index 0000000000000000000000000000000000000000..01bec912e9bed1e506108adbf4bc8826577b8454 --- /dev/null +++ b/src/functionObjects/field/histogram/histogramModels/equalBinWidth/equalBinWidth.C @@ -0,0 +1,167 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2016 OpenFOAM Foundation + Copyright (C) 2016-2022 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 "equalBinWidth.H" +#include "histogramModel.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace histogramModels +{ + defineTypeNameAndDebug(equalBinWidth, 0); + addToRunTimeSelectionTable(histogramModel, equalBinWidth, dictionary); +} +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::histogramModels::equalBinWidth::equalBinWidth +( + const word& name, + const fvMesh& mesh, + const dictionary& dict +) +: + histogramModel(name, mesh, dict), + nBins_(0), + min_(GREAT), + max_(-GREAT) +{ + read(dict); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::histogramModels::equalBinWidth::read(const dictionary& dict) +{ + if (!histogramModel::read(dict)) + { + return false; + } + + nBins_ = dict.getScalar("nBins"); + + if (nBins_ < 1) + { + FatalIOErrorInFunction(dict) + << "Number of histogram bins = " << nBins_ + << " cannot be negative or zero." + << abort(FatalIOError); + } + + min_ = dict.getOrDefault<scalar>("min", GREAT); + max_ = dict.getOrDefault<scalar>("max", -GREAT); + + return true; +} + + +bool Foam::histogramModels::equalBinWidth::write(const bool log) +{ + // Retrieve operand field + const volScalarField& field = histogramModel::getOrReadField(fieldName()); + + // Determine min and max from the operand field + // if the user did not provide any min or max + scalar histMax = max_; + scalar histMin = min_; + + if (max_ == -GREAT) + { + histMax = max(field).value(); + + if (min_ == GREAT) + { + histMin = min(field).value(); + } + if (log) + { + Info<< " Determined histogram bounds from field" + << " min/max(" << fieldName() << ") = " + << histMin << ' ' << histMax << endl; + } + } + else if (min_ == GREAT) + { + histMin = 0; + } + + if (histMax < histMin) + { + FatalErrorInFunction + << "Histogram minimum = " << histMin + << ", cannot be larger than histogram maximum = " << histMax + << exit(FatalError); + } + + + // Calculate the mid-points of bins for the graph axis + pointField binMidPoints(nBins_, Zero); + const scalar delta = (histMax - histMin)/nBins_; + + { + scalar x = histMin + 0.5*delta; + for (point& p : binMidPoints) + { + p.x() = x; + x += delta; + } + } + + + // Calculate the histogram data + scalarField dataNormalised(nBins_, Zero); + labelField dataCount(nBins_, Zero); + const scalarField& V = mesh().V(); + + forAll(field, celli) + { + const label bini = (field[celli] - histMin)/delta; + if (bini >= 0 && bini < nBins_) + { + dataNormalised[bini] += V[celli]; + dataCount[bini]++; + } + } + Pstream::listCombineGather(dataNormalised, plusEqOp<scalar>()); + Pstream::listCombineGather(dataCount, plusEqOp<label>()); + + + // Write histogram data + histogramModel::write(dataNormalised, dataCount, mag(binMidPoints)); + + return true; +} + + +// ************************************************************************* // diff --git a/src/functionObjects/field/histogram/histogramModels/equalBinWidth/equalBinWidth.H b/src/functionObjects/field/histogram/histogramModels/equalBinWidth/equalBinWidth.H new file mode 100644 index 0000000000000000000000000000000000000000..e61b76f30d894570843612aa31f62397e53e12c9 --- /dev/null +++ b/src/functionObjects/field/histogram/histogramModels/equalBinWidth/equalBinWidth.H @@ -0,0 +1,146 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2022 OpenCFD Ltd. +------------------------------------------------------------------------------- +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/>. + +Class + Foam::histogramModels::equalBinWidth + +Description + Histogram model which groups data into bins of equal width. + +Usage + Minimal example by using \c system/controlDict.functions: + \verbatim + histogram1 + { + // Inherited entries + ... + + // Mandatory entries + nBins <label>; + + // Optional entries + min <scalar>; + max <scalar>; + } + \endverbatim + + where the entries mean: + \table + Property | Description | Type | Reqd | Deflt + nBins | Number of histogram bins | label | yes | - + min | Minimum value of histogram data | scalar | no | - + max | Maximum value of histogram data | scalar | no | - + \endtable + +Note + - If \c max is not provided, \c histogram will use operand + field's min and max as the bin extremes. + - If \c max is provided without \c min, + \c histogram will use 0 for the \c min. + +SourceFiles + equalBinWidth.C + +\*---------------------------------------------------------------------------*/ + +#ifndef Foam_histogramModels_equalBinWidth_H +#define Foam_histogramModels_equalBinWidth_H + +#include "histogramModel.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace histogramModels +{ + +/*---------------------------------------------------------------------------*\ + Class equalBinWidth Declaration +\*---------------------------------------------------------------------------*/ + +class equalBinWidth +: + public histogramModel +{ + // Private Data + + //- Number of bins + label nBins_; + + //- Minimum value of histogram data + scalar min_; + + //- Maximum value of histogram data + scalar max_; + + +public: + + //- Runtime type information + TypeName("equalBinWidth"); + + + // Constructors + + //- Construct from components + equalBinWidth + ( + const word& name, + const fvMesh& mesh, + const dictionary& dict + ); + + //- No copy construct + equalBinWidth(const equalBinWidth&) = delete; + + //- No copy assignment + void operator=(const equalBinWidth&) = delete; + + + // Destructor + virtual ~equalBinWidth() = default; + + + // Member Functions + + //- Read top-level dictionary + virtual bool read(const dictionary& dict); + + //- Write data to stream and files + virtual bool write(const bool log); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace histogramModels +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/functionObjects/field/histogram/histogramModels/histogramModel/histogramModel.C b/src/functionObjects/field/histogram/histogramModels/histogramModel/histogramModel.C new file mode 100644 index 0000000000000000000000000000000000000000..8bfb64ce1d59b1989fbd863eda90f987dd1dc86e --- /dev/null +++ b/src/functionObjects/field/histogram/histogramModels/histogramModel/histogramModel.C @@ -0,0 +1,152 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2022 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 "histogramModel.H" +#include "fvMesh.H" +#include "ListOps.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + defineTypeNameAndDebug(histogramModel, 0); + defineRunTimeSelectionTable(histogramModel, dictionary); +} + + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +void Foam::histogramModel::writeFileHeader(Ostream& os) +{ + writeHeader(os, "Histogram"); + writeCommented(os, "Time"); + writeTabbed(os, "binMidPoints"); + writeTabbed(os, "dataCounts"); + writeTabbed(os, "dataValues"); + os << endl; +} + + +Foam::volScalarField& Foam::histogramModel::getOrReadField +( + const word& fieldName +) const +{ + auto* ptr = mesh_.getObjectPtr<volScalarField>(fieldName); + + if (!ptr) + { + ptr = new volScalarField + ( + IOobject + ( + fieldName, + mesh_.time().timeName(), + mesh_, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh_ + ); + mesh_.objectRegistry::store(ptr); + } + + return *ptr; +} + + +void Foam::histogramModel::write +( + scalarField& dataNormalised, + const labelField& dataCount, + const scalarField& magBinMidPoint +) +{ + if (!Pstream::master()) + { + return; + } + + const scalar sumData = sum(dataNormalised); + + if (sumData < SMALL) + { + return; + } + + dataNormalised /= sumData; + + const auto time = mesh().time().value(); + + forAll(dataNormalised, i) + { + file() + << time << tab + << magBinMidPoint[i] << tab + << dataCount[i] << tab + << dataNormalised[i] + << endl; + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::histogramModel::histogramModel +( + const word& name, + const fvMesh& mesh, + const dictionary& dict +) +: + writeFile(mesh, name, "histogram", dict), + mesh_(mesh), + fieldName_(word::null) +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::histogramModel::read(const dictionary& dict) +{ + if (!functionObjects::writeFile::read(dict)) + { + return false; + } + + fieldName_ = dict.get<word>("field"); + + if (writeToFile() && !writtenHeader_) + { + writeFileHeader(file()); + } + + return true; +} + + +// ************************************************************************* // diff --git a/src/functionObjects/field/histogram/histogramModels/histogramModel/histogramModel.H b/src/functionObjects/field/histogram/histogramModels/histogramModel/histogramModel.H new file mode 100644 index 0000000000000000000000000000000000000000..2543633908f4be7f186e81c45fa64cb38d9590c9 --- /dev/null +++ b/src/functionObjects/field/histogram/histogramModels/histogramModel/histogramModel.H @@ -0,0 +1,184 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2022 OpenCFD Ltd. +------------------------------------------------------------------------------- +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/>. + +Namespace + Foam::histogramModels + +Description + A namespace for various histogram model implementations. + +Class + Foam::histogramModel + +Description + A base class for histogram models. + +SourceFiles + histogramModel.C + histogramModelNew.C + +\*---------------------------------------------------------------------------*/ + +#ifndef Foam_histogramModel_H +#define Foam_histogramModel_H + +#include "writeFile.H" +#include "volFields.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward Declarations +class fvMesh; + +/*---------------------------------------------------------------------------*\ + Class histogramModel Declaration +\*---------------------------------------------------------------------------*/ + +class histogramModel +: + public functionObjects::writeFile +{ + // Private Data + + //- Const reference to the mesh + const fvMesh& mesh_; + + //- Name of operand field + word fieldName_; + + +protected: + + // Protected Member Functions + + //- Output file header information + virtual void writeFileHeader(Ostream& os); + + //- Return requested field from the object registry + //- or read+register the field to the object registry + volScalarField& getOrReadField(const word& fieldName) const; + + //- Write histogram data + void write + ( + scalarField& dataNormalised, + const labelField& dataCount, + const scalarField& magMidBin + ); + + +public: + + //- Runtime type information + TypeName("histogramModel"); + + + // Declare runtime constructor selection table + + declareRunTimeSelectionTable + ( + autoPtr, + histogramModel, + dictionary, + ( + const word& name, + const fvMesh& mesh, + const dictionary& dict + ), + (name, mesh, dict) + ); + + + // Selectors + + //- Return a reference to the selected histogram model + static autoPtr<histogramModel> New + ( + const word& name, + const fvMesh& mesh, + const dictionary& dict + ); + + + // Constructors + + //- Construct from components + histogramModel + ( + const word& name, + const fvMesh& mesh, + const dictionary& dict + ); + + //- No copy construct + histogramModel(const histogramModel&) = delete; + + //- No copy assignment + void operator=(const histogramModel&) = delete; + + + //- Destructor + virtual ~histogramModel() = default; + + + // Member Functions + + // Access + + //- Return const reference to the mesh + const fvMesh& mesh() const noexcept + { + return mesh_; + } + + //- Return const reference to the operand field name + const word& fieldName() const noexcept + { + return fieldName_; + } + + + // I-O + + //- Read top-level dictionary + virtual bool read(const dictionary& dict); + + //- Write data to stream and files + virtual bool write(const bool log) = 0; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/functionObjects/field/histogram/histogramModels/histogramModel/histogramModelNew.C b/src/functionObjects/field/histogram/histogramModels/histogramModel/histogramModelNew.C new file mode 100644 index 0000000000000000000000000000000000000000..cc98cf026339f1cd2b4144b1a79b0304ed8521ed --- /dev/null +++ b/src/functionObjects/field/histogram/histogramModels/histogramModel/histogramModelNew.C @@ -0,0 +1,62 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2022 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 "histogramModel.H" +#include "fvMesh.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +Foam::autoPtr<Foam::histogramModel> Foam::histogramModel::New +( + const word& name, + const fvMesh& mesh, + const dictionary& dict +) +{ + const word modelType(dict.get<word>("model")); + + Info<< " Selecting model: " << modelType << nl << endl; + + auto* ctorPtr = dictionaryConstructorTable(modelType); + + if (!ctorPtr) + { + FatalIOErrorInLookup + ( + dict, + "histogramModel", + modelType, + *dictionaryConstructorTablePtr_ + ) << exit(FatalIOError); + } + + return autoPtr<histogramModel>(ctorPtr(name, mesh, dict)); +} + + +// ************************************************************************* // diff --git a/src/functionObjects/field/histogram/histogramModels/unequalBinWidth/unequalBinWidth.C b/src/functionObjects/field/histogram/histogramModels/unequalBinWidth/unequalBinWidth.C new file mode 100644 index 0000000000000000000000000000000000000000..b4b94c4337f33ff227e4807df470a8ea22de567f --- /dev/null +++ b/src/functionObjects/field/histogram/histogramModels/unequalBinWidth/unequalBinWidth.C @@ -0,0 +1,155 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2022 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 "unequalBinWidth.H" +#include "histogramModel.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace histogramModels +{ + defineTypeNameAndDebug(unequalBinWidth, 0); + addToRunTimeSelectionTable(histogramModel, unequalBinWidth, dictionary); +} +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::histogramModels::unequalBinWidth::unequalBinWidth +( + const word& name, + const fvMesh& mesh, + const dictionary& dict +) +: + histogramModel(name, mesh, dict), + nBins_(-1), + ranges_(Zero) +{ + read(dict); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::histogramModels::unequalBinWidth::read(const dictionary& dict) +{ + if (!histogramModel::read(dict)) + { + return false; + } + + ranges_ = dict.get<List<Pair<scalar>>>("ranges"); + + forAll(ranges_, bini) + { + const auto& range = ranges_[bini]; + const scalar min = range.first(); + const scalar max = range.second(); + + if (max < min) + { + FatalIOErrorInFunction(dict) + << "For bin-" << bini + << ", min is larger than max." + << " min = " << min + << " max = " << max + << abort(FatalIOError); + } + } + + nBins_ = ranges_.size(); + + if (nBins_ < 1) + { + FatalIOErrorInFunction(dict) + << "Number of histogram bins = " << nBins_ + << " cannot be negative or zero." + << abort(FatalIOError); + } + + return true; +} + + +bool Foam::histogramModels::unequalBinWidth::write(const bool log) +{ + // Retrieve operand field + const volScalarField& field = histogramModel::getOrReadField(fieldName()); + + // Calculate the mid-points of bins for the graph axis + pointField midBin(nBins_, Zero); + + forAll(ranges_, bini) + { + point& p = midBin[bini]; + const auto& range = ranges_[bini]; + const scalar min = range.first(); + const scalar max = range.second(); + + const scalar delta = max - min; + p.x() = min + 0.5*delta; + } + + + // Calculate the histogram data + scalarField dataNormalised(nBins_, Zero); + labelField dataCount(nBins_, Zero); + const scalarField& V = mesh().V(); + + forAll(field, celli) + { + forAll(ranges_, bini) + { + const auto& range = ranges_[bini]; + const scalar min = range.first(); + const scalar max = range.second(); + + if (field[celli] >= min && field[celli] < max) + { + dataNormalised[bini] += V[celli]; + dataCount[bini]++; + break; + } + } + } + Pstream::listCombineGather(dataNormalised, plusEqOp<scalar>()); + Pstream::listCombineGather(dataCount, plusEqOp<label>()); + + + // Write histogram data + histogramModel::write(dataNormalised, dataCount, mag(midBin)); + + return true; +} + + +// ************************************************************************* // diff --git a/src/functionObjects/field/histogram/histogramModels/unequalBinWidth/unequalBinWidth.H b/src/functionObjects/field/histogram/histogramModels/unequalBinWidth/unequalBinWidth.H new file mode 100644 index 0000000000000000000000000000000000000000..c9c9815d83b86aedc839fbf7fd485bfc16a548e9 --- /dev/null +++ b/src/functionObjects/field/histogram/histogramModels/unequalBinWidth/unequalBinWidth.H @@ -0,0 +1,144 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2022 OpenCFD Ltd. +------------------------------------------------------------------------------- +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/>. + +Class + Foam::histogramModels::unequalBinWidth + +Description + Histogram model which groups data into bins of unequal widths. + +Usage + Minimal example by using \c system/controlDict.functions: + \verbatim + histogram1 + { + // Inherited entries + ... + + // Mandatory entries + ranges + ( + // min max + (<scalar> <scalar>) // bin-0 + (<scalar> <scalar>) // bin-1 + ... + ); + } + \endverbatim + + where the entries mean: + \table + Property | Description | Type | Reqd | Deflt + ranges | Min-max values of histogram data <!-- + --> | List\<Pair\<scalar\>\> | no | - + \endtable + +Note + - All bins are half-open, that is [min, max). + - Bins should be specified as consecutive, non-overlapping + and adjacent intervals of the field variable. No warning + or runtime error will be emitted, otherwise. + +SourceFiles + unequalBinWidth.C + +\*---------------------------------------------------------------------------*/ + +#ifndef Foam_histogramModels_unequalBinWidth_H +#define Foam_histogramModels_unequalBinWidth_H + +#include "histogramModel.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace histogramModels +{ + +/*---------------------------------------------------------------------------*\ + Class unequalBinWidth Declaration +\*---------------------------------------------------------------------------*/ + +class unequalBinWidth +: + public histogramModel +{ + // Private Data + + //- Number of bins + label nBins_; + + //- Lower and upper ranges of operand bins + List<Pair<scalar>> ranges_; + + +public: + + //- Runtime type information + TypeName("unequalBinWidth"); + + + // Constructors + + //- Construct from components + unequalBinWidth + ( + const word& name, + const fvMesh& mesh, + const dictionary& dict + ); + + //- No copy construct + unequalBinWidth(const unequalBinWidth&) = delete; + + //- No copy assignment + void operator=(const unequalBinWidth&) = delete; + + + // Destructor + virtual ~unequalBinWidth() = default; + + + // Member Functions + + //- Read top-level dictionary + virtual bool read(const dictionary& dict); + + //- Write data to stream and files + virtual bool write(const bool log); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace histogramModels +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/tutorials/incompressible/pisoFoam/RAS/cavity/system/FOs/FOhistogram b/tutorials/incompressible/pisoFoam/RAS/cavity/system/FOs/FOhistogram index 34a589c74df8fa7d03667f748b16fd7ce9cb921b..80cf773783f8c81a8c011a0bbbd337343908a486 100644 --- a/tutorials/incompressible/pisoFoam/RAS/cavity/system/FOs/FOhistogram +++ b/tutorials/incompressible/pisoFoam/RAS/cavity/system/FOs/FOhistogram @@ -12,15 +12,54 @@ histogram1 type histogram; libs (fieldFunctionObjects); field p; - nBins 100; - setFormat raw; + model equalBinWidth; - // Optional entries + // Conditional entries + nBins 100; max 10; min -10; - // Optional (inherited) entries - writePrecision 16; + // Inherited entries + writePrecision 6; + writeToFile true; + useUserTime true; + + region region0; + enabled true; + log true; + timeStart 0; + timeEnd 1000; + executeControl timeStep; + executeInterval 1; + writeControl writeTime; + writeInterval -1; +} + + +histogram2 +{ + // Mandatory entries + type histogram; + libs (fieldFunctionObjects); + field p; + model unequalBinWidth; + + // Conditional entries + ranges + ( + // min max + (-10 -9) // bin-0 + (-9 -8) // bin-1 + (-8 -7) + (-7 -6) + (-6 -2) + (-2 0) + (0 5) + (5 10) + ); + + // Inherited entries + writePrecision 6; writeToFile true; useUserTime true;