From 6dadd3d33e803221123827bb7beb14818e4a3e97 Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@esi-group.com> Date: Thu, 1 Feb 2024 15:43:42 +0100 Subject: [PATCH] ENH: include cloudFunction results in vtkCloud writing (#3094) - process the contents of the cloud object registry, which enables output support for calculated values such as Reynolds, Weber numbers etc. ENH: select any/all clouds by default instead of defaultCloud - adds robustness --- .../lagrangian/dataCloud/dataCloud.C | 37 +++++++--- .../lagrangian/dataCloud/dataCloud.H | 12 ++-- .../lagrangian/dataCloud/dataCloudTemplates.C | 8 +-- .../lagrangian/vtkCloud/vtkCloud.C | 68 +++++++++++++------ .../lagrangian/vtkCloud/vtkCloud.H | 8 +-- .../lagrangian/vtkCloud/vtkCloudTemplates.C | 20 ++++-- 6 files changed, 102 insertions(+), 51 deletions(-) diff --git a/src/functionObjects/lagrangian/dataCloud/dataCloud.C b/src/functionObjects/lagrangian/dataCloud/dataCloud.C index e34be5bc705..8ff65489f56 100644 --- a/src/functionObjects/lagrangian/dataCloud/dataCloud.C +++ b/src/functionObjects/lagrangian/dataCloud/dataCloud.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018-2022 OpenCFD Ltd. + Copyright (C) 2018-2024 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -52,12 +52,16 @@ bool Foam::functionObjects::dataCloud::writeCloud const word& cloudName ) { - const auto* objPtr = mesh_.findObject<cloud>(cloudName); - if (!objPtr) + applyFilter_ = false; + + const auto* cloudPtr = mesh_.findObject<cloud>(cloudName); + if (!cloudPtr) { return false; } + const auto& currCloud = *cloudPtr; + objectRegistry obrTmp ( IOobject @@ -71,7 +75,7 @@ bool Foam::functionObjects::dataCloud::writeCloud ) ); - objPtr->writeObjects(obrTmp); + currCloud.writeObjects(obrTmp); const auto* pointsPtr = cloud::findIOPosition(obrTmp); @@ -86,7 +90,10 @@ bool Foam::functionObjects::dataCloud::writeCloud // Number of parcels (locally) - label nParcels = (applyFilter_ ? parcelAddr_.count() : pointsPtr->size()); + const label nParcels + ( + applyFilter_ ? parcelAddr_.count() : pointsPtr->size() + ); // Total number of parcels on all processes const label nTotParcels = returnReduce(nParcels, sumOp<label>()); @@ -104,9 +111,9 @@ bool Foam::functionObjects::dataCloud::writeCloud return false; } - if (Pstream::master()) + if (UPstream::master()) { - mkDir(outputName.path()); + Foam::mkDir(outputName.path()); } return @@ -163,12 +170,15 @@ bool Foam::functionObjects::dataCloud::read(const dictionary& dict) selectClouds_.clear(); dict.readIfPresent("clouds", selectClouds_); + selectClouds_.uniq(); if (selectClouds_.empty()) { - selectClouds_.resize(1); - selectClouds_.first() = - dict.getOrDefault<word>("cloud", cloud::defaultName); + word cloudName; + if (dict.readIfPresent("cloud", cloudName)) + { + selectClouds_.push_back(std::move(cloudName)); + } } dict.readEntry("field", fieldName_); @@ -209,7 +219,12 @@ bool Foam::functionObjects::dataCloud::execute() bool Foam::functionObjects::dataCloud::write() { - const wordList cloudNames(mesh_.sortedNames<cloud>(selectClouds_)); + const wordList cloudNames + ( + selectClouds_.empty() + ? mesh_.sortedNames<cloud>() + : mesh_.sortedNames<cloud>(selectClouds_) + ); if (cloudNames.empty()) { diff --git a/src/functionObjects/lagrangian/dataCloud/dataCloud.H b/src/functionObjects/lagrangian/dataCloud/dataCloud.H index 4943ccf1c70..33b2791b6bb 100644 --- a/src/functionObjects/lagrangian/dataCloud/dataCloud.H +++ b/src/functionObjects/lagrangian/dataCloud/dataCloud.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018-2020 OpenCFD Ltd. + Copyright (C) 2018-2024 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -48,10 +48,10 @@ Description \heading Basic Usage \table Property | Description | Required | Default - type | Type name: dataCloud | yes | + type | Type name: dataCloud | yes | clouds | List of clouds (name or regex) | no | - cloud | Cloud name | no | defaultCloud - field | Name of the field | yes | + cloud | Cloud name | no | + field | Name of the field | yes | selection | Parcel selection control | no | empty-dict \endtable @@ -103,7 +103,7 @@ class dataCloud public fvMeshFunctionObject, public Foam::Detail::parcelSelection { - // Private data + // Private Data //- The printf format for zero-padding names string printf_; @@ -177,7 +177,7 @@ class dataCloud bool writeField ( const fileName& outputName, - const objectRegistry& obrTmp + const objectRegistry& obr ) const; diff --git a/src/functionObjects/lagrangian/dataCloud/dataCloudTemplates.C b/src/functionObjects/lagrangian/dataCloud/dataCloudTemplates.C index d2b6e16b130..67319c08efe 100644 --- a/src/functionObjects/lagrangian/dataCloud/dataCloudTemplates.C +++ b/src/functionObjects/lagrangian/dataCloud/dataCloudTemplates.C @@ -171,10 +171,10 @@ template<class Type> bool Foam::functionObjects::dataCloud::writeField ( const fileName& outputName, - const objectRegistry& obrTmp + const objectRegistry& obr ) const { - const auto* pointsPtr = cloud::findIOPosition(obrTmp); + const auto* pointsPtr = cloud::findIOPosition(obr); if (!pointsPtr) { @@ -185,8 +185,8 @@ bool Foam::functionObjects::dataCloud::writeField // Fields are not always on all processors (eg, multi-component parcels). // Thus need to resolve between all processors. - const List<Type>* fldPtr = obrTmp.findObject<IOField<Type>>(fieldName_); - const List<Type>& values = (fldPtr ? *fldPtr : List<Type>()); + const List<Type>* fldPtr = obr.findObject<IOField<Type>>(fieldName_); + const List<Type>& values = (fldPtr ? *fldPtr : List<Type>::null()); if (!returnReduceOr(fldPtr != nullptr)) { diff --git a/src/functionObjects/lagrangian/vtkCloud/vtkCloud.C b/src/functionObjects/lagrangian/vtkCloud/vtkCloud.C index 08557fd4014..223fa2feab4 100644 --- a/src/functionObjects/lagrangian/vtkCloud/vtkCloud.C +++ b/src/functionObjects/lagrangian/vtkCloud/vtkCloud.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018-2022 OpenCFD Ltd. + Copyright (C) 2018-2024 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -101,12 +101,16 @@ bool Foam::functionObjects::vtkCloud::writeCloud const word& cloudName ) { - const auto* objPtr = mesh_.findObject<cloud>(cloudName); - if (!objPtr) + applyFilter_ = false; + + const auto* cloudPtr = mesh_.cfindObject<cloud>(cloudName); + if (!cloudPtr) { return false; } + const auto& currCloud = *cloudPtr; + objectRegistry obrTmp ( IOobject @@ -120,7 +124,7 @@ bool Foam::functionObjects::vtkCloud::writeCloud ) ); - objPtr->writeObjects(obrTmp); + currCloud.writeObjects(obrTmp); const auto* pointsPtr = cloud::findIOPosition(obrTmp); @@ -135,7 +139,10 @@ bool Foam::functionObjects::vtkCloud::writeCloud // Number of parcels (locally) - label nParcels = (applyFilter_ ? parcelAddr_.count() : pointsPtr->size()); + const label nParcels + ( + applyFilter_ ? parcelAddr_.count() : pointsPtr->size() + ); // Total number of parcels on all processes const label nTotParcels = returnReduce(nParcels, sumOp<label>()); @@ -163,9 +170,9 @@ bool Foam::functionObjects::vtkCloud::writeCloud << exit(FatalError); } - if (Pstream::master()) + if (UPstream::master()) { - mkDir(file.path()); + Foam::mkDir(file.path()); os.open(file); format = writeOpts_.newFormatter(os); @@ -238,7 +245,7 @@ bool Foam::functionObjects::vtkCloud::writeCloud } - if (Pstream::master()) + if (UPstream::master()) { format().flush(); format().endDataArray(); @@ -270,7 +277,7 @@ bool Foam::functionObjects::vtkCloud::writeCloud // Write fields - if (Pstream::master()) + if (UPstream::master()) { if (useVerts_) { @@ -282,13 +289,28 @@ bool Foam::functionObjects::vtkCloud::writeCloud } } - DynamicList<word> written(obrTmp.size()); + DynamicList<word> written(obrTmp.size() + currCloud.objectRegistry::size()); - written.append(writeFields<label>(format, obrTmp, nTotParcels)); - written.append(writeFields<scalar>(format, obrTmp, nTotParcels)); - written.append(writeFields<vector>(format, obrTmp, nTotParcels)); + written.push_back + ( + writeFields<label>(format, obrTmp, nTotParcels) + ); + written.push_back + ( + writeFields<scalar>(format, obrTmp, nTotParcels) + ); + written.push_back + ( + writeFields<vector>(format, obrTmp, nTotParcels) + ); + + // Any cloudFunctions results + written.push_back + ( + writeFields<scalar>(format, currCloud, nTotParcels) + ); - if (Pstream::master()) + if (UPstream::master()) { if (useVerts_) { @@ -415,12 +437,15 @@ bool Foam::functionObjects::vtkCloud::read(const dictionary& dict) selectClouds_.clear(); dict.readIfPresent("clouds", selectClouds_); + selectClouds_.uniq(); if (selectClouds_.empty()) { - selectClouds_.resize(1); - selectClouds_.first() = - dict.getOrDefault<word>("cloud", cloud::defaultName); + word cloudName; + if (dict.readIfPresent("cloud", cloudName)) + { + selectClouds_.push_back(std::move(cloudName)); + } } selectFields_.clear(); @@ -463,7 +488,12 @@ bool Foam::functionObjects::vtkCloud::execute() bool Foam::functionObjects::vtkCloud::write() { - const wordList cloudNames(mesh_.sortedNames<cloud>(selectClouds_)); + const wordList cloudNames + ( + selectClouds_.empty() + ? mesh_.sortedNames<cloud>() + : mesh_.sortedNames<cloud>(selectClouds_) + ); if (cloudNames.empty()) { @@ -498,7 +528,7 @@ bool Foam::functionObjects::vtkCloud::write() Log << " cloud : " << time_.relativePath(outputName) << endl; - if (Pstream::master()) + if (UPstream::master()) { // Add to file-series and emit as JSON fileName seriesName(vtk::seriesWriter::base(outputName)); diff --git a/src/functionObjects/lagrangian/vtkCloud/vtkCloud.H b/src/functionObjects/lagrangian/vtkCloud/vtkCloud.H index 9511de0db04..648414eb2c3 100644 --- a/src/functionObjects/lagrangian/vtkCloud/vtkCloud.H +++ b/src/functionObjects/lagrangian/vtkCloud/vtkCloud.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018-2020 OpenCFD Ltd. + Copyright (C) 2018-2024 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -81,7 +81,7 @@ Description Property | Description | Required | Default type | Type name: vtkCloud | yes | clouds | List of clouds (name or regex) | no | - cloud | Cloud name | no | defaultCloud + cloud | Cloud name | no | fields | List of fields (name or regex) | no | selection | Parcel selection control | no | empty-dict \endtable @@ -160,7 +160,7 @@ class vtkCloud public fvMeshFunctionObject, public Foam::Detail::parcelSelection { - // Private data + // Private Data //- Writer options vtk::outputOptions writeOpts_; @@ -209,7 +209,7 @@ class vtkCloud wordList writeFields ( autoPtr<vtk::formatter>& format, - const objectRegistry& obrTmp, + const objectRegistry& obr, const label nTotParcels ) const; diff --git a/src/functionObjects/lagrangian/vtkCloud/vtkCloudTemplates.C b/src/functionObjects/lagrangian/vtkCloud/vtkCloudTemplates.C index c28bc1fe4c7..f61c1de41e6 100644 --- a/src/functionObjects/lagrangian/vtkCloud/vtkCloudTemplates.C +++ b/src/functionObjects/lagrangian/vtkCloud/vtkCloudTemplates.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018-2022 OpenCFD Ltd. + Copyright (C) 2018-2024 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -33,7 +33,7 @@ template<class Type> Foam::wordList Foam::functionObjects::vtkCloud::writeFields ( autoPtr<vtk::formatter>& format, - const objectRegistry& obrTmp, + const objectRegistry& obr, const label nTotParcels ) const { @@ -55,16 +55,22 @@ Foam::wordList Foam::functionObjects::vtkCloud::writeFields // Fields are not always on all processors (eg, multi-component parcels). // Thus need to resolve names between all processors. - wordList fieldNames(obrTmp.names<IOField<Type>>()); + wordList fieldNames = + ( + selectFields_.size() + ? obr.names<IOField<Type>>(selectFields_) + : obr.names<IOField<Type>>() + ); + Pstream::combineReduce(fieldNames, ListOps::uniqueEqOp<word>()); Foam::sort(fieldNames); // Consistent order for (const word& fieldName : fieldNames) { - const List<Type>* fldPtr = obrTmp.findObject<IOField<Type>>(fieldName); - const List<Type>& values = (fldPtr ? *fldPtr : List<Type>()); + const List<Type>* fldPtr = obr.findObject<IOField<Type>>(fieldName); + const List<Type>& values = (fldPtr ? *fldPtr : List<Type>::null()); - if (Pstream::master()) + if (UPstream::master()) { if (std::is_same<label, typename pTraits<Type>::cmptType>::value) { @@ -93,7 +99,7 @@ Foam::wordList Foam::functionObjects::vtkCloud::writeFields vtk::writeListParallel(format.ref(), values); } - if (Pstream::master()) + if (UPstream::master()) { // Non-legacy format().flush(); -- GitLab