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
This commit is contained in:
Mark Olesen
2024-02-01 15:43:42 +01:00
parent 3a43aae7c0
commit 6dadd3d33e
6 changed files with 102 additions and 51 deletions

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2018-2022 OpenCFD Ltd. Copyright (C) 2018-2024 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -52,12 +52,16 @@ bool Foam::functionObjects::dataCloud::writeCloud
const word& cloudName const word& cloudName
) )
{ {
const auto* objPtr = mesh_.findObject<cloud>(cloudName); applyFilter_ = false;
if (!objPtr)
const auto* cloudPtr = mesh_.findObject<cloud>(cloudName);
if (!cloudPtr)
{ {
return false; return false;
} }
const auto& currCloud = *cloudPtr;
objectRegistry obrTmp objectRegistry obrTmp
( (
IOobject IOobject
@ -71,7 +75,7 @@ bool Foam::functionObjects::dataCloud::writeCloud
) )
); );
objPtr->writeObjects(obrTmp); currCloud.writeObjects(obrTmp);
const auto* pointsPtr = cloud::findIOPosition(obrTmp); const auto* pointsPtr = cloud::findIOPosition(obrTmp);
@ -86,7 +90,10 @@ bool Foam::functionObjects::dataCloud::writeCloud
// Number of parcels (locally) // 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 // Total number of parcels on all processes
const label nTotParcels = returnReduce(nParcels, sumOp<label>()); const label nTotParcels = returnReduce(nParcels, sumOp<label>());
@ -104,9 +111,9 @@ bool Foam::functionObjects::dataCloud::writeCloud
return false; return false;
} }
if (Pstream::master()) if (UPstream::master())
{ {
mkDir(outputName.path()); Foam::mkDir(outputName.path());
} }
return return
@ -163,12 +170,15 @@ bool Foam::functionObjects::dataCloud::read(const dictionary& dict)
selectClouds_.clear(); selectClouds_.clear();
dict.readIfPresent("clouds", selectClouds_); dict.readIfPresent("clouds", selectClouds_);
selectClouds_.uniq();
if (selectClouds_.empty()) if (selectClouds_.empty())
{ {
selectClouds_.resize(1); word cloudName;
selectClouds_.first() = if (dict.readIfPresent("cloud", cloudName))
dict.getOrDefault<word>("cloud", cloud::defaultName); {
selectClouds_.push_back(std::move(cloudName));
}
} }
dict.readEntry("field", fieldName_); dict.readEntry("field", fieldName_);
@ -209,7 +219,12 @@ bool Foam::functionObjects::dataCloud::execute()
bool Foam::functionObjects::dataCloud::write() 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()) if (cloudNames.empty())
{ {

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2018-2020 OpenCFD Ltd. Copyright (C) 2018-2024 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -48,10 +48,10 @@ Description
\heading Basic Usage \heading Basic Usage
\table \table
Property | Description | Required | Default Property | Description | Required | Default
type | Type name: dataCloud | yes | type | Type name: dataCloud | yes |
clouds | List of clouds (name or regex) | no | clouds | List of clouds (name or regex) | no |
cloud | Cloud name | no | defaultCloud cloud | Cloud name | no |
field | Name of the field | yes | field | Name of the field | yes |
selection | Parcel selection control | no | empty-dict selection | Parcel selection control | no | empty-dict
\endtable \endtable
@ -103,7 +103,7 @@ class dataCloud
public fvMeshFunctionObject, public fvMeshFunctionObject,
public Foam::Detail::parcelSelection public Foam::Detail::parcelSelection
{ {
// Private data // Private Data
//- The printf format for zero-padding names //- The printf format for zero-padding names
string printf_; string printf_;
@ -177,7 +177,7 @@ class dataCloud
bool writeField bool writeField
( (
const fileName& outputName, const fileName& outputName,
const objectRegistry& obrTmp const objectRegistry& obr
) const; ) const;

View File

@ -171,10 +171,10 @@ template<class Type>
bool Foam::functionObjects::dataCloud::writeField bool Foam::functionObjects::dataCloud::writeField
( (
const fileName& outputName, const fileName& outputName,
const objectRegistry& obrTmp const objectRegistry& obr
) const ) const
{ {
const auto* pointsPtr = cloud::findIOPosition(obrTmp); const auto* pointsPtr = cloud::findIOPosition(obr);
if (!pointsPtr) if (!pointsPtr)
{ {
@ -185,8 +185,8 @@ bool Foam::functionObjects::dataCloud::writeField
// Fields are not always on all processors (eg, multi-component parcels). // Fields are not always on all processors (eg, multi-component parcels).
// Thus need to resolve between all processors. // Thus need to resolve between all processors.
const List<Type>* fldPtr = obrTmp.findObject<IOField<Type>>(fieldName_); const List<Type>* fldPtr = obr.findObject<IOField<Type>>(fieldName_);
const List<Type>& values = (fldPtr ? *fldPtr : List<Type>()); const List<Type>& values = (fldPtr ? *fldPtr : List<Type>::null());
if (!returnReduceOr(fldPtr != nullptr)) if (!returnReduceOr(fldPtr != nullptr))
{ {

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2018-2022 OpenCFD Ltd. Copyright (C) 2018-2024 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -101,12 +101,16 @@ bool Foam::functionObjects::vtkCloud::writeCloud
const word& cloudName const word& cloudName
) )
{ {
const auto* objPtr = mesh_.findObject<cloud>(cloudName); applyFilter_ = false;
if (!objPtr)
const auto* cloudPtr = mesh_.cfindObject<cloud>(cloudName);
if (!cloudPtr)
{ {
return false; return false;
} }
const auto& currCloud = *cloudPtr;
objectRegistry obrTmp objectRegistry obrTmp
( (
IOobject IOobject
@ -120,7 +124,7 @@ bool Foam::functionObjects::vtkCloud::writeCloud
) )
); );
objPtr->writeObjects(obrTmp); currCloud.writeObjects(obrTmp);
const auto* pointsPtr = cloud::findIOPosition(obrTmp); const auto* pointsPtr = cloud::findIOPosition(obrTmp);
@ -135,7 +139,10 @@ bool Foam::functionObjects::vtkCloud::writeCloud
// Number of parcels (locally) // 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 // Total number of parcels on all processes
const label nTotParcels = returnReduce(nParcels, sumOp<label>()); const label nTotParcels = returnReduce(nParcels, sumOp<label>());
@ -163,9 +170,9 @@ bool Foam::functionObjects::vtkCloud::writeCloud
<< exit(FatalError); << exit(FatalError);
} }
if (Pstream::master()) if (UPstream::master())
{ {
mkDir(file.path()); Foam::mkDir(file.path());
os.open(file); os.open(file);
format = writeOpts_.newFormatter(os); format = writeOpts_.newFormatter(os);
@ -238,7 +245,7 @@ bool Foam::functionObjects::vtkCloud::writeCloud
} }
if (Pstream::master()) if (UPstream::master())
{ {
format().flush(); format().flush();
format().endDataArray(); format().endDataArray();
@ -270,7 +277,7 @@ bool Foam::functionObjects::vtkCloud::writeCloud
// Write fields // Write fields
if (Pstream::master()) if (UPstream::master())
{ {
if (useVerts_) 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.push_back
written.append(writeFields<scalar>(format, obrTmp, nTotParcels)); (
written.append(writeFields<vector>(format, obrTmp, nTotParcels)); writeFields<label>(format, obrTmp, nTotParcels)
);
written.push_back
(
writeFields<scalar>(format, obrTmp, nTotParcels)
);
written.push_back
(
writeFields<vector>(format, obrTmp, nTotParcels)
);
if (Pstream::master()) // Any cloudFunctions results
written.push_back
(
writeFields<scalar>(format, currCloud, nTotParcels)
);
if (UPstream::master())
{ {
if (useVerts_) if (useVerts_)
{ {
@ -415,12 +437,15 @@ bool Foam::functionObjects::vtkCloud::read(const dictionary& dict)
selectClouds_.clear(); selectClouds_.clear();
dict.readIfPresent("clouds", selectClouds_); dict.readIfPresent("clouds", selectClouds_);
selectClouds_.uniq();
if (selectClouds_.empty()) if (selectClouds_.empty())
{ {
selectClouds_.resize(1); word cloudName;
selectClouds_.first() = if (dict.readIfPresent("cloud", cloudName))
dict.getOrDefault<word>("cloud", cloud::defaultName); {
selectClouds_.push_back(std::move(cloudName));
}
} }
selectFields_.clear(); selectFields_.clear();
@ -463,7 +488,12 @@ bool Foam::functionObjects::vtkCloud::execute()
bool Foam::functionObjects::vtkCloud::write() 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()) if (cloudNames.empty())
{ {
@ -498,7 +528,7 @@ bool Foam::functionObjects::vtkCloud::write()
Log << " cloud : " Log << " cloud : "
<< time_.relativePath(outputName) << endl; << time_.relativePath(outputName) << endl;
if (Pstream::master()) if (UPstream::master())
{ {
// Add to file-series and emit as JSON // Add to file-series and emit as JSON
fileName seriesName(vtk::seriesWriter::base(outputName)); fileName seriesName(vtk::seriesWriter::base(outputName));

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2018-2020 OpenCFD Ltd. Copyright (C) 2018-2024 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -81,7 +81,7 @@ Description
Property | Description | Required | Default Property | Description | Required | Default
type | Type name: vtkCloud | yes | type | Type name: vtkCloud | yes |
clouds | List of clouds (name or regex) | no | 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 | fields | List of fields (name or regex) | no |
selection | Parcel selection control | no | empty-dict selection | Parcel selection control | no | empty-dict
\endtable \endtable
@ -160,7 +160,7 @@ class vtkCloud
public fvMeshFunctionObject, public fvMeshFunctionObject,
public Foam::Detail::parcelSelection public Foam::Detail::parcelSelection
{ {
// Private data // Private Data
//- Writer options //- Writer options
vtk::outputOptions writeOpts_; vtk::outputOptions writeOpts_;
@ -209,7 +209,7 @@ class vtkCloud
wordList writeFields wordList writeFields
( (
autoPtr<vtk::formatter>& format, autoPtr<vtk::formatter>& format,
const objectRegistry& obrTmp, const objectRegistry& obr,
const label nTotParcels const label nTotParcels
) const; ) const;

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2018-2022 OpenCFD Ltd. Copyright (C) 2018-2024 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -33,7 +33,7 @@ template<class Type>
Foam::wordList Foam::functionObjects::vtkCloud::writeFields Foam::wordList Foam::functionObjects::vtkCloud::writeFields
( (
autoPtr<vtk::formatter>& format, autoPtr<vtk::formatter>& format,
const objectRegistry& obrTmp, const objectRegistry& obr,
const label nTotParcels const label nTotParcels
) const ) const
{ {
@ -55,16 +55,22 @@ Foam::wordList Foam::functionObjects::vtkCloud::writeFields
// Fields are not always on all processors (eg, multi-component parcels). // Fields are not always on all processors (eg, multi-component parcels).
// Thus need to resolve names between all processors. // 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>()); Pstream::combineReduce(fieldNames, ListOps::uniqueEqOp<word>());
Foam::sort(fieldNames); // Consistent order Foam::sort(fieldNames); // Consistent order
for (const word& fieldName : fieldNames) for (const word& fieldName : fieldNames)
{ {
const List<Type>* fldPtr = obrTmp.findObject<IOField<Type>>(fieldName); const List<Type>* fldPtr = obr.findObject<IOField<Type>>(fieldName);
const List<Type>& values = (fldPtr ? *fldPtr : List<Type>()); 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) 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); vtk::writeListParallel(format.ref(), values);
} }
if (Pstream::master()) if (UPstream::master())
{ {
// Non-legacy // Non-legacy
format().flush(); format().flush();