From 78c984f8f40bd813d7c3d0a0dc00554117d3417e Mon Sep 17 00:00:00 2001 From: Andrew Heather <> Date: Tue, 12 Apr 2022 16:03:14 +0100 Subject: [PATCH] ENH: binField: new field function object The new 'binField' function object calculates binned data, where specified patches are divided into segments according to various input bin characteristics, so that spatially-localised information can be output for each segment. Co-authored-by: Kutalmis Bercin <kutalmis.bercin@esi-group.com> --- src/functionObjects/field/Make/files | 6 + src/functionObjects/field/binField/binField.C | 128 +++++++ src/functionObjects/field/binField/binField.H | 221 ++++++++++++ .../binField/binModels/binModel/binModel.C | 205 ++++++++++++ .../binField/binModels/binModel/binModel.H | 243 ++++++++++++++ .../binField/binModels/binModel/binModelNew.C | 59 ++++ .../binModels/binModel/binModelTemplates.C | 102 ++++++ .../singleDirectionUniformBin.C | 186 +++++++++++ .../singleDirectionUniformBin.H | 186 +++++++++++ .../singleDirectionUniformBinTemplates.C | 195 +++++++++++ .../binModels/uniformBin/uniformBin.C | 315 ++++++++++++++++++ .../binModels/uniformBin/uniformBin.H | 222 ++++++++++++ .../uniformBin/uniformBinTemplates.C | 178 ++++++++++ 13 files changed, 2246 insertions(+) create mode 100644 src/functionObjects/field/binField/binField.C create mode 100644 src/functionObjects/field/binField/binField.H create mode 100644 src/functionObjects/field/binField/binModels/binModel/binModel.C create mode 100644 src/functionObjects/field/binField/binModels/binModel/binModel.H create mode 100644 src/functionObjects/field/binField/binModels/binModel/binModelNew.C create mode 100644 src/functionObjects/field/binField/binModels/binModel/binModelTemplates.C create mode 100644 src/functionObjects/field/binField/binModels/singleDirectionUniformBin/singleDirectionUniformBin.C create mode 100644 src/functionObjects/field/binField/binModels/singleDirectionUniformBin/singleDirectionUniformBin.H create mode 100644 src/functionObjects/field/binField/binModels/singleDirectionUniformBin/singleDirectionUniformBinTemplates.C create mode 100644 src/functionObjects/field/binField/binModels/uniformBin/uniformBin.C create mode 100644 src/functionObjects/field/binField/binModels/uniformBin/uniformBin.H create mode 100644 src/functionObjects/field/binField/binModels/uniformBin/uniformBinTemplates.C diff --git a/src/functionObjects/field/Make/files b/src/functionObjects/field/Make/files index 59fabd85cd3..b7c2550efbd 100644 --- a/src/functionObjects/field/Make/files +++ b/src/functionObjects/field/Make/files @@ -1,5 +1,11 @@ AMIWeights/AMIWeights.C +binField/binField.C +binField/binModels/binModel/binModel.C +binField/binModels/binModel/binModelNew.C +binField/binModels/uniformBin/uniformBin.C +binField/binModels/singleDirectionUniformBin/singleDirectionUniformBin.C + columnAverage/columnAverage.C continuityError/continuityError.C diff --git a/src/functionObjects/field/binField/binField.C b/src/functionObjects/field/binField/binField.C new file mode 100644 index 00000000000..b805afcd9ae --- /dev/null +++ b/src/functionObjects/field/binField/binField.C @@ -0,0 +1,128 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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 "binField.H" +#include "binModel.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace functionObjects +{ + defineTypeNameAndDebug(binField, 0); + addToRunTimeSelectionTable(functionObject, binField, dictionary); +} +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::functionObjects::binField::binField +( + const word& name, + const Time& runTime, + const dictionary& dict, + bool readFields +) +: + fvMeshFunctionObject(name, runTime, dict), + binModelPtr_(nullptr) +{ + if (readFields) + { + read(dict); + } +} + + +Foam::functionObjects::binField::binField +( + const word& name, + const objectRegistry& obr, + const dictionary& dict, + bool readFields +) +: + fvMeshFunctionObject(name, obr, dict), + binModelPtr_(nullptr) +{ + if (readFields) + { + read(dict); + } +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::functionObjects::binField::read(const dictionary& dict) +{ + if (!fvMeshFunctionObject::read(dict)) + { + return false; + } + + Info<< type() << " " << name() << ":" << endl; + + binModelPtr_.reset(binModel::New(dict, mesh_, name())); + + return true; +} + + +bool Foam::functionObjects::binField::execute() +{ + Log << type() << " " << name() << ":" << nl + << " Calculating bins" << nl << endl; + + binModelPtr_->apply(); + + return true; +} + + +bool Foam::functionObjects::binField::write() +{ + return true; +} + + +void Foam::functionObjects::binField::updateMesh(const mapPolyMesh& mpm) +{ + binModelPtr_->updateMesh(mpm); +} + + +void Foam::functionObjects::binField::movePoints(const polyMesh& mesh) +{ + binModelPtr_->movePoints(mesh); +} + + +// ************************************************************************* // diff --git a/src/functionObjects/field/binField/binField.H b/src/functionObjects/field/binField/binField.H new file mode 100644 index 00000000000..1fd57a1aeda --- /dev/null +++ b/src/functionObjects/field/binField/binField.H @@ -0,0 +1,221 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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::functionObjects::binField + +Group + grpFieldFunctionObjects + +Description + Calculates binned data, where specified patches are divided into + segments according to various input bin characteristics, so that + spatially-localised information can be output for each segment. + + Operands: + \table + Operand | Type | Location + input | vol\<Type\>Field(s) <!-- + --> | \<time\>/\<inpField\>s + output file | dat <!-- + --> | postProcessing/\<FO\>/\<time\>/\<file\> + output field | - | - + \endtable + + where \c \<Type\>=Scalar/Vector/SphericalTensor/SymmTensor/Tensor. + +Usage + Minimal example by using \c system/controlDict.functions: + \verbatim + binField1 + { + // Mandatory entries + type binField; + libs (fieldFunctionObjects); + binModel <word>; + fields (<wordHashSet>); + patches (<wordRes>); + binData + { + // Entries of the chosen binModel + } + + // Optional entries + cellZones (<wordRes>); + decomposePatchValues <bool>; + + // Conditional optional entries + + // Option-1, i.e. general coordinate system specification + coordinateSystem + { + type cartesian; + origin (0 0 0); + rotation + { + type axes; + e3 (0 0 1); + e1 (1 0 0); // (e1, e2) or (e2, e3) or (e3, e1) + } + } + + // Option-2, i.e. the centre of rotation + // by inherently using e3=(0 0 1) and e1=(1 0 0) + CofR (0 0 0); + + // Inherited entries + ... + } + \endverbatim + + where the entries mean: + \table + Property | Description | Type | Reqd | Deflt + type | Type name: binField | word | yes | - + libs | Library name: fieldFunctionObjects | word | yes | - + binModel | Name of the bin model | word | yes | - + fields | Names of operand fields | wordHasSet | yes | - + patches | Names of operand patches | wordRes | yes | - + binData | Entries of the chosen bin model | dict | yes | - + decomposePatchValues | Flag to output normal and tangential <!-- + --> components | bool | no | false + cellZones | Names of operand cell zones | wordRes | no | - + coordinateSystem | Coordinate system specifier | dict | cndtnl | - + CofR | Centre of rotation | vector | cndtnl | - + \endtable + + Options for the \c binModel entry: + \verbatim + singleDirectionUniformBin | Segments in a single direction + uniformBin | Segments in multiple directions + \endverbatim + + The inherited entries are elaborated in: + - \link fvMeshFunctionObject.H \endlink + - \link writeFile.H \endlink + - \link coordinateSystem.H \endlink + +SourceFiles + binField.C + +\*---------------------------------------------------------------------------*/ + +#ifndef Foam_functionObjects_binField_H +#define Foam_functionObjects_binField_H + +#include "fvMeshFunctionObject.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +class binModel; + +namespace functionObjects +{ + +/*---------------------------------------------------------------------------*\ + Class binField Declaration +\*---------------------------------------------------------------------------*/ + +class binField +: + public fvMeshFunctionObject +{ +protected: + + // Protected Data + + //- Runtime-selectable bin model + autoPtr<binModel> binModelPtr_; + + +public: + + //- Runtime type information + TypeName("binField"); + + + // Constructors + + //- Construct from Time and dictionary + binField + ( + const word& name, + const Time& runTime, + const dictionary& dict, + const bool readFields = true + ); + + //- Construct from objectRegistry and dictionary + binField + ( + const word& name, + const objectRegistry& obr, + const dictionary& dict, + const bool readFields = true + ); + + //- No copy construct + binField(const binField&) = delete; + + //- No copy assignment + void operator=(const binField&) = delete; + + + //- Destructor + virtual ~binField() = default; + + + // Member Functions + + //- Read the dictionary + virtual bool read(const dictionary& dict); + + //- Execute the function object + virtual bool execute(); + + //- Write to data files/fields and to streams + virtual bool write(); + + //- Update for changes of mesh + virtual void updateMesh(const mapPolyMesh& mpm); + + //- Update for changes of mesh + virtual void movePoints(const polyMesh& mesh); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace functionObjects +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/functionObjects/field/binField/binModels/binModel/binModel.C b/src/functionObjects/field/binField/binModels/binModel/binModel.C new file mode 100644 index 00000000000..5e351b07837 --- /dev/null +++ b/src/functionObjects/field/binField/binModels/binModel/binModel.C @@ -0,0 +1,205 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2021-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 "binModel.H" +#include "fvMesh.H" +#include "cartesianCS.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + defineTypeNameAndDebug(binModel, 0); + defineRunTimeSelectionTable(binModel, dictionary); +} + + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +template<> +bool Foam::binModel::decomposePatchValues +( + List<List<vector>>& data, + const label bini, + const vector& v, + const vector& n +) const +{ + if (!decomposePatchValues_) + { + return false; + } + + #ifdef FULLDEBUG + if (data.size() != 3) + { + FatalErrorInFunction + << "Inconsistent data list size - expect size 3" + << abort(FatalError); + } + #endif + + data[1][bini] += n*(v & n); + data[2][bini] += v - n*(v & n); + + return true; +} + + +void Foam::binModel::setCoordinateSystem +( + const dictionary& dict, + const word& e3Name, + const word& e1Name +) +{ + coordSysPtr_.clear(); + + if (dict.found(coordinateSystem::typeName_())) + { + coordSysPtr_ = + coordinateSystem::New + ( + mesh_, + dict, + coordinateSystem::typeName_() + ); + + Info<< "Setting co-ordinate system:" << nl + << " - type : " << coordSysPtr_->name() << nl + << " - origin : " << coordSysPtr_->origin() << nl + << " - e3 : " << coordSysPtr_->e3() << nl + << " - e1 : " << coordSysPtr_->e1() << endl; + } + else if (dict.found("CofR")) + { + const vector origin(dict.get<point>("CofR")); + + const vector e3 + ( + e3Name == word::null + ? vector(0, 0, 1) + : dict.get<vector>(e3Name) + ); + + const vector e1 + ( + e1Name == word::null + ? vector(1, 0, 0) + : dict.get<vector>(e1Name) + ); + + coordSysPtr_.reset(new coordSystem::cartesian(origin, e3, e1)); + } + else + { + coordSysPtr_.reset(new coordSystem::cartesian(dict)); + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::binModel::binModel +( + const dictionary& dict, + const fvMesh& mesh, + const word& outputPrefix +) +: + writeFile(mesh, outputPrefix), + mesh_(mesh), + decomposePatchValues_(false), + cumulative_(false), + coordSysPtr_(), + nBin_(1), + patchSet_(), + fieldNames_(), + cellZoneIDs_(), + filePtrs_() +{} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +bool Foam::binModel::read(const dictionary& dict) +{ + patchSet_ = mesh_.boundaryMesh().patchSet(dict.get<wordRes>("patches")); + fieldNames_ = dict.get<wordHashSet>("fields").sortedToc(); + + if (dict.found("cellZones")) + { + DynamicList<label> zoneIDs; + DynamicList<wordRe> czUnmatched; + for (const auto& cz : dict.get<wordRes>("cellZones")) + { + const labelList czi(mesh_.cellZones().indices(cz)); + + if (czi.empty()) + { + czUnmatched.append(cz); + } + else + { + zoneIDs.append(czi); + } + } + + if (czUnmatched.size()) + { + WarningInFunction + << "Unable to find zone(s): " << czUnmatched << nl + << "Valid cellZones are : " << mesh_.cellZones().sortedNames() + << endl; + } + + cellZoneIDs_.transfer(zoneIDs); + } + + decomposePatchValues_ = dict.get<bool>("decomposePatchValues"); + + filePtrs_.setSize(fieldNames_.size()); + forAll(filePtrs_, i) + { + filePtrs_.set(i, createFile(fieldNames_[i] + "Bin")); + } + + setCoordinateSystem(dict); + + return true; +} + + +void Foam::binModel::updateMesh(const mapPolyMesh& mpm) +{} + + +void Foam::binModel::movePoints(const polyMesh& mesh) +{} + + +// ************************************************************************* // diff --git a/src/functionObjects/field/binField/binModels/binModel/binModel.H b/src/functionObjects/field/binField/binModels/binModel/binModel.H new file mode 100644 index 00000000000..3583a0a9731 --- /dev/null +++ b/src/functionObjects/field/binField/binModels/binModel/binModel.H @@ -0,0 +1,243 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2021-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::binModel + +Description + Base class for bin models to handle general bin characteristics. + +SourceFiles + binModel.C + binModelNew.C + binModelTemplates.C + +\*---------------------------------------------------------------------------*/ + +#ifndef Foam_binModel_H +#define Foam_binModel_H + +#include "dictionary.H" +#include "HashSet.H" +#include "volFields.H" +#include "runTimeSelectionTables.H" +#include "OFstream.H" +#include "coordinateSystem.H" +#include "writeFile.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward Declarations +class fvMesh; + +/*---------------------------------------------------------------------------*\ + Class binModel Declaration +\*---------------------------------------------------------------------------*/ + +class binModel +: + public functionObjects::writeFile +{ +protected: + + // Protected Data + + //- Reference to the mesh + const fvMesh& mesh_; + + //- Decompose patch values into normal and tangential components + bool decomposePatchValues_; + + //- Flag to accumulate bin data with + //- increasing distance in binning direction + bool cumulative_; + + //- Local coordinate system of bins + autoPtr<coordinateSystem> coordSysPtr_; + + //- Total number of bins + label nBin_; + + //- Indices of operand patches + labelHashSet patchSet_; + + //- Names of operand fields + wordList fieldNames_; + + //- Indices of operand cell zones + labelList cellZoneIDs_; + + //- List of file pointers; 1 file per field + PtrList<OFstream> filePtrs_; + + + // Protected Member Functions + + //- Set the co-ordinate system from dictionary and axes names + void setCoordinateSystem + ( + const dictionary& dict, + const word& e3Name = word::null, + const word& e1Name = word::null + ); + + //- Helper function to decompose patch values + //- into normal and tangential components + template<class Type> + bool decomposePatchValues + ( + List<List<Type>>& data, + const label bini, + const Type& v, + const vector& n + ) const; + + //- Helper function to construct a string description for a given type + template<class Type> + string writeComponents(const word& stem) const; + + //- Write binned data to stream + template<class Type> + void writeBinnedData + ( + List<List<Type>>& data, + Ostream& os + ) const; + + +public: + + //- Runtime type information + TypeName("binModel"); + + + // Declare runtime constructor selection table + + declareRunTimeSelectionTable + ( + autoPtr, + binModel, + dictionary, + ( + const dictionary& dict, + const fvMesh& mesh, + const word& outputPrefix + ), + (dict, mesh, outputPrefix) + ); + + + // Selectors + + //- Return a reference to the selected bin model + static autoPtr<binModel> New + ( + const dictionary& dict, + const fvMesh& mesh, + const word& outputPrefix + ); + + + // Constructors + + //- Construct from components + binModel + ( + const dictionary& dict, + const fvMesh& mesh, + const word& outputPrefix + ); + + //- No copy construct + binModel(const binModel&) = delete; + + //- No copy assignment + void operator=(const binModel&) = delete; + + + //- Destructor + virtual ~binModel() = default; + + + // Member Functions + + //- Read the dictionary + virtual bool read(const dictionary& dict); + + + // Access + + //- Return the total number of bins + label nBin() const noexcept + { + return nBin_; + }; + + + // Evaluation + + //- Initialise bin properties + virtual void initialise() = 0; + + //- Apply bins + virtual void apply() = 0; + + //- Update for changes of mesh + virtual void updateMesh(const mapPolyMesh& mpm); + + //- Update for changes of mesh + virtual void movePoints(const polyMesh& mesh); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +template<> +bool binModel::decomposePatchValues +( + List<List<vector>>& data, + const label bini, + const vector& v, + const vector& n +) const; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository + #include "binModelTemplates.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/functionObjects/field/binField/binModels/binModel/binModelNew.C b/src/functionObjects/field/binField/binModels/binModel/binModelNew.C new file mode 100644 index 00000000000..2447b099198 --- /dev/null +++ b/src/functionObjects/field/binField/binModels/binModel/binModelNew.C @@ -0,0 +1,59 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2021-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 "binModel.H" +#include "fvMesh.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +Foam::autoPtr<Foam::binModel> Foam::binModel::New +( + const dictionary& dict, + const fvMesh& mesh, + const word& outputPrefix +) +{ + word modelType(dict.get<word>("binModel")); + + auto cstrIter = dictionaryConstructorTablePtr_->cfind(modelType); + + if (!cstrIter.found()) + { + FatalIOErrorInLookup + ( + dict, + "binModel", + modelType, + *dictionaryConstructorTablePtr_ + ) << exit(FatalIOError); + } + + return autoPtr<binModel>(cstrIter()(dict, mesh, outputPrefix)); +} + + +// ************************************************************************* // diff --git a/src/functionObjects/field/binField/binModels/binModel/binModelTemplates.C b/src/functionObjects/field/binField/binModels/binModel/binModelTemplates.C new file mode 100644 index 00000000000..fdd86ffaa45 --- /dev/null +++ b/src/functionObjects/field/binField/binModels/binModel/binModelTemplates.C @@ -0,0 +1,102 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2021-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/>. + +\*---------------------------------------------------------------------------*/ + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +template<class Type> +bool Foam::binModel::decomposePatchValues +( + List<List<Type>>& data, + const label bini, + const Type& v, + const vector& n +) const +{ + return decomposePatchValues_; +} + + +template<class Type> +Foam::string Foam::binModel::writeComponents(const word& stem) const +{ + if (pTraits<Type>::nComponents == 1) + { + return stem; + } + + string result = ""; + for (label cmpt = 0; cmpt < pTraits<Type>::nComponents; ++cmpt) + { + if (cmpt) result += " "; + result += stem + "_" + word(pTraits<Type>::componentNames[cmpt]); + } + return result; +}; + + +template<class Type> +void Foam::binModel::writeBinnedData +( + List<List<Type>>& data, + Ostream& os +) const +{ + if (cumulative_) + { + for (auto& datai : data) + { + for (label bini = 1; bini < nBin_; ++bini) + { + datai[bini] += datai[bini-1]; + } + } + } + + writeCurrentTime(os); + + for (label bini = 0; bini < nBin_; ++bini) + { + Type total = Zero; + + for (label i = 0; i < data.size(); ++i) + { + total += data[i][bini]; + } + + writeValue(os, total); + + for (label i = 0; i < data.size(); ++i) + { + writeValue(os, data[i][bini]); + } + } + + os << endl; +} + + +// ************************************************************************* // diff --git a/src/functionObjects/field/binField/binModels/singleDirectionUniformBin/singleDirectionUniformBin.C b/src/functionObjects/field/binField/binModels/singleDirectionUniformBin/singleDirectionUniformBin.C new file mode 100644 index 00000000000..2140504cc04 --- /dev/null +++ b/src/functionObjects/field/binField/binModels/singleDirectionUniformBin/singleDirectionUniformBin.C @@ -0,0 +1,186 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2021-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 "singleDirectionUniformBin.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace binModels +{ + defineTypeNameAndDebug(singleDirectionUniformBin, 0); + addToRunTimeSelectionTable(binModel, singleDirectionUniformBin, dictionary); +} +} + + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +void Foam::binModels::singleDirectionUniformBin::initialise() +{ + const polyBoundaryMesh& pbm = mesh_.boundaryMesh(); + + // Determine extents of patches in a given direction + scalar geomMin = GREAT; + scalar geomMax = -GREAT; + for (const label patchi : patchSet_) + { + const polyPatch& pp = pbm[patchi]; + const scalarField d(pp.faceCentres() & binDir_); + geomMin = min(min(d), geomMin); + geomMax = max(max(d), geomMax); + } + + for (const label zonei : cellZoneIDs_) + { + const cellZone& cZone = mesh_.cellZones()[zonei]; + const vectorField cz(mesh_.C(), cZone); + const scalarField d(cz & binDir_); + + geomMin = min(min(d), geomMin); + geomMax = max(max(d), geomMax); + } + + reduce(geomMin, minOp<scalar>()); + reduce(geomMax, maxOp<scalar>()); + + // Slightly boost max so that region of interest is fully within bounds + geomMax = 1.0001*(geomMax - geomMin) + geomMin; + + // Use geometry limits if not specified by the user + if (binMin_ == GREAT) binMin_ = geomMin; + if (binMax_ == GREAT) binMax_ = geomMax; + + binDx_ = (binMax_ - binMin_)/scalar(nBin_); + + if (binDx_ <= 0) + { + FatalErrorInFunction + << "Max bound must be greater than min bound" << nl + << " d = " << binDx_ << nl + << " min = " << binMin_ << nl + << " max = " << binMax_ << nl + << exit(FatalError); + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::binModels::singleDirectionUniformBin::singleDirectionUniformBin +( + const dictionary& dict, + const fvMesh& mesh, + const word& outputPrefix +) +: + binModel(dict, mesh, outputPrefix), + binDx_(0), + binMin_(GREAT), + binMax_(GREAT), + binDir_(Zero) +{ + read(dict); +} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +bool Foam::binModels::singleDirectionUniformBin::read(const dictionary& dict) +{ + if (!binModel::read(dict)) + { + return false; + } + + Info<< " Activating a set of single-direction bins" << endl; + + const dictionary& binDict = dict.subDict("binData"); + + nBin_ = binDict.getCheck<label>("nBin", labelMinMax::ge(1)); + + Info<< " Employing " << nBin_ << " bins" << endl; + if (binDict.readIfPresent("min", binMin_)) + { + Info<< " - min : " << binMin_ << endl; + } + if (binDict.readIfPresent("max", binMax_)) + { + Info<< " - max : " << binMax_ << endl; + } + + cumulative_ = binDict.getOrDefault<bool>("cumulative", false); + Info<< " - cumulative : " << cumulative_ << endl; + Info<< " - decomposePatchValues : " << decomposePatchValues_ << endl; + + binDir_ = binDict.get<vector>("direction"); + binDir_.normalise(); + + if (mag(binDir_) == 0) + { + FatalIOErrorInFunction(dict) + << "Input direction should not be zero valued" << nl + << " direction = " << binDir_ << nl + << exit(FatalIOError); + } + + Info<< " - direction : " << binDir_ << nl << endl; + + initialise(); + + return true; +} + + +void Foam::binModels::singleDirectionUniformBin::apply() +{ + forAll(fieldNames_, i) + { + const bool ok = + processField<scalar>(i) + || processField<vector>(i) + || processField<sphericalTensor>(i) + || processField<symmTensor>(i) + || processField<tensor>(i); + + if (!ok) + { + WarningInFunction + << "Unable to find field " << fieldNames_[i] + << ". Avaliable objects are " + << mesh_.objectRegistry::sortedToc() + << endl; + } + } + + writtenHeader_ = true; +} + + +// ************************************************************************* // diff --git a/src/functionObjects/field/binField/binModels/singleDirectionUniformBin/singleDirectionUniformBin.H b/src/functionObjects/field/binField/binModels/singleDirectionUniformBin/singleDirectionUniformBin.H new file mode 100644 index 00000000000..1e2a631b11b --- /dev/null +++ b/src/functionObjects/field/binField/binModels/singleDirectionUniformBin/singleDirectionUniformBin.H @@ -0,0 +1,186 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2021-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::binModels::singleDirectionUniformBin + +Description + Calculates binned data in a specified direction. + + For example, a 10cm-long patch extending only in the x-direction + can be binned into 5 bins in the same direction, so that + local information can be output for each 2cm-long segment. + +Usage + Minimal example by using \c system/controlDict.functions: + \verbatim + binField1 + { + // Other binField entries + ... + + // Mandatory entries + binModel singleDirectionUniformBin; + + binData + { + // Mandatory entries + nBin <label>; + direction <vector>; + + // Optional entries + cumulative <bool>; + min <scalar>; + max <scalar>; + } + } + \endverbatim + + where the entries mean: + \table + Property | Description | Type | Reqd | Deflt + binModel | Type name: singleDirectionUniformBin | word | yes | - + binData | Entries of the chosen bin model | dict | yes | - + nBin | Number of bins in binning direction | label | yes | - + direction | Binning direction | vector | yes | - + cumulative | Flag to bin data accumulated with increasing distance <!-- + --> in binning direction | bool | no | false + min | Min-bound in the binning direction with respect to <!-- + --> the global coordinate system's origin | scalar | no | GREAT + max | Max-bound in the binning direction with respect to <!-- + --> the global coordinate system's origin | scalar | no | GREAT + \endtable + +SourceFiles + singleDirectionUniformBin.C + singleDirectionUniformBinTemplates.C + +\*---------------------------------------------------------------------------*/ + +#ifndef Foam_binModels_singleDirectionUniformBin_H +#define Foam_binModels_singleDirectionUniformBin_H + +#include "binModel.H" +#include "writeFile.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace binModels +{ + +/*---------------------------------------------------------------------------*\ + Class singleDirectionUniformBin Declaration +\*---------------------------------------------------------------------------*/ + +class singleDirectionUniformBin +: + public binModel +{ +protected: + + // Protected Data + + //- Distance between bin divisions + scalar binDx_; + + //- Minimum bin bound + scalar binMin_; + + //- Maximum bin bound + scalar binMax_; + + //- Binning direction + vector binDir_; + + + // Protected Member Functions + + //- Write header for a binned-data file + template<class Type> + void writeFileHeader(OFstream& os) const; + + //- Initialise bin properties + virtual void initialise(); + + //- Apply the binning to field fieldi + template<class Type> + bool processField(const label fieldi); + + +public: + + //- Runtime type information + TypeName("singleDirectionUniformBin"); + + + // Constructors + + //- Construct from components + singleDirectionUniformBin + ( + const dictionary& dict, + const fvMesh& mesh, + const word& outputPrefix + ); + + //- No copy construct + singleDirectionUniformBin(const singleDirectionUniformBin&) = delete; + + //- No copy assignment + void operator=(const singleDirectionUniformBin&) = delete; + + + //- Destructor + virtual ~singleDirectionUniformBin() = default; + + + // Member Functions + + //- Read the dictionary + virtual bool read(const dictionary& dict); + + //- Apply bins + virtual void apply(); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace binModels +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository + #include "singleDirectionUniformBinTemplates.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/functionObjects/field/binField/binModels/singleDirectionUniformBin/singleDirectionUniformBinTemplates.C b/src/functionObjects/field/binField/binModels/singleDirectionUniformBin/singleDirectionUniformBinTemplates.C new file mode 100644 index 00000000000..5fedd25a114 --- /dev/null +++ b/src/functionObjects/field/binField/binModels/singleDirectionUniformBin/singleDirectionUniformBinTemplates.C @@ -0,0 +1,195 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2021-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/>. + +\*---------------------------------------------------------------------------*/ + + +template<class Type> +void Foam::binModels::singleDirectionUniformBin::writeFileHeader +( + OFstream& os +) const +{ + writeHeaderValue(os, "bins", nBin_); + writeHeaderValue(os, "start", binMin_); + writeHeaderValue(os, "end", binMax_); + writeHeaderValue(os, "delta", binDx_); + writeHeaderValue(os, "direction", binDir_); + + // Compute and print bin end points in the binning direction + vectorField binPoints(nBin_); + writeCommented(os, "x co-ords :"); + forAll(binPoints, pointi) + { + binPoints[pointi] = (binMin_ + (pointi + 1)*binDx_)*binDir_; + os << tab << binPoints[pointi].x(); + } + os << nl; + + writeCommented(os, "y co-ords :"); + forAll(binPoints, pointi) + { + os << tab << binPoints[pointi].y(); + } + os << nl; + + writeCommented(os, "z co-ords :"); + forAll(binPoints, pointi) + { + os << tab << binPoints[pointi].z(); + } + os << nl; + + writeHeader(os, ""); + writeCommented(os, "Time"); + + for (label i = 0; i < nBin_; ++i) + { + const word ibin("_" + Foam::name(i)); + writeTabbed(os, writeComponents<Type>("total" + ibin)); + writeTabbed(os, writeComponents<Type>("internal" + ibin)); + + if (decomposePatchValues_) + { + writeTabbed(os, writeComponents<Type>("normal" + ibin)); + writeTabbed(os, writeComponents<Type>("tangenial" + ibin)); + } + else + { + writeTabbed(os, writeComponents<Type>("patch" + ibin)); + } + + } + + os << endl; +} + + +template<class Type> +bool Foam::binModels::singleDirectionUniformBin::processField +( + const label fieldi +) +{ + const word& fieldName = fieldNames_[fieldi]; + + typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType; + + const VolFieldType* fieldPtr = mesh_.findObject<VolFieldType>(fieldName); + + if (!fieldPtr) + { + return false; + } + + if (Pstream::master() && !writtenHeader_) + { + writeFileHeader<Type>(filePtrs_[fieldi]); + } + + const VolFieldType& fld = *fieldPtr; + + // Total number of fields + // + // 0: internal + // 1: patch total + // + // OR + // + // 0: internal + // 1: patch normal + // 2: patch tangential + label nField = 2; + if (decomposePatchValues_) + { + nField += 1; + } + + List<List<Type>> data(nField); + for (auto& binList : data) + { + binList.setSize(nBin_, Zero); + } + + for (const label zonei : cellZoneIDs_) + { + const cellZone& cZone = mesh_.cellZones()[zonei]; + + for (const label celli : cZone) + { + const scalar dd = mesh_.C()[celli] & binDir_; + + if (dd < binMin_ || dd > binMax_) + { + continue; + } + + // Find the bin division corresponding to the cell + const label bini = + min(max(floor((dd - binMin_)/binDx_), 0), nBin_ - 1); + + data[0][bini] += fld[celli]; + } + } + + forAllIters(patchSet_, iter) + { + const label patchi = iter(); + const polyPatch& pp = mesh_.boundaryMesh()[patchi]; + const vectorField np(mesh_.boundary()[patchi].nf()); + + const scalarField dd(pp.faceCentres() & binDir_); + + forAll(dd, facei) + { + // Avoid faces outside of the bin + if (dd[facei] < binMin_ || dd[facei] > binMax_) + { + continue; + } + + // Find the bin division corresponding to the face + const label bini = + min(max(floor((dd[facei] - binMin_)/binDx_), 0), nBin_ - 1); + + const Type& v = fld.boundaryField()[patchi][facei]; + + if (!decomposePatchValues(data, bini, v, np[facei])) + { + data[1][bini] += v; + } + } + } + + if (Pstream::master()) + { + writeBinnedData(data, filePtrs_[fieldi]); + } + + return true; +} + + +// ************************************************************************* // diff --git a/src/functionObjects/field/binField/binModels/uniformBin/uniformBin.C b/src/functionObjects/field/binField/binModels/uniformBin/uniformBin.C new file mode 100644 index 00000000000..77836bf690b --- /dev/null +++ b/src/functionObjects/field/binField/binModels/uniformBin/uniformBin.C @@ -0,0 +1,315 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2021-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 "uniformBin.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace binModels +{ + defineTypeNameAndDebug(uniformBin, 0); + addToRunTimeSelectionTable(binModel, uniformBin, dictionary); +} +} + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +void Foam::binModels::uniformBin::initialise() +{ + const polyBoundaryMesh& pbm = mesh_.boundaryMesh(); + + // Determine extents of patches in a given coordinate system + vector geomMin(GREAT, GREAT, GREAT); + vector geomMax(-GREAT, -GREAT, -GREAT); + + for (const label patchi : patchSet_) + { + const polyPatch& pp = pbm[patchi]; + const vectorField ppcs(coordSysPtr_->localPosition(pp.faceCentres())); + + for (direction i = 0; i < vector::nComponents; ++i) + { + geomMin[i] = min(min(ppcs.component(i)), geomMin[i]); + geomMax[i] = max(max(ppcs.component(i)), geomMax[i]); + } + } + + for (const label zonei : cellZoneIDs_) + { + const cellZone& cZone = mesh_.cellZones()[zonei]; + const vectorField d + ( + coordSysPtr_->localPosition(vectorField(mesh_.C(), cZone)) + ); + + for (direction i = 0; i < vector::nComponents; ++i) + { + geomMin[i] = min(min(d.component(i)), geomMin[i]); + geomMax[i] = max(max(d.component(i)), geomMax[i]); + } + } + + reduce(geomMin, minOp<vector>()); + reduce(geomMax, maxOp<vector>()); + + for (direction i = 0; i < vector::nComponents; ++i) + { + // Slightly boost max so that region of interest is fully within bounds + geomMax[i] = 1.0001*(geomMax[i] - geomMin[i]) + geomMin[i]; + + // Use geometry limits if not specified by the user + if (binMinMax_[i][0] == GREAT) binMinMax_[i][0] = geomMin[i]; + if (binMinMax_[i][1] == GREAT) binMinMax_[i][1] = geomMax[i]; + + if (binMinMax_[i][0] > binMinMax_[i][1]) + { + FatalErrorInFunction + << "Max bounds must be greater than min bounds" << nl + << " direction = " << i << nl + << " min = " << binMinMax_[i][0] << nl + << " max = " << binMinMax_[i][1] << nl + << exit(FatalError); + } + + //- Compute bin widths in binning directions + binW_[i] = (binMinMax_[i][1] - binMinMax_[i][0])/scalar(nBins_[i]); + + if (binW_[i] <= 0) + { + FatalErrorInFunction + << "Bin widths must be greater than zero" << nl + << " direction = " << i << nl + << " min bound = " << binMinMax_[i][0] << nl + << " max bound = " << binMinMax_[i][1] << nl + << " bin width = " << binW_[i] + << exit(FatalError); + } + } + + setBinsAddressing(); +} + + +Foam::labelList Foam::binModels::uniformBin::binAddr(const vectorField& d) const +{ + labelList binIndices(d.size(), -1); + + forAll(d, i) + { + // Avoid elements outside of the bin + bool faceInside = true; + for (direction j = 0; j < vector::nComponents; ++j) + { + if (d[i][j] < binMinMax_[j][0] || d[i][j] > binMinMax_[j][1]) + { + faceInside = false; + break; + } + } + + if (faceInside) + { + // Find the bin division corresponding to the element + Vector<label> n(Zero); + for (direction j = 0; j < vector::nComponents; ++j) + { + n[j] = floor((d[i][j] - binMinMax_[j][0])/binW_[j]); + n[j] = min(max(n[j], 0), nBins_[j] - 1); + } + + // Order: (e1, e2, e3), the first varies the fastest + binIndices[i] = n[0] + nBins_[0]*n[1] + nBins_[0]*nBins_[1]*n[2]; + } + else + { + binIndices[i] = -1; + } + } + + return binIndices; +} + + +void Foam::binModels::uniformBin::setBinsAddressing() +{ + faceToBin_.setSize(mesh_.nBoundaryFaces()); + faceToBin_ = -1; + + forAllIters(patchSet_, iter) + { + const polyPatch& pp = mesh_.boundaryMesh()[iter()]; + const label i0 = pp.start() - mesh_.nInternalFaces(); + + SubList<label>(faceToBin_, pp.size(), i0) = + binAddr(coordSysPtr_->localPosition(pp.faceCentres())); + } + + cellToBin_.setSize(mesh_.nCells()); + cellToBin_ = -1; + + for (const label zonei : cellZoneIDs_) + { + const cellZone& cZone = mesh_.cellZones()[zonei]; + labelList bins + ( + binAddr(coordSysPtr_->localPosition(vectorField(mesh_.C(), cZone))) + ); + + forAll(cZone, i) + { + const label celli = cZone[i]; + cellToBin_[celli] = bins[i]; + } + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::binModels::uniformBin::uniformBin +( + const dictionary& dict, + const fvMesh& mesh, + const word& outputPrefix +) +: + binModel(dict, mesh, outputPrefix), + nBins_(Zero), + binW_(Zero), + binMinMax_ + ( + vector2D(GREAT, GREAT), + vector2D(GREAT, GREAT), + vector2D(GREAT, GREAT) + ) +{ + read(dict); +} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +bool Foam::binModels::uniformBin::read(const dictionary& dict) +{ + if (!binModel::read(dict)) + { + return false; + } + + Info<< " Activating a set of uniform bins" << endl; + + const dictionary& binDict = dict.subDict("binData"); + + nBins_ = binDict.get<Vector<label>>("nBin"); + + for (const label n : nBins_) + { + nBin_ *= n; + } + + if (nBin_ <= 0) + { + FatalIOErrorInFunction(binDict) + << "Number of bins must be greater than zero" << nl + << " e1 bins = " << nBins_[0] << nl + << " e2 bins = " << nBins_[1] << nl + << " e3 bins = " << nBins_[2] + << exit(FatalIOError); + } + + Info<< " - Employing:" << nl + << " " << nBins_[0] << " e1 bins," << nl + << " " << nBins_[1] << " e2 bins," << nl + << " " << nBins_[2] << " e3 bins" + << endl; + + cumulative_ = binDict.getOrDefault<bool>("cumulative", false); + Info<< " - cumulative : " << cumulative_ << endl; + Info<< " - decomposePatchValues : " << decomposePatchValues_ << endl; + + if (binDict.found("minMax")) + { + const dictionary& minMaxDict = binDict.subDict("minMax"); + + for (direction i = 0; i < vector::nComponents; ++i) + { + const word ei("e" + Foam::name(i)); + + if (minMaxDict.readIfPresent(ei, binMinMax_[i])) + { + Info<< " - " << ei << " min : " + << binMinMax_[i][0] << nl + << " - " << ei << " max : " + << binMinMax_[i][1] << endl; + } + } + } + Info<< endl; + + initialise(); + + return true; +} + + +void Foam::binModels::uniformBin::apply() +{ + forAll(fieldNames_, i) + { + const bool ok = + processField<scalar>(i) + || processField<vector>(i) + || processField<sphericalTensor>(i) + || processField<symmTensor>(i) + || processField<tensor>(i); + + if (!ok) + { + WarningInFunction + << "Unable to find field " << fieldNames_[i] + << endl; + } + } + + writtenHeader_ = true; +} + + +void Foam::binModels::uniformBin::updateMesh(const mapPolyMesh& mpm) +{} + + +void Foam::binModels::uniformBin::movePoints(const polyMesh& mesh) +{ + setBinsAddressing(); +} + + +// ************************************************************************* // diff --git a/src/functionObjects/field/binField/binModels/uniformBin/uniformBin.H b/src/functionObjects/field/binField/binModels/uniformBin/uniformBin.H new file mode 100644 index 00000000000..bbc043b6dae --- /dev/null +++ b/src/functionObjects/field/binField/binModels/uniformBin/uniformBin.H @@ -0,0 +1,222 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2021-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::binModels::uniformBin + +Description + Calculates binned data in multiple segments according to + a specified Cartesian or cylindrical coordinate system. + +Usage + Minimal example by using \c system/controlDict.functions: + \verbatim + binField1 + { + // Other binField entries + ... + + // Mandatory entries + binModel uniformBin; + + binData + { + // Mandatory entries + nBin <Vector<label>>; + + // Optional entries + cumulative <bool>; + minMax + { + e1 (<scalar> <scalar>); // (min max); + e2 (<scalar> <scalar>); + e3 (<scalar> <scalar>); + } + } + } + \endverbatim + + where the entries mean: + \table + Property | Description | Type | Reqd | Deflt + binModel | Type name: uniformBin | word | yes | - + binData | Entries of the chosen bin model | dict | yes | - + nBin | Numbers of bins in specified directions | Vector\<label\> <!-- + --> | yes | - + cumulative | Flag to bin data accumulated with increasing distance <!-- + --> in binning direction | bool | no | false + minMax | Min-max bounds in binning directions with respect to <!-- + --> the coordinateSystem's origin | dict | no | - + \endtable + +Note + - The order of bin numbering is (e1, e2, e3), where the first + varies the fastest. For example, for a cylindrical bin with + \f$ nBin = (radial, azimuth, height) = (2, 4, 2) \f$, the bin indices + may look like as follows - note the counterclockwise increments: + \verbatim + |-------------------| + | 12 | | 14 | + | 11 | 13 | + | 9 | 15 | + | 10 | | 16 | + |-------------------| + / / / / + / / / / + |-------------------| + | 4 | | 6 | + | 3 | 5 | + | 1 | 7 | + | 2 | | 8 | + |-------------------| + \endverbatim + +SourceFiles + uniformBin.C + uniformBinTemplates.C + +\*---------------------------------------------------------------------------*/ + +#ifndef Foam_binModels_uniformBin_H +#define Foam_binModels_uniformBin_H + +#include "binModel.H" +#include "writeFile.H" +#include "coordinateSystem.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace binModels +{ + +/*---------------------------------------------------------------------------*\ + Class uniformBin Declaration +\*---------------------------------------------------------------------------*/ + +class uniformBin +: + public binModel +{ +protected: + + // Protected Data + + //- Numbers of bins in binning directions + Vector<label> nBins_; + + //- Equidistant bin widths in binning directions + vector binW_; + + //- Min-max bounds of bins in binning directions + Vector<vector2D> binMinMax_; + + //- Face index to bin index addressing + labelList faceToBin_; + + //- Cell index to bin index addressing + labelList cellToBin_; + + + // Protected Member Functions + + //- Write header for an binned-data file + template<class Type> + void writeFileHeader(OFstream& os) const; + + //- Initialise bin properties + virtual void initialise(); + + //- Return list of bin indices corresponding to positions given by d + virtual labelList binAddr(const vectorField& d) const; + + //- Set/cache the bin addressing + virtual void setBinsAddressing(); + + //- Apply the binning to field fieldi + template<class Type> + bool processField(const label fieldi); + + +public: + + //- Runtime type information + TypeName("uniformBin"); + + + // Constructors + + //- Construct from components + uniformBin + ( + const dictionary& dict, + const fvMesh& mesh, + const word& outputPrefix + ); + + //- No copy construct + uniformBin(const uniformBin&) = delete; + + //- No copy assignment + void operator=(const uniformBin&) = delete; + + + //- Destructor + virtual ~uniformBin() = default; + + + // Member Functions + + //- Read the dictionary + virtual bool read(const dictionary& dict); + + //- Apply bins + virtual void apply(); + + //- Update for changes of mesh + virtual void updateMesh(const mapPolyMesh& mpm); + + //- Update for changes of mesh + virtual void movePoints(const polyMesh& mesh); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository + #include "uniformBinTemplates.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace binModels +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/functionObjects/field/binField/binModels/uniformBin/uniformBinTemplates.C b/src/functionObjects/field/binField/binModels/uniformBin/uniformBinTemplates.C new file mode 100644 index 00000000000..8f7c1c103e1 --- /dev/null +++ b/src/functionObjects/field/binField/binModels/uniformBin/uniformBinTemplates.C @@ -0,0 +1,178 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2021-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/>. + +\*---------------------------------------------------------------------------*/ + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +template<class Type> +void Foam::binModels::uniformBin::writeFileHeader +( + OFstream& os +) const +{ + writeHeader(os, "bins"); + + const tensor& R = coordSysPtr_->R(); + for (direction i = 0; i < vector::nComponents; ++i) + { + writeHeaderValue(os, "e" + Foam::name(i) + " bins", nBins_[i]); + writeHeaderValue(os, " start", binMinMax_[i][0]); + writeHeaderValue(os, " end", binMinMax_[i][1]); + writeHeaderValue(os, " delta", binW_[i]); + writeHeaderValue(os, " direction", R.col(i)); + } + writeCommented(os, "bin end co-ordinates:"); + os << nl; + + // Compute and print bin end points in binning directions + for (direction i = 0; i < vector::nComponents; ++i) + { + scalar binEnd = binMinMax_[i][0]; + + writeCommented(os, "e"+Foam::name(i)+" co-ords :"); + for (label j = 0; j < nBins_[i]; ++j) + { + binEnd += binW_[i]; + os << tab << binEnd; + } + os << nl; + } + + writeHeader(os, ""); + writeCommented(os, "Time"); + + for (label i = 0; i < nBin_; ++i) + { + const word ibin(Foam::name(i) + ':'); + writeTabbed(os, writeComponents<Type>("total" + ibin)); + writeTabbed(os, writeComponents<Type>("internal" + ibin)); + + if (decomposePatchValues_) + { + writeTabbed(os, writeComponents<Type>("normal" + ibin)); + writeTabbed(os, writeComponents<Type>("tangential" + ibin)); + } + else + { + writeTabbed(os, writeComponents<Type>("patch" + ibin)); + } + } + + os << endl; +} + +template<class Type> +bool Foam::binModels::uniformBin::processField(const label fieldi) +{ + const word& fieldName = fieldNames_[fieldi]; + + typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType; + + const VolFieldType* fieldPtr = mesh_.findObject<VolFieldType>(fieldName); + + if (!fieldPtr) + { + return false; + } + + if (Pstream::master() && !writtenHeader_) + { + writeFileHeader<Type>(filePtrs_[fieldi]); + } + + const VolFieldType& fld = *fieldPtr; + + // Total number of fields + // + // 0: internal + // 1: patch total + // + // OR + // + // 0: internal + // 1: patch normal + // 2: patch tangential + label nField = 2; + if (decomposePatchValues_) + { + nField += 1; + } + + List<List<Type>> data(nField); + for (auto& binList : data) + { + binList.setSize(nBin_, Zero); + } + + for (const label zonei : cellZoneIDs_) + { + const cellZone& cZone = mesh_.cellZones()[zonei]; + + for (const label celli : cZone) + { + const label bini = cellToBin_[celli]; + + if (bini != -1) + { + data[0][bini] += fld[celli]; + } + } + } + + forAllIters(patchSet_, iter) + { + const label patchi = iter(); + const polyPatch& pp = mesh_.boundaryMesh()[patchi]; + const vectorField np(mesh_.boundary()[patchi].nf()); + + forAll(pp, facei) + { + const label localFacei = + pp.start() - mesh_.nInternalFaces() + facei; + const label bini = faceToBin_[localFacei]; + + if (bini != -1) + { + const Type& v = fld.boundaryField()[patchi][facei]; + + if (!decomposePatchValues(data, bini, v, np[facei])) + { + data[1][bini] += v; + } + } + } + } + + if (Pstream::master()) + { + writeBinnedData(data, filePtrs_[fieldi]); + } + + return true; +} + + +// ************************************************************************* // -- GitLab