From 9fe527ba3a3dfdc100e014cf4983795fd50157df Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Tue, 11 Mar 2025 15:18:43 +0000 Subject: [PATCH 01/31] WIP: fieldStatistics: new function object --- src/functionObjects/field/Make/files | 2 + .../field/fieldStatistics/fieldStatistics.C | 312 ++++++++++++++++++ .../field/fieldStatistics/fieldStatistics.H | 277 ++++++++++++++++ .../fieldStatisticsTemplates.C | 183 ++++++++++ 4 files changed, 774 insertions(+) create mode 100644 src/functionObjects/field/fieldStatistics/fieldStatistics.C create mode 100644 src/functionObjects/field/fieldStatistics/fieldStatistics.H create mode 100644 src/functionObjects/field/fieldStatistics/fieldStatisticsTemplates.C diff --git a/src/functionObjects/field/Make/files b/src/functionObjects/field/Make/files index fe9eec32830..060eb3e1685 100644 --- a/src/functionObjects/field/Make/files +++ b/src/functionObjects/field/Make/files @@ -154,4 +154,6 @@ resolutionIndex/resolutionIndexModels/CelikEtaIndex/CelikEtaIndex.C age/age.C comfort/comfort.C +fieldStatistics/fieldStatistics.C + LIB = $(FOAM_LIBBIN)/libfieldFunctionObjects diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.C b/src/functionObjects/field/fieldStatistics/fieldStatistics.C new file mode 100644 index 00000000000..c54d581f0e2 --- /dev/null +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.C @@ -0,0 +1,312 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2025 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 "fieldStatistics.H" +#include "fieldTypes.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace functionObjects +{ + defineTypeNameAndDebug(fieldStatistics, 0); + addToRunTimeSelectionTable(functionObject, fieldStatistics, dictionary); +} +} + +const Foam::Enum +< + Foam::functionObjects::fieldStatistics::modeType +> +Foam::functionObjects::fieldStatistics::modeTypeNames_ +({ + { modeType::mdMag, "magnitude" }, + { modeType::mdCmpt, "component" }, +}); + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +Foam::functionObjects::fieldStatistics::statistic +Foam::functionObjects::fieldStatistics::createStatistic +( + const word& statName, + const modeType& mode +) +{ + statistic m; + m.name_ = statName; + + m.calc = [this, statName, mode](variantInput input) -> variantOutput + { + return std::visit + ( + [this, statName, mode](auto&& arg) -> variantOutput + { + using T = std::decay_t<decltype(arg)>; + using BaseType = typename T::value_type; + + if (statName == "min") + { + if (mode == mdMag) return mag(calcMin<BaseType>(arg)); + else return calcMin<BaseType>(arg); + } + else if (statName == "max") + { + if (mode == mdMag) return mag(calcMax<BaseType>(arg)); + else return calcMax<BaseType>(arg); + } + else if (statName == "mean") + { + if (mode == mdMag) return mag(calcMean<BaseType>(arg)); + else return calcMean<BaseType>(arg); + } + else if (statName == "variance") + { + if (mode == mdMag) return mag(calcVariance<BaseType>(arg)); + else return calcVariance<BaseType>(arg); + } + else return scalar{}; // Default case (for compiler) + }, + input + ); + }; + + return m; +} + + +void Foam::functionObjects::fieldStatistics::writeFileHeader +( + Ostream& os, + const word& fieldName +) +{ + writeHeader(os, word("Field Statistics: " + fieldName)); + writeCommented(os, "Time"); + + // Number of input statistics (i.e., statistics_) could be lesser than that + // of output statistics (i.e., results_; e.g., cell index of min value). + // Therefore, the output file columns are based on output statistics. + const auto& result = results_(fieldName); + + forAllConstIters(result, iter) + { + const word& name = iter.key(); + writeTabbed(os, name); + } + os << endl; + + writtenHeader_ = true; +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::functionObjects::fieldStatistics::fieldStatistics +( + const word& name, + const Time& runTime, + const dictionary& dict +) +: + fvMeshFunctionObject(name, runTime, dict), + writeFile(mesh_, name, typeName, dict), + fieldSet_(mesh_) +{ + read(dict); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::functionObjects::fieldStatistics::read(const dictionary& dict) +{ + if (!(fvMeshFunctionObject::read(dict) && writeFile::read(dict))) + { + return false; + } + + mode_ = modeTypeNames_.getOrDefault("mode", dict, modeType::mdMag); + + // Reset and reprepare the input field names + fieldSet_.clear(); + fieldSet_.read(dict); + fieldSet_.updateSelection(); + + // Reset and reprepare the input statistics + statistics_.clear(); + const wordHashSet stats(dict.get<wordHashSet>("statistics")); + for (const word& m : stats) + { + statistics_.insert(m, createStatistic(m, mode_)); + } + + // Reset and reprepare the output statistics + results_.clear(); + + return true; +} + + +bool Foam::functionObjects::fieldStatistics::execute() +{ + // Calculate the specified statistics for the specified fields + for (const word& fieldName : fieldSet_.selectionNames()) + { + const bool ok = + ( + calcStat<scalar>(fieldName) + || calcStat<vector>(fieldName) + || calcStat<symmTensor>(fieldName) + || calcStat<tensor>(fieldName) + ); + + if (!ok) + { + WarningInFunction + << "Unable to find field " << fieldName << endl; + } + } + + // Store the statistical results into the state containers + for (const word& fieldName : fieldSet_.selectionNames()) + { + const auto& results = results_(fieldName); + + forAllConstIters(results, iter) + { + const word& name = iter.key(); + const variantOutput& value = iter.val(); + + const word variableName(fieldName + "_" + name); + + std::visit + ( + [this, variableName](const auto& v) + { + this->setResult(variableName, v); + }, + value + ); + } + } + + return true; +} + + +bool Foam::functionObjects::fieldStatistics::write() +{ + // Create an output file per field + if (writeToFile() && !writtenHeader_) + { + for (const word& fieldName : fieldSet_.selectionNames()) + { + filePtrs_.set(fieldName, newFileAtStartTime(fieldName)); + + OFstream& file = *filePtrs_(fieldName); + + writeFileHeader(file, fieldName); + } + } + + // Write the statistical results to the output file if requested + if (writeToFile()) + { + for (const word& fieldName : fieldSet_.selectionNames()) + { + const auto& results = results_(fieldName); + + OFstream& file = *filePtrs_(fieldName); + + writeCurrentTime(file); + + forAllConstIters(results, iter) + { + const variantOutput& value = iter.val(); + + std::visit + ( + [&file](const auto& v) + { + if constexpr (std::is_same_v<std::decay_t<decltype(v)>, scalar>) + { + file<< token::TAB << v; + } + else + { + for (const auto& val : v) file<< token::TAB << val; + } + }, + value + ); + } + file<< nl; + } + } + + // Print the statistical results to the standard stream if requested + if (log) + { + for (const word& fieldName : fieldSet_.selectionNames()) + { + const auto& results = results_(fieldName); + + forAllConstIters(results, iter) + { + const word& name = iter.key(); + const variantOutput& value = iter.val(); + + std::visit + ( + [name](const auto& v) + { + if constexpr (std::is_same_v<std::decay_t<decltype(v)>, scalar>) + { + Info<< name << " " << v; + } + else + { + Info<< name << " "; + for (const auto& val : v) Info<< val << " "; + } + Info<< nl; + }, + value + ); + } + } + } + + return true; +} + + +// ************************************************************************* // diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.H b/src/functionObjects/field/fieldStatistics/fieldStatistics.H new file mode 100644 index 00000000000..6b4ec3877d9 --- /dev/null +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.H @@ -0,0 +1,277 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2025 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::fieldStatistics + +Group + grpFieldFunctionObjects + +Description + + Operands: + \table + Operand | Type | Location + input | - | - + output file | dat | \<case\>/postProcessing/\<FO\>/\<time\>/\<file\> + output field | - | - + \endtable + +Usage + Minimal example by using \c system/controlDict.functions: + \verbatim + fieldStatistics1 + { + // Mandatory entries + type fieldStatistics; + libs (fieldFunctionObjects); + fields (<wordList>); + statistics (<wordList>); + + // Optional entries + mode <word>; + + // Inherited entries + ... + } + \endverbatim + + where the entries mean: + \table + Property | Description | Type | Reqd | Deflt + type | Type name: fieldStatistics | word | yes | - + libs | Library name: fieldFunctionObjects | word | yes | - + fields | List of operand fields | wordList | yes | - + statistics | List of operand statistics | wordList | yes | - + mode | Output format of the statistical results | word | no | magnitude + \endtable + + Available statistics of the operand field through the \c statistics entry: + \verbatim + min | Minimum value + max | Maximum value + mean | Arithmetic mean value + variance | Sample variance value (unbiased) + \endverbatim + + Options for the \c mode entry: + \verbatim + magnitude | Output statistics magnitude-wise + component | Output statistics separately for each component + \endverbatim + + The inherited entries are elaborated in: + - \link functionObject.H \endlink + - \link writeFile.H \endlink + +SourceFiles + fieldStatistics.C + fieldStatisticsTemplates.C + +\*---------------------------------------------------------------------------*/ + +#ifndef functionObjects_fieldStatistics_H +#define functionObjects_fieldStatistics_H + +#include "fvMeshFunctionObject.H" +#include "writeFile.H" +#include "volFieldSelection.H" +#include <functional> +#include <variant> + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace functionObjects +{ + +/*---------------------------------------------------------------------------*\ + Class fieldStatistics Declaration +\*---------------------------------------------------------------------------*/ + +class fieldStatistics +: + public fvMeshFunctionObject, + public writeFile +{ + // Private Enumerations + + //- Options for the output format of the statistical results + enum modeType : char + { + mdMag = 0, //!< "Output statistics magnitude-wise" + mdCmpt //!< "Output statistics separately for each component" + }; + + //- Names for modeType + static const Enum<modeType> modeTypeNames_; + + + // Private Classes + + //- Type-safe union for input field types + using variantInput = std::variant + < + volScalarField, + volVectorField, + volSymmTensorField, + volTensorField + >; + + //- Type-safe union for output data types + using variantOutput = std::variant + < + scalar, + vector, + symmTensor, + tensor + >; + + //- Class to encapsulate information about specified statistic + struct statistic + { + //- Name of the statistic + word name_; + + //- Calculate the value of the specified statistic + std::function<variantOutput(variantInput)> calc; + }; + + + // Private Data + + //- Output-format mode - only applicable for tensor ranks > 0 + modeType mode_; + + //- Operand fields on which statistics are computed + volFieldSelection fieldSet_; + + //- List of file pointers; one file per field + HashPtrTable<OFstream> filePtrs_; + + //- Hash table containing all specified statistics + HashTable<statistic> statistics_; + + //- Hash table containing all statistical results per field + HashTable<HashTable<variantOutput>> results_; + + + // Private Member Functions + + //- Return the statistic container + statistic createStatistic(const word& statName, const modeType& mode); + + //- Compute the specified statistics of a given field + template<class T> + bool calcStat(const word& fieldName); + + + // Central tendency statistics + + //- Return the arithmetic mean of the given input field + template<class T> + T calcMean(const VolumeField<T>& field); + + + // Dispersion statistics + + //- Return the minimum value of the given input field + // Store the processor index, cell index and location of the minimum + template<class T> + T calcMin(const VolumeField<T>& field); + + //- Return the maximum value of the given input field + // Store the processor index, cell index and location of the maximum + template<class T> + T calcMax(const VolumeField<T>& field); + + //- Return the sample variance of the given input field + template<class T> + T calcVariance(const VolumeField<T>& field); + + + //- Output the file header information + void writeFileHeader(Ostream& os, const word& fieldName); + +public: + + //- Runtime type information + TypeName("fieldStatistics"); + + + // Generated Methods + + //- No copy construct + fieldStatistics(const fieldStatistics&) = delete; + + //- No copy assignment + void operator=(const fieldStatistics&) = delete; + + + // Constructors + + //- Construct from name, Time and dictionary + fieldStatistics + ( + const word& name, + const Time& runTime, + const dictionary& dict + ); + + + //- Destructor + virtual ~fieldStatistics() = default; + + + // Member Functions + + //- Read function object settings + virtual bool read(const dictionary&); + + //- Execute function object + virtual bool execute(); + + //- Write function object results + virtual bool write(); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace functionObjects +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository + #include "fieldStatisticsTemplates.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/functionObjects/field/fieldStatistics/fieldStatisticsTemplates.C b/src/functionObjects/field/fieldStatistics/fieldStatisticsTemplates.C new file mode 100644 index 00000000000..760532be33b --- /dev/null +++ b/src/functionObjects/field/fieldStatistics/fieldStatisticsTemplates.C @@ -0,0 +1,183 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2025 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 "fieldStatistics.H" +#include "volFields.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +template<class Type> +bool Foam::functionObjects::fieldStatistics::calcStat(const word& fieldName) +{ + typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType; + + if (!obr_.foundObject<VolFieldType>(fieldName)) + { + return false; + } + + const VolFieldType& field = lookupObject<VolFieldType>(fieldName); + + HashTable<variantOutput> result; + for (const auto& iter : statistics_.csorted()) + { + const statistic& stat = iter.val(); + + // Assign a new entry, overwriting existing entries + result.set(stat.name_, stat.calc(field)); + } + + results_.set(fieldName, result); + + return true; +} + + +template<class T> +T Foam::functionObjects::fieldStatistics::calcMean(const VolumeField<T>& field) +{ + return gAverage(field); +} + + +template<class T> +T Foam::functionObjects::fieldStatistics::calcMin(const VolumeField<T>& field) +{ + const label proci = Pstream::myProcNo(); + + // Find min internal field value info + + List<T> minVs(Pstream::nProcs(), pTraits<T>::max); + + labelPair minMaxIds = findMinMax(field); + + label minId = minMaxIds.first(); + if (minId != -1) + { + minVs[proci] = field[minId]; + } + + // Find min boundary field info + const auto& fieldBoundary = field.boundaryField(); + + forAll(fieldBoundary, patchi) + { + const Field<T>& fp = fieldBoundary[patchi]; + if (fp.size()) + { + minMaxIds = findMinMax(fp); + + minId = minMaxIds.first(); + if (minVs[proci] > fp[minId]) + { + minVs[proci] = fp[minId]; + } + } + } + + // Collect info from all processors and output + Pstream::allGatherList(minVs); + + minId = findMin(minVs); + + return minVs[minId]; // minValue +} + + +template<class T> +T Foam::functionObjects::fieldStatistics::calcMax(const VolumeField<T>& field) +{ + const label proci = Pstream::myProcNo(); + + // Find max internal field value info + + List<T> maxVs(Pstream::nProcs(), pTraits<T>::min); + + labelPair minMaxIds = findMinMax(field); + + label maxId = minMaxIds.second(); + if (maxId != -1) + { + maxVs[proci] = field[maxId]; + } + + + // Find max boundary field info + const auto& fieldBoundary = field.boundaryField(); + + forAll(fieldBoundary, patchi) + { + const Field<T>& fp = fieldBoundary[patchi]; + if (fp.size()) + { + minMaxIds = findMinMax(fp); + + maxId = minMaxIds.second(); + if (maxVs[proci] < fp[maxId]) + { + maxVs[proci] = fp[maxId]; + } + } + } + + // Collect info from all processors and output + Pstream::allGatherList(maxVs); + + maxId = findMax(maxVs); + + return maxVs[maxId]; // maxValue +} + + +template<class T> +T Foam::functionObjects::fieldStatistics::calcVariance +( + const VolumeField<T>& field +) +{ + label n = field.size(); + reduce(n, sumOp<label>()); + + const T average(calcMean(field)); + + T var = Zero; + for (const auto& elem : field) + { + var += (elem - average); + } + reduce(var, sumOp<T>()); + + if (n <= 1) + { + return T{}; + } + + return 1/(n-1)*var; +} + + +// ************************************************************************* // -- GitLab From 5f2d55e07b466cf49b788b03ba9712b203e3360e Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Tue, 11 Mar 2025 15:43:38 +0000 Subject: [PATCH 02/31] WIP: fieldStatistics: introduce flag to process internal fields only --- .../field/fieldStatistics/fieldStatistics.C | 2 + .../field/fieldStatistics/fieldStatistics.H | 28 ++++-- .../fieldStatisticsTemplates.C | 95 +++++++++++-------- 3 files changed, 75 insertions(+), 50 deletions(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.C b/src/functionObjects/field/fieldStatistics/fieldStatistics.C index c54d581f0e2..4e6d159b2e5 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.C +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.C @@ -153,6 +153,8 @@ bool Foam::functionObjects::fieldStatistics::read(const dictionary& dict) return false; } + internal_ = dict.getOrDefault("internal", false); + mode_ = modeTypeNames_.getOrDefault("mode", dict, modeType::mdMag); // Reset and reprepare the input field names diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.H b/src/functionObjects/field/fieldStatistics/fieldStatistics.H index 6b4ec3877d9..866433d3339 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.H +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.H @@ -52,6 +52,7 @@ Usage // Optional entries mode <word>; + internal <bool>; // Inherited entries ... @@ -66,6 +67,8 @@ Usage fields | List of operand fields | wordList | yes | - statistics | List of operand statistics | wordList | yes | - mode | Output format of the statistical results | word | no | magnitude + internal | Flag to use internal fields only in computing statistics <!-- + --> | bool | no | false \endtable Available statistics of the operand field through the \c statistics entry: @@ -135,10 +138,10 @@ class fieldStatistics //- Type-safe union for input field types using variantInput = std::variant < - volScalarField, - volVectorField, - volSymmTensorField, - volTensorField + scalarField, + vectorField, + symmTensorField, + tensorField >; //- Type-safe union for output data types @@ -163,6 +166,9 @@ class fieldStatistics // Private Data + //- Flag to use internal fields only in computing statistics + bool internal_; + //- Output-format mode - only applicable for tensor ranks > 0 modeType mode_; @@ -193,7 +199,7 @@ class fieldStatistics //- Return the arithmetic mean of the given input field template<class T> - T calcMean(const VolumeField<T>& field); + T calcMean(const Field<T>& field); // Dispersion statistics @@ -201,17 +207,23 @@ class fieldStatistics //- Return the minimum value of the given input field // Store the processor index, cell index and location of the minimum template<class T> - T calcMin(const VolumeField<T>& field); + T calcMin(const Field<T>& field); //- Return the maximum value of the given input field // Store the processor index, cell index and location of the maximum template<class T> - T calcMax(const VolumeField<T>& field); + T calcMax(const Field<T>& field); //- Return the sample variance of the given input field template<class T> - T calcVariance(const VolumeField<T>& field); + T calcVariance(const Field<T>& field); + //- + template<class GeoField> + tmp<Field<typename GeoField::value_type>> flatten + ( + const GeoField& field + ); //- Output the file header information void writeFileHeader(Ostream& os, const word& fieldName); diff --git a/src/functionObjects/field/fieldStatistics/fieldStatisticsTemplates.C b/src/functionObjects/field/fieldStatistics/fieldStatisticsTemplates.C index 760532be33b..48e7581974e 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatisticsTemplates.C +++ b/src/functionObjects/field/fieldStatistics/fieldStatisticsTemplates.C @@ -30,6 +30,51 @@ License // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +template<class GeoField> +Foam::tmp<Foam::Field<typename GeoField::value_type>> +Foam::functionObjects::fieldStatistics::flatten(const GeoField& fld) +{ + typedef typename GeoField::value_type value_type; + typedef Field<value_type> FieldType; + + + label n = fld.size(); + + if (!internal_) + { + for (const auto& pfld : fld.boundaryField()) + { + if (!pfld.coupled()) + { + n += pfld.size(); + } + } + } + + auto tflatFld = tmp<FieldType>::New(n); + auto& flatFld = tflatFld.ref(); + + // Insert internal values + SubList<value_type>(flatFld, fld.size(), 0) = fld.primitiveField(); + + if (!internal_) + { + // Insert boundary values + n = fld.size(); + for (const auto& pfld : fld.boundaryField()) + { + if (!pfld.coupled()) + { + SubList<value_type>(flatFld, pfld.size(), n) = pfld; + n += pfld.size(); + } + } + } + + return tflatFld; +} + + template<class Type> bool Foam::functionObjects::fieldStatistics::calcStat(const word& fieldName) { @@ -42,13 +87,16 @@ bool Foam::functionObjects::fieldStatistics::calcStat(const word& fieldName) const VolFieldType& field = lookupObject<VolFieldType>(fieldName); + tmp<Field<Type>> tfld = flatten(field); + const Field<Type> fld = tfld.cref(); + HashTable<variantOutput> result; for (const auto& iter : statistics_.csorted()) { const statistic& stat = iter.val(); // Assign a new entry, overwriting existing entries - result.set(stat.name_, stat.calc(field)); + result.set(stat.name_, stat.calc(fld)); } results_.set(fieldName, result); @@ -58,14 +106,14 @@ bool Foam::functionObjects::fieldStatistics::calcStat(const word& fieldName) template<class T> -T Foam::functionObjects::fieldStatistics::calcMean(const VolumeField<T>& field) +T Foam::functionObjects::fieldStatistics::calcMean(const Field<T>& field) { return gAverage(field); } template<class T> -T Foam::functionObjects::fieldStatistics::calcMin(const VolumeField<T>& field) +T Foam::functionObjects::fieldStatistics::calcMin(const Field<T>& field) { const label proci = Pstream::myProcNo(); @@ -81,24 +129,6 @@ T Foam::functionObjects::fieldStatistics::calcMin(const VolumeField<T>& field) minVs[proci] = field[minId]; } - // Find min boundary field info - const auto& fieldBoundary = field.boundaryField(); - - forAll(fieldBoundary, patchi) - { - const Field<T>& fp = fieldBoundary[patchi]; - if (fp.size()) - { - minMaxIds = findMinMax(fp); - - minId = minMaxIds.first(); - if (minVs[proci] > fp[minId]) - { - minVs[proci] = fp[minId]; - } - } - } - // Collect info from all processors and output Pstream::allGatherList(minVs); @@ -109,7 +139,7 @@ T Foam::functionObjects::fieldStatistics::calcMin(const VolumeField<T>& field) template<class T> -T Foam::functionObjects::fieldStatistics::calcMax(const VolumeField<T>& field) +T Foam::functionObjects::fieldStatistics::calcMax(const Field<T>& field) { const label proci = Pstream::myProcNo(); @@ -125,25 +155,6 @@ T Foam::functionObjects::fieldStatistics::calcMax(const VolumeField<T>& field) maxVs[proci] = field[maxId]; } - - // Find max boundary field info - const auto& fieldBoundary = field.boundaryField(); - - forAll(fieldBoundary, patchi) - { - const Field<T>& fp = fieldBoundary[patchi]; - if (fp.size()) - { - minMaxIds = findMinMax(fp); - - maxId = minMaxIds.second(); - if (maxVs[proci] < fp[maxId]) - { - maxVs[proci] = fp[maxId]; - } - } - } - // Collect info from all processors and output Pstream::allGatherList(maxVs); @@ -156,7 +167,7 @@ T Foam::functionObjects::fieldStatistics::calcMax(const VolumeField<T>& field) template<class T> T Foam::functionObjects::fieldStatistics::calcVariance ( - const VolumeField<T>& field + const Field<T>& field ) { label n = field.size(); -- GitLab From 40eda5738983cd7e6d7ceb0446c23c378f561619 Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Tue, 11 Mar 2025 16:56:55 +0000 Subject: [PATCH 03/31] WIP: fieldStatistics: add volume-weighted average to the options --- .../field/fieldStatistics/fieldStatistics.C | 11 ++++++++++ .../field/fieldStatistics/fieldStatistics.H | 22 +++++++++++++++++++ .../fieldStatisticsTemplates.C | 6 +++++ 3 files changed, 39 insertions(+) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.C b/src/functionObjects/field/fieldStatistics/fieldStatistics.C index 4e6d159b2e5..3271e641a64 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.C +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.C @@ -50,6 +50,16 @@ Foam::functionObjects::fieldStatistics::modeTypeNames_ { modeType::mdCmpt, "component" }, }); +const Foam::Enum +< + Foam::functionObjects::fieldStatistics::meanType +> +Foam::functionObjects::fieldStatistics::meanTypeNames_ +({ + { meanType::ARITHMETIC, "arithmetic" }, + { meanType::VOLUMETRIC, "volumetric" }, +}); + // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // @@ -156,6 +166,7 @@ bool Foam::functionObjects::fieldStatistics::read(const dictionary& dict) internal_ = dict.getOrDefault("internal", false); mode_ = modeTypeNames_.getOrDefault("mode", dict, modeType::mdMag); + mean_ = meanTypeNames_.getOrDefault("mean", dict, meanType::ARITHMETIC); // Reset and reprepare the input field names fieldSet_.clear(); diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.H b/src/functionObjects/field/fieldStatistics/fieldStatistics.H index 866433d3339..f8f6ca5d91d 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.H +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.H @@ -53,6 +53,7 @@ Usage // Optional entries mode <word>; internal <bool>; + mean <word>; // Inherited entries ... @@ -69,6 +70,7 @@ Usage mode | Output format of the statistical results | word | no | magnitude internal | Flag to use internal fields only in computing statistics <!-- --> | bool | no | false + mean | Type of the mean operation | word | no | arithmetic \endtable Available statistics of the operand field through the \c statistics entry: @@ -85,6 +87,12 @@ Usage component | Output statistics separately for each component \endverbatim + Options for the \c meanType entry: + \verbatim + arithmetic | Arithmetic mean (average) + volumetric | Volume-weighted arithmetic mean + \endverbatim + The inherited entries are elaborated in: - \link functionObject.H \endlink - \link writeFile.H \endlink @@ -133,6 +141,17 @@ class fieldStatistics static const Enum<modeType> modeTypeNames_; + //- Options for the mean type of the specified fields + enum meanType : char + { + ARITHMETIC = 0, //!< "Arithmetic mean (average)" + VOLUMETRIC //!< "Volume-weighted arithmetic mean" + }; + + //- Names for meanType + static const Enum<meanType> meanTypeNames_; + + // Private Classes //- Type-safe union for input field types @@ -172,6 +191,9 @@ class fieldStatistics //- Output-format mode - only applicable for tensor ranks > 0 modeType mode_; + //- Type of the mean of the specified fields + meanType mean_; + //- Operand fields on which statistics are computed volFieldSelection fieldSet_; diff --git a/src/functionObjects/field/fieldStatistics/fieldStatisticsTemplates.C b/src/functionObjects/field/fieldStatistics/fieldStatisticsTemplates.C index 48e7581974e..b55bd359a7b 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatisticsTemplates.C +++ b/src/functionObjects/field/fieldStatistics/fieldStatisticsTemplates.C @@ -108,6 +108,12 @@ bool Foam::functionObjects::fieldStatistics::calcStat(const word& fieldName) template<class T> T Foam::functionObjects::fieldStatistics::calcMean(const Field<T>& field) { + if (internal_ && (mean_ == VOLUMETRIC)) + { + const auto& V = mesh_.V(); + return (gSum(V*field)/gSum(V)); + } + return gAverage(field); } -- GitLab From fa260b5c2d5d1c7e623089ed923a1f934bf98daf Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Thu, 13 Mar 2025 10:09:08 +0000 Subject: [PATCH 04/31] SQUASH: 970449: use inplace value-count reduce --- .../field/fieldStatistics/fieldStatisticsTemplates.C | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatisticsTemplates.C b/src/functionObjects/field/fieldStatistics/fieldStatisticsTemplates.C index b55bd359a7b..795d90101d9 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatisticsTemplates.C +++ b/src/functionObjects/field/fieldStatistics/fieldStatisticsTemplates.C @@ -176,9 +176,6 @@ T Foam::functionObjects::fieldStatistics::calcVariance const Field<T>& field ) { - label n = field.size(); - reduce(n, sumOp<label>()); - const T average(calcMean(field)); T var = Zero; @@ -186,7 +183,10 @@ T Foam::functionObjects::fieldStatistics::calcVariance { var += (elem - average); } - reduce(var, sumOp<T>()); + + label n = field.size(); + + sumReduce(var, n); if (n <= 1) { -- GitLab From 829d32b7be6b08911bbfd2d05f86171e3f88c254 Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Thu, 13 Mar 2025 10:11:57 +0000 Subject: [PATCH 05/31] SQUASH: 970449: use more useful naming convention for the template file --- src/functionObjects/field/fieldStatistics/fieldStatistics.C | 6 ++++++ src/functionObjects/field/fieldStatistics/fieldStatistics.H | 6 ------ .../{fieldStatisticsTemplates.C => fieldStatisticsImpl.cxx} | 0 3 files changed, 6 insertions(+), 6 deletions(-) rename src/functionObjects/field/fieldStatistics/{fieldStatisticsTemplates.C => fieldStatisticsImpl.cxx} (100%) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.C b/src/functionObjects/field/fieldStatistics/fieldStatistics.C index 3271e641a64..488484a9d18 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.C +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.C @@ -61,6 +61,12 @@ Foam::functionObjects::fieldStatistics::meanTypeNames_ }); +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Implementation +#include "fieldStatisticsImpl.cxx" + + // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // Foam::functionObjects::fieldStatistics::statistic diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.H b/src/functionObjects/field/fieldStatistics/fieldStatistics.H index f8f6ca5d91d..81af225e693 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.H +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.H @@ -300,12 +300,6 @@ public: // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -#ifdef NoRepository - #include "fieldStatisticsTemplates.C" -#endif - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - #endif // ************************************************************************* // diff --git a/src/functionObjects/field/fieldStatistics/fieldStatisticsTemplates.C b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx similarity index 100% rename from src/functionObjects/field/fieldStatistics/fieldStatisticsTemplates.C rename to src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx -- GitLab From 653feb6820f5f009e2ff16fb6817e0ed8e4f6e32 Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Thu, 13 Mar 2025 10:13:55 +0000 Subject: [PATCH 06/31] SQUASH: 970449: pass the enum 'modeType' by value --- src/functionObjects/field/fieldStatistics/fieldStatistics.C | 2 +- src/functionObjects/field/fieldStatistics/fieldStatistics.H | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.C b/src/functionObjects/field/fieldStatistics/fieldStatistics.C index 488484a9d18..887ee68b541 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.C +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.C @@ -73,7 +73,7 @@ Foam::functionObjects::fieldStatistics::statistic Foam::functionObjects::fieldStatistics::createStatistic ( const word& statName, - const modeType& mode + const modeType mode ) { statistic m; diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.H b/src/functionObjects/field/fieldStatistics/fieldStatistics.H index 81af225e693..08a4066db31 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.H +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.H @@ -210,7 +210,7 @@ class fieldStatistics // Private Member Functions //- Return the statistic container - statistic createStatistic(const word& statName, const modeType& mode); + statistic createStatistic(const word& statName, const modeType mode); //- Compute the specified statistics of a given field template<class T> -- GitLab From 798b3f4d2d2b31b6c5ff918bdc4037f1a40a2b80 Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Thu, 13 Mar 2025 11:09:39 +0000 Subject: [PATCH 07/31] SQUASH: 970449: retrieve the field in a more consistent and efficient way --- .../field/fieldStatistics/fieldStatisticsImpl.cxx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx index 795d90101d9..543bc733065 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx +++ b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx @@ -85,7 +85,12 @@ bool Foam::functionObjects::fieldStatistics::calcStat(const word& fieldName) return false; } - const VolFieldType& field = lookupObject<VolFieldType>(fieldName); + const auto* fieldp = obr_.cfindObject<VolFieldType>(fieldName); + if (!fieldp) + { + return false; + } + const auto& field = *fieldp; tmp<Field<Type>> tfld = flatten(field); const Field<Type> fld = tfld.cref(); -- GitLab From 90ee449c8f3f64b2f51a17b7fcb31d11b341100f Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Thu, 13 Mar 2025 11:10:31 +0000 Subject: [PATCH 08/31] SQUASH: 970449: add missing reference --- .../field/fieldStatistics/fieldStatisticsImpl.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx index 543bc733065..f49ff106b81 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx +++ b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx @@ -93,7 +93,7 @@ bool Foam::functionObjects::fieldStatistics::calcStat(const word& fieldName) const auto& field = *fieldp; tmp<Field<Type>> tfld = flatten(field); - const Field<Type> fld = tfld.cref(); + const auto& fld = tfld.cref(); HashTable<variantOutput> result; for (const auto& iter : statistics_.csorted()) -- GitLab From 3c5cd38f5262c13f66a392a9bdf71fe8cfb414a3 Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Thu, 13 Mar 2025 11:11:52 +0000 Subject: [PATCH 09/31] SQUASH: 3876b5d: avoid dimension mixing in mesh.V --- .../field/fieldStatistics/fieldStatisticsImpl.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx index f49ff106b81..368e8a4b70d 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx +++ b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx @@ -115,7 +115,7 @@ T Foam::functionObjects::fieldStatistics::calcMean(const Field<T>& field) { if (internal_ && (mean_ == VOLUMETRIC)) { - const auto& V = mesh_.V(); + const Field<scalar>& V = mesh_.V(); return (gSum(V*field)/gSum(V)); } -- GitLab From ed4bbc4631633340ed35e049fa408a48ad3b2797 Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Thu, 13 Mar 2025 11:13:20 +0000 Subject: [PATCH 10/31] SQUASH: 970449: simplify the calcMin/calcMax routines (they were there for the metadata) --- .../fieldStatistics/fieldStatisticsImpl.cxx | 42 +------------------ 1 file changed, 2 insertions(+), 40 deletions(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx index 368e8a4b70d..424ea685b60 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx +++ b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx @@ -126,52 +126,14 @@ T Foam::functionObjects::fieldStatistics::calcMean(const Field<T>& field) template<class T> T Foam::functionObjects::fieldStatistics::calcMin(const Field<T>& field) { - const label proci = Pstream::myProcNo(); - - // Find min internal field value info - - List<T> minVs(Pstream::nProcs(), pTraits<T>::max); - - labelPair minMaxIds = findMinMax(field); - - label minId = minMaxIds.first(); - if (minId != -1) - { - minVs[proci] = field[minId]; - } - - // Collect info from all processors and output - Pstream::allGatherList(minVs); - - minId = findMin(minVs); - - return minVs[minId]; // minValue + return gMin(field); } template<class T> T Foam::functionObjects::fieldStatistics::calcMax(const Field<T>& field) { - const label proci = Pstream::myProcNo(); - - // Find max internal field value info - - List<T> maxVs(Pstream::nProcs(), pTraits<T>::min); - - labelPair minMaxIds = findMinMax(field); - - label maxId = minMaxIds.second(); - if (maxId != -1) - { - maxVs[proci] = field[maxId]; - } - - // Collect info from all processors and output - Pstream::allGatherList(maxVs); - - maxId = findMax(maxVs); - - return maxVs[maxId]; // maxValue + return gMax(field); } -- GitLab From 2732ad35cf4e06ddab0b897b476fc00be74ea17b Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Thu, 13 Mar 2025 11:17:36 +0000 Subject: [PATCH 11/31] SQUASH: f17efd1: use more compact form for field slicing --- .../field/fieldStatistics/fieldStatisticsImpl.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx index 424ea685b60..6f5d9f73abd 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx +++ b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx @@ -55,7 +55,7 @@ Foam::functionObjects::fieldStatistics::flatten(const GeoField& fld) auto& flatFld = tflatFld.ref(); // Insert internal values - SubList<value_type>(flatFld, fld.size(), 0) = fld.primitiveField(); + flatFld.slice(0, fld.size()) = fld.primitiveField(); if (!internal_) { @@ -65,7 +65,7 @@ Foam::functionObjects::fieldStatistics::flatten(const GeoField& fld) { if (!pfld.coupled()) { - SubList<value_type>(flatFld, pfld.size(), n) = pfld; + flatFld.slice(n, pfld.size()) = pfld; n += pfld.size(); } } -- GitLab From 060f37e91295c3408c8a909ca229bf6de8a2b1fb Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Thu, 13 Mar 2025 11:22:49 +0000 Subject: [PATCH 12/31] SQUASH: replace the for-loop with a modern version --- .../field/fieldStatistics/fieldStatistics.C | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.C b/src/functionObjects/field/fieldStatistics/fieldStatistics.C index 887ee68b541..0b441a84d73 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.C +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.C @@ -132,7 +132,7 @@ void Foam::functionObjects::fieldStatistics::writeFileHeader // Therefore, the output file columns are based on output statistics. const auto& result = results_(fieldName); - forAllConstIters(result, iter) + for (const auto& iter : result.csorted()) { const word& name = iter.key(); writeTabbed(os, name); @@ -219,7 +219,7 @@ bool Foam::functionObjects::fieldStatistics::execute() { const auto& results = results_(fieldName); - forAllConstIters(results, iter) + for (const auto& iter : results.csorted()) { const word& name = iter.key(); const variantOutput& value = iter.val(); @@ -267,7 +267,7 @@ bool Foam::functionObjects::fieldStatistics::write() writeCurrentTime(file); - forAllConstIters(results, iter) + for (const auto& iter : results.csorted()) { const variantOutput& value = iter.val(); @@ -298,7 +298,7 @@ bool Foam::functionObjects::fieldStatistics::write() { const auto& results = results_(fieldName); - forAllConstIters(results, iter) + for (const auto& iter : results.csorted()) { const word& name = iter.key(); const variantOutput& value = iter.val(); -- GitLab From a879f47980b9938292ff773f43aecf63275a91ef Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Thu, 13 Mar 2025 11:48:22 +0000 Subject: [PATCH 13/31] SQUASH: various style changes --- .../field/fieldStatistics/fieldStatistics.C | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.C b/src/functionObjects/field/fieldStatistics/fieldStatistics.C index 0b441a84d73..ec14558f3c8 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.C +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.C @@ -243,6 +243,8 @@ bool Foam::functionObjects::fieldStatistics::execute() bool Foam::functionObjects::fieldStatistics::write() { + Log << type() << " " << name() << " write:" << endl; + // Create an output file per field if (writeToFile() && !writtenHeader_) { @@ -298,6 +300,8 @@ bool Foam::functionObjects::fieldStatistics::write() { const auto& results = results_(fieldName); + Info<< tab << "Field" << tab << fieldName << nl; + for (const auto& iter : results.csorted()) { const word& name = iter.key(); @@ -309,18 +313,19 @@ bool Foam::functionObjects::fieldStatistics::write() { if constexpr (std::is_same_v<std::decay_t<decltype(v)>, scalar>) { - Info<< name << " " << v; + Info<< tab << name << tab << v << nl; } else { - Info<< name << " "; - for (const auto& val : v) Info<< val << " "; + Info<< tab << name << tab; + for (const auto& val : v) Info<< val << tab; + Info<< nl; } - Info<< nl; }, value ); } + Info<< endl; } } -- GitLab From 0edb5ea6b41f0f9f6e75010b0a886cbff3acdcef Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Thu, 13 Mar 2025 15:27:50 +0000 Subject: [PATCH 14/31] STYLE --- src/functionObjects/field/fieldStatistics/fieldStatistics.C | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.C b/src/functionObjects/field/fieldStatistics/fieldStatistics.C index ec14558f3c8..7c3e40df2ea 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.C +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.C @@ -300,7 +300,7 @@ bool Foam::functionObjects::fieldStatistics::write() { const auto& results = results_(fieldName); - Info<< tab << "Field" << tab << fieldName << nl; + Info<< ' Field' << tab << fieldName << nl; for (const auto& iter : results.csorted()) { @@ -313,11 +313,11 @@ bool Foam::functionObjects::fieldStatistics::write() { if constexpr (std::is_same_v<std::decay_t<decltype(v)>, scalar>) { - Info<< tab << name << tab << v << nl; + Info<< ' ' << name << tab << v << nl; } else { - Info<< tab << name << tab; + Info<< ' ' << name << tab; for (const auto& val : v) Info<< val << tab; Info<< nl; } -- GitLab From 7765382f13a83f7964526e7b52ab5834fa03d9ad Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Thu, 13 Mar 2025 11:50:41 +0000 Subject: [PATCH 15/31] SQUASH: dd6d51b6e: remove redundant template file name --- src/functionObjects/field/fieldStatistics/fieldStatistics.H | 1 - 1 file changed, 1 deletion(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.H b/src/functionObjects/field/fieldStatistics/fieldStatistics.H index 08a4066db31..98e7bf35bde 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.H +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.H @@ -99,7 +99,6 @@ Usage SourceFiles fieldStatistics.C - fieldStatisticsTemplates.C \*---------------------------------------------------------------------------*/ -- GitLab From 864c29710495797bd51aaf05a5253982a8d32e79 Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Thu, 13 Mar 2025 11:58:10 +0000 Subject: [PATCH 16/31] SQUASH: 970449: use more convenient type trait checks --- .../field/fieldStatistics/fieldStatistics.C | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.C b/src/functionObjects/field/fieldStatistics/fieldStatistics.C index 7c3e40df2ea..094c03a5cfb 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.C +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.C @@ -277,13 +277,16 @@ bool Foam::functionObjects::fieldStatistics::write() ( [&file](const auto& v) { - if constexpr (std::is_same_v<std::decay_t<decltype(v)>, scalar>) + if constexpr + ( + is_vectorspace_v<std::decay_t<decltype(v)>> + ) { - file<< token::TAB << v; + for (const auto& val : v) file<< token::TAB << val; } else { - for (const auto& val : v) file<< token::TAB << val; + file<< token::TAB << v; } }, value @@ -311,16 +314,19 @@ bool Foam::functionObjects::fieldStatistics::write() ( [name](const auto& v) { - if constexpr (std::is_same_v<std::decay_t<decltype(v)>, scalar>) - { - Info<< ' ' << name << tab << v << nl; - } - else + if constexpr + ( + is_vectorspace_v<std::decay_t<decltype(v)>> + ) { Info<< ' ' << name << tab; for (const auto& val : v) Info<< val << tab; Info<< nl; } + else + { + Info<< tab << name << tab << v << nl; + } }, value ); -- GitLab From 79ba2ccdd4b881472b68a21bb6e39b411784f30d Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Thu, 13 Mar 2025 15:52:19 +0000 Subject: [PATCH 17/31] STYLE --- .../field/fieldStatistics/fieldStatistics.C | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.C b/src/functionObjects/field/fieldStatistics/fieldStatistics.C index 094c03a5cfb..350bcfc8a66 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.C +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.C @@ -303,7 +303,7 @@ bool Foam::functionObjects::fieldStatistics::write() { const auto& results = results_(fieldName); - Info<< ' Field' << tab << fieldName << nl; + Info<< nl << " Field " << fieldName << nl; for (const auto& iter : results.csorted()) { @@ -319,20 +319,20 @@ bool Foam::functionObjects::fieldStatistics::write() is_vectorspace_v<std::decay_t<decltype(v)>> ) { - Info<< ' ' << name << tab; - for (const auto& val : v) Info<< val << tab; + Info<< " " << name << " "; + for (const auto& val : v) Info<< val << " "; Info<< nl; } else { - Info<< tab << name << tab << v << nl; + Info<< " " << name << " " << v << nl; } }, value ); } - Info<< endl; } + Info<< endl; } return true; -- GitLab From 6d43ee2034ee5c48fcdf9cbbeeb813746c969f8f Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Thu, 13 Mar 2025 16:58:10 +0000 Subject: [PATCH 18/31] WIP: collect the data writer routines into functions --- .../field/fieldStatistics/fieldStatistics.C | 150 ++++++++++-------- .../field/fieldStatistics/fieldStatistics.H | 6 + 2 files changed, 89 insertions(+), 67 deletions(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.C b/src/functionObjects/field/fieldStatistics/fieldStatistics.C index 350bcfc8a66..ad39bdc8569 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.C +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.C @@ -143,6 +143,87 @@ void Foam::functionObjects::fieldStatistics::writeFileHeader } +void Foam::functionObjects::fieldStatistics::writeStatData() +{ + for (const word& fieldName : fieldSet_.selectionNames()) + { + const auto& results = results_(fieldName); + + if (!results.size()) break; + + OFstream& file = *filePtrs_(fieldName); + + writeCurrentTime(file); + + for (const auto& iter : results.csorted()) + { + const variantOutput& value = iter.val(); + + std::visit + ( + [&file](const auto& v) + { + if constexpr + ( + is_vectorspace_v<std::decay_t<decltype(v)>> + ) + { + for (const auto& val : v) file<< token::TAB << val; + } + else + { + file<< token::TAB << v; + } + }, + value + ); + } + file<< nl; + } +} + + +void Foam::functionObjects::fieldStatistics::logStatData() +{ + for (const word& fieldName : fieldSet_.selectionNames()) + { + const auto& results = results_(fieldName); + + if (!results.size()) break; + + Info<< nl << " Field " << fieldName << nl; + + for (const auto& iter : results.csorted()) + { + const word& name = iter.key(); + const variantOutput& value = iter.val(); + + std::visit + ( + [name](const auto& v) + { + if constexpr + ( + is_vectorspace_v<std::decay_t<decltype(v)>> + ) + { + Info<< " " << name << " "; + for (const auto& val : v) Info<< val << " "; + Info<< nl; + } + else + { + Info<< " " << name << " " << v << nl; + } + }, + value + ); + } + } + Info<< endl; +} + + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::functionObjects::fieldStatistics::fieldStatistics @@ -261,78 +342,13 @@ bool Foam::functionObjects::fieldStatistics::write() // Write the statistical results to the output file if requested if (writeToFile()) { - for (const word& fieldName : fieldSet_.selectionNames()) - { - const auto& results = results_(fieldName); - - OFstream& file = *filePtrs_(fieldName); - - writeCurrentTime(file); - - for (const auto& iter : results.csorted()) - { - const variantOutput& value = iter.val(); - - std::visit - ( - [&file](const auto& v) - { - if constexpr - ( - is_vectorspace_v<std::decay_t<decltype(v)>> - ) - { - for (const auto& val : v) file<< token::TAB << val; - } - else - { - file<< token::TAB << v; - } - }, - value - ); - } - file<< nl; - } + writeStatData(); } // Print the statistical results to the standard stream if requested if (log) { - for (const word& fieldName : fieldSet_.selectionNames()) - { - const auto& results = results_(fieldName); - - Info<< nl << " Field " << fieldName << nl; - - for (const auto& iter : results.csorted()) - { - const word& name = iter.key(); - const variantOutput& value = iter.val(); - - std::visit - ( - [name](const auto& v) - { - if constexpr - ( - is_vectorspace_v<std::decay_t<decltype(v)>> - ) - { - Info<< " " << name << " "; - for (const auto& val : v) Info<< val << " "; - Info<< nl; - } - else - { - Info<< " " << name << " " << v << nl; - } - }, - value - ); - } - } - Info<< endl; + logStatData(); } return true; diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.H b/src/functionObjects/field/fieldStatistics/fieldStatistics.H index 98e7bf35bde..5c20cb348e7 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.H +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.H @@ -249,6 +249,12 @@ class fieldStatistics //- Output the file header information void writeFileHeader(Ostream& os, const word& fieldName); + //- + void writeStatData(); + + //- + void logStatData(); + public: //- Runtime type information -- GitLab From 6282fefe5b9649bedbed46a2d21d156ee208afde Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Thu, 13 Mar 2025 11:52:51 +0000 Subject: [PATCH 19/31] WIP: ensure backward-compatibility for fieldMinMax --- .../field/fieldStatistics/fieldStatistics.C | 147 +++++++++++++++++- .../field/fieldStatistics/fieldStatistics.H | 41 +++++ .../fieldStatistics/fieldStatisticsImpl.cxx | 105 +++++++++++++ 3 files changed, 291 insertions(+), 2 deletions(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.C b/src/functionObjects/field/fieldStatistics/fieldStatistics.C index ad39bdc8569..0c2801836ae 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.C +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.C @@ -138,8 +138,6 @@ void Foam::functionObjects::fieldStatistics::writeFileHeader writeTabbed(os, name); } os << endl; - - writtenHeader_ = true; } @@ -224,6 +222,97 @@ void Foam::functionObjects::fieldStatistics::logStatData() } +void Foam::functionObjects::fieldStatistics::writeExtremaFileHeader +( + Ostream& os, + const word& fieldName +) +{ + writeHeader(os, word("Field Extrema Data: " + fieldName)); + writeCommented(os, "Time"); + writeTabbed(os, "min"); + writeTabbed(os, "min_procID"); + writeTabbed(os, "min_cellID"); + writeTabbed(os, "min_position"); + writeTabbed(os, "max"); + writeTabbed(os, "max_procID"); + writeTabbed(os, "max_cellID"); + writeTabbed(os, "max_position"); + os << endl; +} + + +void Foam::functionObjects::fieldStatistics::writeExtremaData() +{ + for (const word& fieldName : fieldSet_.selectionNames()) + { + const auto& min = extremaMetaData_(fieldName).first(); + const auto& max = extremaMetaData_(fieldName).second(); + + OFstream& efile = *extremaFilePtrs_(fieldName); + + writeCurrentTime(efile); + + efile<< token::TAB; + + std::visit([&efile](const auto& v){ efile<< v; }, min.value_); + + efile<< token::TAB + << min.procID_ << token::TAB + << min.cellID_ << token::TAB + << min.position_ << token::TAB; + + std::visit([&efile](const auto& v){ efile<< v; }, max.value_); + + efile<< token::TAB + << max.procID_ << token::TAB + << max.cellID_ << token::TAB + << max.position_ << nl; + } +} + + +void Foam::functionObjects::fieldStatistics::logExtremaData() +{ + for (const word& fieldName : fieldSet_.selectionNames()) + { + const auto& min = extremaMetaData_(fieldName).first(); + const auto& max = extremaMetaData_(fieldName).second(); + + const word outputName = + (mode_ == mdMag) + ? word("mag(" + fieldName + ")") + : fieldName; + + std::visit + ( + [outputName](const auto& v) + { + Info<< " min(" << outputName << ") = " << v; + }, + min.value_ + ); + + Info<< " in cell " << min.cellID_ + << " at location " << min.position_ + << " on processor " << min.procID_; + + std::visit + ( + [outputName](const auto& v) + { + Info<< nl << " max(" << outputName << ") = " << v; + }, + max.value_ + ); + + Info<< " in cell " << max.cellID_ + << " at location " << max.position_ + << " on processor " << max.procID_ << endl; + } +} + + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::functionObjects::fieldStatistics::fieldStatistics @@ -251,6 +340,7 @@ bool Foam::functionObjects::fieldStatistics::read(const dictionary& dict) } internal_ = dict.getOrDefault("internal", false); + extrema_ = dict.getOrDefault("extrema", false); mode_ = modeTypeNames_.getOrDefault("mode", dict, modeType::mdMag); mean_ = meanTypeNames_.getOrDefault("mean", dict, meanType::ARITHMETIC); @@ -271,6 +361,9 @@ bool Foam::functionObjects::fieldStatistics::read(const dictionary& dict) // Reset and reprepare the output statistics results_.clear(); + // Reset and reprepare the output statistics + extremaMetaData_.clear(); + return true; } @@ -316,6 +409,35 @@ bool Foam::functionObjects::fieldStatistics::execute() value ); } + + if (extrema_) + { + const auto& min = extremaMetaData_(fieldName).first(); + std::visit + ( + [this, fieldName](const auto& v) + { + this->setResult(word(fieldName + "_min"), v); + }, + min.value_ + ); + this->setResult(word(fieldName + "_min_procID"), min.procID_); + this->setResult(word(fieldName + "_min_cellID"), min.cellID_); + this->setResult(word(fieldName + "_min_position"), min.position_); + + const auto& max = extremaMetaData_(fieldName).second(); + std::visit + ( + [this, fieldName](const auto& v) + { + this->setResult(word(fieldName + "_max"), v); + }, + max.value_ + ); + this->setResult(word(fieldName + "_max_procID"), max.procID_); + this->setResult(word(fieldName + "_max_cellID"), max.cellID_); + this->setResult(word(fieldName + "_max_position"), max.position_); + } } return true; @@ -337,17 +459,38 @@ bool Foam::functionObjects::fieldStatistics::write() writeFileHeader(file, fieldName); } + + if (extrema_) + { + for (const word& fieldName : fieldSet_.selectionNames()) + { + extremaFilePtrs_.set + ( + fieldName, + newFileAtStartTime(word("fieldMinMax_" + fieldName)) + ); + + OFstream& file = *extremaFilePtrs_(fieldName); + writeExtremaFileHeader(file, fieldName); + } + } + + writtenHeader_ = true; } // Write the statistical results to the output file if requested if (writeToFile()) { + if (extrema_) writeExtremaData(); + writeStatData(); } // Print the statistical results to the standard stream if requested if (log) { + if (extrema_) logExtremaData(); + logStatData(); } diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.H b/src/functionObjects/field/fieldStatistics/fieldStatistics.H index 5c20cb348e7..5cdf0b99bd6 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.H +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.H @@ -54,6 +54,7 @@ Usage mode <word>; internal <bool>; mean <word>; + extrema <bool>; // Inherited entries ... @@ -71,6 +72,7 @@ Usage internal | Flag to use internal fields only in computing statistics <!-- --> | bool | no | false mean | Type of the mean operation | word | no | arithmetic + extrema | Flag to enable extrema metadata calculations | bool | no | false \endtable Available statistics of the operand field through the \c statistics entry: @@ -181,12 +183,31 @@ class fieldStatistics std::function<variantOutput(variantInput)> calc; }; + //- Class to encapsulate metadata about minima and maxima + struct extremaMetaData + { + //- Value of the extremum + variantOutput value_; + + //- Processor index of the extremum + label procID_; + + //- Cell index of the extremum + label cellID_; + + //- Position vector of the extremum + vector position_; + }; + // Private Data //- Flag to use internal fields only in computing statistics bool internal_; + //- Flag to enable extrema metadata calculations + bool extrema_; + //- Output-format mode - only applicable for tensor ranks > 0 modeType mode_; @@ -199,12 +220,18 @@ class fieldStatistics //- List of file pointers; one file per field HashPtrTable<OFstream> filePtrs_; + //- List of file pointers for extrema data; one file per field + HashPtrTable<OFstream> extremaFilePtrs_; + //- Hash table containing all specified statistics HashTable<statistic> statistics_; //- Hash table containing all statistical results per field HashTable<HashTable<variantOutput>> results_; + //- Hash table containing the metadata of the extrema per field + HashTable<Pair<extremaMetaData>> extremaMetaData_; + // Private Member Functions @@ -246,6 +273,10 @@ class fieldStatistics const GeoField& field ); + //- Return the extrema metadata of the specified field + template<class GeoField> + Pair<extremaMetaData> calcExtremaMetaData(const GeoField& field); + //- Output the file header information void writeFileHeader(Ostream& os, const word& fieldName); @@ -255,6 +286,16 @@ class fieldStatistics //- void logStatData(); + //- Output the extrema-data file header information + void writeExtremaFileHeader(Ostream& os, const word& fieldName); + + //- Write extrema data to the specified file + void writeExtremaData(); + + //- Write extrema data to the standard stream + void logExtremaData(); + + public: //- Runtime type information diff --git a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx index 6f5d9f73abd..34240d6b240 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx +++ b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx @@ -106,6 +106,8 @@ bool Foam::functionObjects::fieldStatistics::calcStat(const word& fieldName) results_.set(fieldName, result); + if (extrema_) extremaMetaData_.set(fieldName, calcExtremaMetaData(field)); + return true; } @@ -164,4 +166,107 @@ T Foam::functionObjects::fieldStatistics::calcVariance } +template<class GeoField> +Foam::Pair<Foam::functionObjects::fieldStatistics::extremaMetaData> +Foam::functionObjects::fieldStatistics::calcExtremaMetaData +( + const GeoField& field +) +{ + typedef typename GeoField::value_type value_type; + + const label proci = Pstream::myProcNo(); + + // Find the extrema metadata of the specified internal field + + List<value_type> minVs(Pstream::nProcs(), pTraits<value_type>::max); + List<label> minCells(Pstream::nProcs(), Zero); + List<vector> minCs(Pstream::nProcs(), Zero); + + List<value_type> maxVs(Pstream::nProcs(), pTraits<value_type>::min); + List<label> maxCells(Pstream::nProcs(), Zero); + List<vector> maxCs(Pstream::nProcs(), Zero); + + labelPair minMaxIds = findMinMax(field); + + label minId = minMaxIds.first(); + if (minId != -1) + { + minVs[proci] = field[minId]; + minCells[proci] = minId; + minCs[proci] = mesh_.C()[minId]; + } + + label maxId = minMaxIds.second(); + if (maxId != -1) + { + maxVs[proci] = field[maxId]; + maxCells[proci] = maxId; + maxCs[proci] = mesh_.C()[maxId]; + } + + if (!internal_) + { + // Find the extrema metadata of the specified boundary fields + const auto& fieldBoundary = field.boundaryField(); + const auto& CfBoundary = mesh_.C().boundaryField(); + + forAll(fieldBoundary, patchi) + { + const Field<value_type>& fp = fieldBoundary[patchi]; + if (fp.size()) + { + const vectorField& Cfp = CfBoundary[patchi]; + + const labelList& faceCells = + fieldBoundary[patchi].patch().faceCells(); + + minMaxIds = findMinMax(fp); + + minId = minMaxIds.first(); + if (minVs[proci] > fp[minId]) + { + minVs[proci] = fp[minId]; + minCells[proci] = faceCells[minId]; + minCs[proci] = Cfp[minId]; + } + + maxId = minMaxIds.second(); + if (maxVs[proci] < fp[maxId]) + { + maxVs[proci] = fp[maxId]; + maxCells[proci] = faceCells[maxId]; + maxCs[proci] = Cfp[maxId]; + } + } + } + } + + // Collect info from all processors and output + Pstream::allGatherList(minVs); + Pstream::allGatherList(minCells); + Pstream::allGatherList(minCs); + + Pstream::allGatherList(maxVs); + Pstream::allGatherList(maxCells); + Pstream::allGatherList(maxCs); + + extremaMetaData min; + minId = findMin(minVs); + min.value_ = minVs[minId]; + min.procID_ = minId; + min.cellID_ = minCells[minId]; + min.position_ = minCs[minId]; + + extremaMetaData max; + maxId = findMax(maxVs); + max.value_ = maxVs[maxId]; + max.procID_ = maxId; + max.cellID_ = maxCells[maxId]; + max.position_ = maxCs[maxId]; + + return Pair<extremaMetaData>(min, max); +} + + // ************************************************************************* // -- GitLab From 4b88d5e1537d50dd72e6bf086c7a0adba12cc4b6 Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Thu, 13 Mar 2025 17:21:06 +0000 Subject: [PATCH 20/31] SQUASH: 39000e8e1b: remove Info duplications --- .../field/fieldStatistics/fieldStatistics.C | 8 ++++---- .../field/fieldStatistics/fieldStatistics.H | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.C b/src/functionObjects/field/fieldStatistics/fieldStatistics.C index 0c2801836ae..3490dbf66e8 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.C +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.C @@ -196,26 +196,26 @@ void Foam::functionObjects::fieldStatistics::logStatData() const word& name = iter.key(); const variantOutput& value = iter.val(); + Info<< " " << name << " "; std::visit ( - [name](const auto& v) + [](const auto& v) { if constexpr ( is_vectorspace_v<std::decay_t<decltype(v)>> ) { - Info<< " " << name << " "; for (const auto& val : v) Info<< val << " "; - Info<< nl; } else { - Info<< " " << name << " " << v << nl; + Info<< v; } }, value ); + Info<< nl; } } Info<< endl; diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.H b/src/functionObjects/field/fieldStatistics/fieldStatistics.H index 5cdf0b99bd6..ec116a3e9b5 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.H +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.H @@ -280,10 +280,10 @@ class fieldStatistics //- Output the file header information void writeFileHeader(Ostream& os, const word& fieldName); - //- + //- Write the statistical data to the specified file void writeStatData(); - //- + //- Write the statistical data to the standard stream void logStatData(); //- Output the extrema-data file header information -- GitLab From b594deee65513482bd3da90eab2c4d3a941226cf Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Fri, 14 Mar 2025 09:23:24 +0000 Subject: [PATCH 21/31] SQUASH: 970449: update the copyright statement --- src/functionObjects/field/fieldStatistics/fieldStatistics.C | 3 ++- src/functionObjects/field/fieldStatistics/fieldStatistics.H | 3 ++- .../field/fieldStatistics/fieldStatisticsImpl.cxx | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.C b/src/functionObjects/field/fieldStatistics/fieldStatistics.C index 3490dbf66e8..8f9b37d9609 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.C +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.C @@ -5,7 +5,8 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2025 OpenCFD Ltd. + Copyright (C) 2011-2016 OpenFOAM Foundation + Copyright (C) 2015-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.H b/src/functionObjects/field/fieldStatistics/fieldStatistics.H index ec116a3e9b5..14531671e86 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.H +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.H @@ -5,7 +5,8 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2025 OpenCFD Ltd. + Copyright (C) 2011-2017 OpenFOAM Foundation + Copyright (C) 2015-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. diff --git a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx index 34240d6b240..ebbdef80574 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx +++ b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx @@ -5,7 +5,8 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2025 OpenCFD Ltd. + Copyright (C) 2011-2017 OpenFOAM Foundation + Copyright (C) 2015-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. -- GitLab From d0a6d71ae74dee0720c7323f5b5827bcbe2ac1cd Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Fri, 14 Mar 2025 09:29:15 +0000 Subject: [PATCH 22/31] SQUASH: 970449: documentation updates --- .../field/fieldStatistics/fieldStatistics.C | 8 ++++---- .../field/fieldStatistics/fieldStatistics.H | 19 +++++++++++-------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.C b/src/functionObjects/field/fieldStatistics/fieldStatistics.C index 8f9b37d9609..ba9bbccbe4a 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.C +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.C @@ -128,9 +128,9 @@ void Foam::functionObjects::fieldStatistics::writeFileHeader writeHeader(os, word("Field Statistics: " + fieldName)); writeCommented(os, "Time"); - // Number of input statistics (i.e., statistics_) could be lesser than that - // of output statistics (i.e., results_; e.g., cell index of min value). - // Therefore, the output file columns are based on output statistics. + // Number of input statistics (i.e., statistics_) should be the same with + // that of output statistics (i.e., results_). However, for consistency, + // the output file columns are based on output statistics. const auto& result = results_(fieldName); for (const auto& iter : result.csorted()) @@ -359,7 +359,7 @@ bool Foam::functionObjects::fieldStatistics::read(const dictionary& dict) statistics_.insert(m, createStatistic(m, mode_)); } - // Reset and reprepare the output statistics + // Reset the output-statistics container results_.clear(); // Reset and reprepare the output statistics diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.H b/src/functionObjects/field/fieldStatistics/fieldStatistics.H index 14531671e86..3c8bdf1319b 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.H +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.H @@ -31,15 +31,18 @@ Group grpFieldFunctionObjects Description + Calculates various statistics of the specified fields. Operands: \table - Operand | Type | Location - input | - | - - output file | dat | \<case\>/postProcessing/\<FO\>/\<time\>/\<file\> - output field | - | - + Operand | Type | Location + input | vol\<Type\>Field(s) | Registry + output file | dat | \<case\>/postProcessing/\<FO\>/\<time\>/\<file\> + output field | - | - \endtable + where \c \<Type\>=Scalar/Vector/SymmTensor/Tensor. + Usage Minimal example by using \c system/controlDict.functions: \verbatim @@ -53,9 +56,9 @@ Usage // Optional entries mode <word>; - internal <bool>; mean <word>; extrema <bool>; + internal <bool>; // Inherited entries ... @@ -70,10 +73,10 @@ Usage fields | List of operand fields | wordList | yes | - statistics | List of operand statistics | wordList | yes | - mode | Output format of the statistical results | word | no | magnitude + mean | Type of the mean operation | word | no | arithmetic internal | Flag to use internal fields only in computing statistics <!-- --> | bool | no | false - mean | Type of the mean operation | word | no | arithmetic - extrema | Flag to enable extrema metadata calculations | bool | no | false + extrema | Flag to enable extrema data calculations | bool | no | false \endtable Available statistics of the operand field through the \c statistics entry: @@ -180,7 +183,7 @@ class fieldStatistics //- Name of the statistic word name_; - //- Calculate the value of the specified statistic + //- Return the value of the specified statistic std::function<variantOutput(variantInput)> calc; }; -- GitLab From 02959dc870411ea33af6f8b73adcdfd5e002f9dd Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Fri, 14 Mar 2025 09:38:20 +0000 Subject: [PATCH 23/31] SQUASH: 56377ad: documentation updates --- .../field/fieldStatistics/fieldStatistics.C | 30 +++++++++---------- .../field/fieldStatistics/fieldStatistics.H | 14 ++++----- .../fieldStatistics/fieldStatisticsImpl.cxx | 16 +++++----- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.C b/src/functionObjects/field/fieldStatistics/fieldStatistics.C index ba9bbccbe4a..50a3a3dff2a 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.C +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.C @@ -247,25 +247,25 @@ void Foam::functionObjects::fieldStatistics::writeExtremaData() { for (const word& fieldName : fieldSet_.selectionNames()) { - const auto& min = extremaMetaData_(fieldName).first(); - const auto& max = extremaMetaData_(fieldName).second(); + const auto& min = extremaData_(fieldName).first(); + const auto& max = extremaData_(fieldName).second(); - OFstream& efile = *extremaFilePtrs_(fieldName); + OFstream& file = *extremaFilePtrs_(fieldName); - writeCurrentTime(efile); + writeCurrentTime(file); - efile<< token::TAB; + file<< token::TAB; - std::visit([&efile](const auto& v){ efile<< v; }, min.value_); + std::visit([&file](const auto& v){ file<< v; }, min.value_); - efile<< token::TAB + file<< token::TAB << min.procID_ << token::TAB << min.cellID_ << token::TAB << min.position_ << token::TAB; - std::visit([&efile](const auto& v){ efile<< v; }, max.value_); + std::visit([&file](const auto& v){ file<< v; }, max.value_); - efile<< token::TAB + file<< token::TAB << max.procID_ << token::TAB << max.cellID_ << token::TAB << max.position_ << nl; @@ -277,8 +277,8 @@ void Foam::functionObjects::fieldStatistics::logExtremaData() { for (const word& fieldName : fieldSet_.selectionNames()) { - const auto& min = extremaMetaData_(fieldName).first(); - const auto& max = extremaMetaData_(fieldName).second(); + const auto& min = extremaData_(fieldName).first(); + const auto& max = extremaData_(fieldName).second(); const word outputName = (mode_ == mdMag) @@ -362,8 +362,8 @@ bool Foam::functionObjects::fieldStatistics::read(const dictionary& dict) // Reset the output-statistics container results_.clear(); - // Reset and reprepare the output statistics - extremaMetaData_.clear(); + // Reset the extrema-data container + extremaData_.clear(); return true; } @@ -413,7 +413,7 @@ bool Foam::functionObjects::fieldStatistics::execute() if (extrema_) { - const auto& min = extremaMetaData_(fieldName).first(); + const auto& min = extremaData_(fieldName).first(); std::visit ( [this, fieldName](const auto& v) @@ -426,7 +426,7 @@ bool Foam::functionObjects::fieldStatistics::execute() this->setResult(word(fieldName + "_min_cellID"), min.cellID_); this->setResult(word(fieldName + "_min_position"), min.position_); - const auto& max = extremaMetaData_(fieldName).second(); + const auto& max = extremaData_(fieldName).second(); std::visit ( [this, fieldName](const auto& v) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.H b/src/functionObjects/field/fieldStatistics/fieldStatistics.H index 3c8bdf1319b..dc8f38d0fcc 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.H +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.H @@ -187,8 +187,8 @@ class fieldStatistics std::function<variantOutput(variantInput)> calc; }; - //- Class to encapsulate metadata about minima and maxima - struct extremaMetaData + //- Class to encapsulate the data about minima and maxima + struct extremaData { //- Value of the extremum variantOutput value_; @@ -209,7 +209,7 @@ class fieldStatistics //- Flag to use internal fields only in computing statistics bool internal_; - //- Flag to enable extrema metadata calculations + //- Flag to enable extrema data calculations bool extrema_; //- Output-format mode - only applicable for tensor ranks > 0 @@ -233,8 +233,8 @@ class fieldStatistics //- Hash table containing all statistical results per field HashTable<HashTable<variantOutput>> results_; - //- Hash table containing the metadata of the extrema per field - HashTable<Pair<extremaMetaData>> extremaMetaData_; + //- Hash table containing the data of the extrema per field + HashTable<Pair<extremaData>> extremaData_; // Private Member Functions @@ -277,9 +277,9 @@ class fieldStatistics const GeoField& field ); - //- Return the extrema metadata of the specified field + //- Return the extrema data of the specified field template<class GeoField> - Pair<extremaMetaData> calcExtremaMetaData(const GeoField& field); + Pair<extremaData> calcExtremaData(const GeoField& field); //- Output the file header information void writeFileHeader(Ostream& os, const word& fieldName); diff --git a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx index ebbdef80574..7b5cd8d1cf6 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx +++ b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx @@ -107,7 +107,7 @@ bool Foam::functionObjects::fieldStatistics::calcStat(const word& fieldName) results_.set(fieldName, result); - if (extrema_) extremaMetaData_.set(fieldName, calcExtremaMetaData(field)); + if (extrema_) extremaData_.set(fieldName, calcExtremaData(field)); return true; } @@ -168,8 +168,8 @@ T Foam::functionObjects::fieldStatistics::calcVariance template<class GeoField> -Foam::Pair<Foam::functionObjects::fieldStatistics::extremaMetaData> -Foam::functionObjects::fieldStatistics::calcExtremaMetaData +Foam::Pair<Foam::functionObjects::fieldStatistics::extremaData> +Foam::functionObjects::fieldStatistics::calcExtremaData ( const GeoField& field ) @@ -178,7 +178,7 @@ Foam::functionObjects::fieldStatistics::calcExtremaMetaData const label proci = Pstream::myProcNo(); - // Find the extrema metadata of the specified internal field + // Find the extrema data of the specified internal field List<value_type> minVs(Pstream::nProcs(), pTraits<value_type>::max); List<label> minCells(Pstream::nProcs(), Zero); @@ -208,7 +208,7 @@ Foam::functionObjects::fieldStatistics::calcExtremaMetaData if (!internal_) { - // Find the extrema metadata of the specified boundary fields + // Find the extrema data of the specified boundary fields const auto& fieldBoundary = field.boundaryField(); const auto& CfBoundary = mesh_.C().boundaryField(); @@ -252,21 +252,21 @@ Foam::functionObjects::fieldStatistics::calcExtremaMetaData Pstream::allGatherList(maxCells); Pstream::allGatherList(maxCs); - extremaMetaData min; + extremaData min; minId = findMin(minVs); min.value_ = minVs[minId]; min.procID_ = minId; min.cellID_ = minCells[minId]; min.position_ = minCs[minId]; - extremaMetaData max; + extremaData max; maxId = findMax(maxVs); max.value_ = maxVs[maxId]; max.procID_ = maxId; max.cellID_ = maxCells[maxId]; max.position_ = maxCs[maxId]; - return Pair<extremaMetaData>(min, max); + return Pair<extremaData>(min, max); } -- GitLab From b34dc2a5a3465e3ad2cc2d2cade2c0fffbcaf429 Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Fri, 14 Mar 2025 10:12:39 +0000 Subject: [PATCH 24/31] SQUASH: 970449: update the fields during the execution Update the fields at the execution stage instead of the 'read' stage. Otherwise, various fields which are registered after the 'read' stage will be missed. --- .../field/fieldStatistics/fieldStatistics.C | 17 +++++++++++------ .../fieldStatistics/fieldStatisticsImpl.cxx | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.C b/src/functionObjects/field/fieldStatistics/fieldStatistics.C index 50a3a3dff2a..f239a161c6d 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.C +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.C @@ -91,22 +91,23 @@ Foam::functionObjects::fieldStatistics::createStatistic if (statName == "min") { - if (mode == mdMag) return mag(calcMin<BaseType>(arg)); + // if (mode == mdMag) return mag(calcMin<BaseType>(arg)); + if (mode == mdMag) return calcMin<scalar>(mag(arg)); else return calcMin<BaseType>(arg); } else if (statName == "max") { - if (mode == mdMag) return mag(calcMax<BaseType>(arg)); + if (mode == mdMag) return calcMax<scalar>(mag(arg)); else return calcMax<BaseType>(arg); } else if (statName == "mean") { - if (mode == mdMag) return mag(calcMean<BaseType>(arg)); + if (mode == mdMag) return calcMean<scalar>(mag(arg)); else return calcMean<BaseType>(arg); } else if (statName == "variance") { - if (mode == mdMag) return mag(calcVariance<BaseType>(arg)); + if (mode == mdMag) return calcVariance<scalar>(mag(arg)); else return calcVariance<BaseType>(arg); } else return scalar{}; // Default case (for compiler) @@ -190,7 +191,10 @@ void Foam::functionObjects::fieldStatistics::logStatData() if (!results.size()) break; - Info<< nl << " Field " << fieldName << nl; + const word outputName = + (mode_ == mdMag) ? word("mag(" + fieldName + ")") : fieldName; + + Info<< nl << " Field " << outputName << nl; for (const auto& iter : results.csorted()) { @@ -349,7 +353,6 @@ bool Foam::functionObjects::fieldStatistics::read(const dictionary& dict) // Reset and reprepare the input field names fieldSet_.clear(); fieldSet_.read(dict); - fieldSet_.updateSelection(); // Reset and reprepare the input statistics statistics_.clear(); @@ -371,6 +374,8 @@ bool Foam::functionObjects::fieldStatistics::read(const dictionary& dict) bool Foam::functionObjects::fieldStatistics::execute() { + fieldSet_.updateSelection(); + // Calculate the specified statistics for the specified fields for (const word& fieldName : fieldSet_.selectionNames()) { diff --git a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx index 7b5cd8d1cf6..58ed6f6a0dc 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx +++ b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx @@ -163,7 +163,7 @@ T Foam::functionObjects::fieldStatistics::calcVariance return T{}; } - return 1/(n-1)*var; + return 1.0/(n - 1.0)*var; } -- GitLab From 4e287cec4cdc40c9a788a969ac4b741bdec5cf9a Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Fri, 14 Mar 2025 12:03:53 +0000 Subject: [PATCH 25/31] SQUASH: 56377ad: various changes to the extrema functionality --- .../field/fieldStatistics/fieldStatistics.C | 18 ++++++++---------- .../field/fieldStatistics/fieldStatistics.H | 4 ++-- .../fieldStatistics/fieldStatisticsImpl.cxx | 11 ++++++++++- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.C b/src/functionObjects/field/fieldStatistics/fieldStatistics.C index f239a161c6d..4b449ee7d5f 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.C +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.C @@ -251,8 +251,8 @@ void Foam::functionObjects::fieldStatistics::writeExtremaData() { for (const word& fieldName : fieldSet_.selectionNames()) { - const auto& min = extremaData_(fieldName).first(); - const auto& max = extremaData_(fieldName).second(); + const auto& min = extremaResults_(fieldName).first(); + const auto& max = extremaResults_(fieldName).second(); OFstream& file = *extremaFilePtrs_(fieldName); @@ -281,13 +281,11 @@ void Foam::functionObjects::fieldStatistics::logExtremaData() { for (const word& fieldName : fieldSet_.selectionNames()) { - const auto& min = extremaData_(fieldName).first(); - const auto& max = extremaData_(fieldName).second(); + const auto& min = extremaResults_(fieldName).first(); + const auto& max = extremaResults_(fieldName).second(); const word outputName = - (mode_ == mdMag) - ? word("mag(" + fieldName + ")") - : fieldName; + (mode_ == mdMag) ? word("mag(" + fieldName + ")") : fieldName; std::visit ( @@ -366,7 +364,7 @@ bool Foam::functionObjects::fieldStatistics::read(const dictionary& dict) results_.clear(); // Reset the extrema-data container - extremaData_.clear(); + extremaResults_.clear(); return true; } @@ -418,7 +416,7 @@ bool Foam::functionObjects::fieldStatistics::execute() if (extrema_) { - const auto& min = extremaData_(fieldName).first(); + const auto& min = extremaResults_(fieldName).first(); std::visit ( [this, fieldName](const auto& v) @@ -431,7 +429,7 @@ bool Foam::functionObjects::fieldStatistics::execute() this->setResult(word(fieldName + "_min_cellID"), min.cellID_); this->setResult(word(fieldName + "_min_position"), min.position_); - const auto& max = extremaData_(fieldName).second(); + const auto& max = extremaResults_(fieldName).second(); std::visit ( [this, fieldName](const auto& v) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.H b/src/functionObjects/field/fieldStatistics/fieldStatistics.H index dc8f38d0fcc..94cf7e41dc1 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.H +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.H @@ -233,8 +233,8 @@ class fieldStatistics //- Hash table containing all statistical results per field HashTable<HashTable<variantOutput>> results_; - //- Hash table containing the data of the extrema per field - HashTable<Pair<extremaData>> extremaData_; + //- Hash table containing the results of the extrema per field + HashTable<Pair<extremaData>> extremaResults_; // Private Member Functions diff --git a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx index 58ed6f6a0dc..aaa5d9ac63b 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx +++ b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx @@ -107,7 +107,16 @@ bool Foam::functionObjects::fieldStatistics::calcStat(const word& fieldName) results_.set(fieldName, result); - if (extrema_) extremaData_.set(fieldName, calcExtremaData(field)); + if (extrema_) + { + extremaResults_.set + ( + fieldName, + (mode_ == mdMag) + ? calcExtremaData(mag(field)()) + : calcExtremaData(field) + ); + } return true; } -- GitLab From 92ddaf6755c253326bee2dc9a9131eb57b25c54b Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Fri, 14 Mar 2025 17:10:36 +0000 Subject: [PATCH 26/31] SQUASH: 970449: add the spherical tensor --- .../field/fieldStatistics/fieldStatistics.C | 4 ++-- .../field/fieldStatistics/fieldStatistics.H | 7 ++++--- .../field/fieldStatistics/fieldStatisticsImpl.cxx | 3 +-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.C b/src/functionObjects/field/fieldStatistics/fieldStatistics.C index 4b449ee7d5f..590e6105ee6 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.C +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.C @@ -5,8 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2015-2025 OpenCFD Ltd. + Copyright (C) 2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -381,6 +380,7 @@ bool Foam::functionObjects::fieldStatistics::execute() ( calcStat<scalar>(fieldName) || calcStat<vector>(fieldName) + || calcStat<sphericalTensor>(fieldName) || calcStat<symmTensor>(fieldName) || calcStat<tensor>(fieldName) ); diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.H b/src/functionObjects/field/fieldStatistics/fieldStatistics.H index 94cf7e41dc1..eb5c7bfbc9f 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.H +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.H @@ -5,8 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2011-2017 OpenFOAM Foundation - Copyright (C) 2015-2025 OpenCFD Ltd. + Copyright (C) 2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -41,7 +40,7 @@ Description output field | - | - \endtable - where \c \<Type\>=Scalar/Vector/SymmTensor/Tensor. + where \c \<Type\>=Scalar/Vector/SphericalTensor/SymmTensor/Tensor. Usage Minimal example by using \c system/controlDict.functions: @@ -164,6 +163,7 @@ class fieldStatistics < scalarField, vectorField, + sphericalTensorField, symmTensorField, tensorField >; @@ -173,6 +173,7 @@ class fieldStatistics < scalar, vector, + sphericalTensor, symmTensor, tensor >; diff --git a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx index aaa5d9ac63b..a2719307b84 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx +++ b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx @@ -5,8 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2011-2017 OpenFOAM Foundation - Copyright (C) 2015-2025 OpenCFD Ltd. + Copyright (C) 2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. -- GitLab From 31deb5f3be3138dc893578bff043eea6d0ac3338 Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Fri, 14 Mar 2025 17:12:34 +0000 Subject: [PATCH 27/31] SQUASH: rename .C as .cxx --- src/functionObjects/field/Make/files | 2 +- .../fieldStatistics/{fieldStatistics.C => fieldStatistics.cxx} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/functionObjects/field/fieldStatistics/{fieldStatistics.C => fieldStatistics.cxx} (100%) diff --git a/src/functionObjects/field/Make/files b/src/functionObjects/field/Make/files index 060eb3e1685..bd6b60b3736 100644 --- a/src/functionObjects/field/Make/files +++ b/src/functionObjects/field/Make/files @@ -154,6 +154,6 @@ resolutionIndex/resolutionIndexModels/CelikEtaIndex/CelikEtaIndex.C age/age.C comfort/comfort.C -fieldStatistics/fieldStatistics.C +fieldStatistics/fieldStatistics.cxx LIB = $(FOAM_LIBBIN)/libfieldFunctionObjects diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.C b/src/functionObjects/field/fieldStatistics/fieldStatistics.cxx similarity index 100% rename from src/functionObjects/field/fieldStatistics/fieldStatistics.C rename to src/functionObjects/field/fieldStatistics/fieldStatistics.cxx -- GitLab From 883d5ed971e2a1c14e66690ed063b05402a83d3a Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Fri, 14 Mar 2025 17:17:15 +0000 Subject: [PATCH 28/31] STYLE: avoid any trailing spaces --- .../field/fieldStatistics/fieldStatistics.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatistics.cxx b/src/functionObjects/field/fieldStatistics/fieldStatistics.cxx index 590e6105ee6..27fbd003967 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatistics.cxx +++ b/src/functionObjects/field/fieldStatistics/fieldStatistics.cxx @@ -200,7 +200,7 @@ void Foam::functionObjects::fieldStatistics::logStatData() const word& name = iter.key(); const variantOutput& value = iter.val(); - Info<< " " << name << " "; + Info<< " " << name; std::visit ( [](const auto& v) @@ -210,11 +210,11 @@ void Foam::functionObjects::fieldStatistics::logStatData() is_vectorspace_v<std::decay_t<decltype(v)>> ) { - for (const auto& val : v) Info<< val << " "; + for (const auto& val : v) Info<< " " << val; } else { - Info<< v; + Info<< " " << v; } }, value -- GitLab From 188bce8c38c276182f8f65e9fde06cd9b2ba0afd Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Mon, 31 Mar 2025 09:12:44 +0100 Subject: [PATCH 29/31] SQUASH: remove the duplicate logic --- .../field/fieldStatistics/fieldStatisticsImpl.cxx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx index a2719307b84..142f1248f9e 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx +++ b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx @@ -80,11 +80,6 @@ bool Foam::functionObjects::fieldStatistics::calcStat(const word& fieldName) { typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType; - if (!obr_.foundObject<VolFieldType>(fieldName)) - { - return false; - } - const auto* fieldp = obr_.cfindObject<VolFieldType>(fieldName); if (!fieldp) { -- GitLab From d5764cee628948c3c51460f0e2a0e9633ed0a3e5 Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Mon, 31 Mar 2025 11:15:51 +0100 Subject: [PATCH 30/31] SQUASH: simplify the weighted average routine --- .../field/fieldStatistics/fieldStatisticsImpl.cxx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx index 142f1248f9e..b5c410402bd 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx +++ b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx @@ -121,8 +121,7 @@ T Foam::functionObjects::fieldStatistics::calcMean(const Field<T>& field) { if (internal_ && (mean_ == VOLUMETRIC)) { - const Field<scalar>& V = mesh_.V(); - return (gSum(V*field)/gSum(V)); + return gWeightedAverage(mesh_.V(), field); } return gAverage(field); -- GitLab From dc2792d0f1bad5e35dbf4a8c2974eb7a1bf8c3c1 Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin <kutalmis.bercin@esi-group.com> Date: Mon, 31 Mar 2025 11:24:51 +0100 Subject: [PATCH 31/31] SQUASH: modernize the calcExtremaData routine --- .../fieldStatistics/fieldStatisticsImpl.cxx | 40 +++++++++---------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx index b5c410402bd..7499b6c742c 100644 --- a/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx +++ b/src/functionObjects/field/fieldStatistics/fieldStatisticsImpl.cxx @@ -192,20 +192,18 @@ Foam::functionObjects::fieldStatistics::calcExtremaData labelPair minMaxIds = findMinMax(field); - label minId = minMaxIds.first(); - if (minId != -1) + if (label celli = minMaxIds.first(); celli >= 0) { - minVs[proci] = field[minId]; - minCells[proci] = minId; - minCs[proci] = mesh_.C()[minId]; + minVs[proci] = field[celli]; + minCells[proci] = celli; + minCs[proci] = mesh_.C()[celli]; } - label maxId = minMaxIds.second(); - if (maxId != -1) + if (label celli = minMaxIds.second(); celli >= 0) { - maxVs[proci] = field[maxId]; - maxCells[proci] = maxId; - maxCs[proci] = mesh_.C()[maxId]; + maxVs[proci] = field[celli]; + maxCells[proci] = celli; + maxCs[proci] = mesh_.C()[celli]; } if (!internal_) @@ -226,20 +224,18 @@ Foam::functionObjects::fieldStatistics::calcExtremaData minMaxIds = findMinMax(fp); - minId = minMaxIds.first(); - if (minVs[proci] > fp[minId]) + if (label celli = minMaxIds.first(); minVs[proci] > fp[celli]) { - minVs[proci] = fp[minId]; - minCells[proci] = faceCells[minId]; - minCs[proci] = Cfp[minId]; + minVs[proci] = fp[celli]; + minCells[proci] = faceCells[celli]; + minCs[proci] = Cfp[celli]; } - maxId = minMaxIds.second(); - if (maxVs[proci] < fp[maxId]) + if (label celli = minMaxIds.second(); maxVs[proci] < fp[celli]) { - maxVs[proci] = fp[maxId]; - maxCells[proci] = faceCells[maxId]; - maxCs[proci] = Cfp[maxId]; + maxVs[proci] = fp[celli]; + maxCells[proci] = faceCells[celli]; + maxCs[proci] = Cfp[celli]; } } } @@ -255,14 +251,14 @@ Foam::functionObjects::fieldStatistics::calcExtremaData Pstream::allGatherList(maxCs); extremaData min; - minId = findMin(minVs); + const label minId = findMin(minVs); min.value_ = minVs[minId]; min.procID_ = minId; min.cellID_ = minCells[minId]; min.position_ = minCs[minId]; extremaData max; - maxId = findMax(maxVs); + const label maxId = findMax(maxVs); max.value_ = maxVs[maxId]; max.procID_ = maxId; max.cellID_ = maxCells[maxId]; -- GitLab