mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
Merge branch 'feature-ensightCloudFO' into 'develop'
ensight cloud functionObject See merge request Development/openfoam!666
This commit is contained in:
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2015 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -221,7 +221,7 @@ Foam::Ostream& Foam::ensightFile::write
|
||||
}
|
||||
|
||||
|
||||
Foam::Ostream& Foam::ensightFile::write(const int32_t val)
|
||||
void Foam::ensightFile::writeInt(const int32_t val, const int fieldWidth)
|
||||
{
|
||||
if (format() == IOstreamOption::BINARY)
|
||||
{
|
||||
@ -233,24 +233,22 @@ Foam::Ostream& Foam::ensightFile::write(const int32_t val)
|
||||
}
|
||||
else
|
||||
{
|
||||
stdStream().width(10);
|
||||
stdStream().width(fieldWidth);
|
||||
stdStream() << val;
|
||||
syncState();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Foam::Ostream& Foam::ensightFile::write(const int64_t val)
|
||||
void Foam::ensightFile::writeInt(const int64_t val, const int fieldWidth)
|
||||
{
|
||||
int32_t ivalue(narrowInt32(val));
|
||||
int32_t work(narrowInt32(val));
|
||||
|
||||
return write(ivalue);
|
||||
writeInt(work, fieldWidth);
|
||||
}
|
||||
|
||||
|
||||
Foam::Ostream& Foam::ensightFile::write(const float val)
|
||||
void Foam::ensightFile::writeFloat(const float val, const int fieldWidth)
|
||||
{
|
||||
if (format() == IOstreamOption::BINARY)
|
||||
{
|
||||
@ -262,40 +260,45 @@ Foam::Ostream& Foam::ensightFile::write(const float val)
|
||||
}
|
||||
else
|
||||
{
|
||||
stdStream().width(12);
|
||||
stdStream().width(fieldWidth);
|
||||
stdStream() << val;
|
||||
syncState();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::ensightFile::writeFloat(const double val, const int fieldWidth)
|
||||
{
|
||||
float work(narrowFloat(val));
|
||||
|
||||
writeFloat(work, fieldWidth);
|
||||
}
|
||||
|
||||
|
||||
Foam::Ostream& Foam::ensightFile::write(const int32_t val)
|
||||
{
|
||||
writeInt(val, 10);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Foam::Ostream& Foam::ensightFile::write(const int64_t val)
|
||||
{
|
||||
writeInt(val, 10);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Foam::Ostream& Foam::ensightFile::write(const float val)
|
||||
{
|
||||
writeFloat(val, 12);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Foam::Ostream& Foam::ensightFile::write(const double val)
|
||||
{
|
||||
float fvalue(narrowFloat(val));
|
||||
|
||||
return write(fvalue);
|
||||
}
|
||||
|
||||
|
||||
Foam::Ostream& Foam::ensightFile::write
|
||||
(
|
||||
const label value,
|
||||
const label fieldWidth
|
||||
)
|
||||
{
|
||||
if (format() == IOstreamOption::BINARY)
|
||||
{
|
||||
write(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
stdStream().width(fieldWidth);
|
||||
stdStream() << value;
|
||||
syncState();
|
||||
}
|
||||
|
||||
writeFloat(val, 12);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -376,7 +379,7 @@ void Foam::ensightFile::beginParticleCoordinates(const label nparticles)
|
||||
{
|
||||
writeString("particle coordinates");
|
||||
newline();
|
||||
write(nparticles, 8); // unusual width
|
||||
writeInt(nparticles, 8); // Warning: unusual width
|
||||
newline();
|
||||
}
|
||||
|
||||
|
||||
@ -163,6 +163,18 @@ public:
|
||||
//- Write string as "%79s" or as binary (max 80 chars)
|
||||
void writeString(const std::string& str);
|
||||
|
||||
//- Write integer value with specified width or as binary
|
||||
void writeInt(const int32_t val, const int fieldWidth);
|
||||
|
||||
//- Write (narrowed) integer value with specified width or as binary
|
||||
void writeInt(const int64_t val, const int fieldWidth);
|
||||
|
||||
//- Write floating-point with specified width or as binary
|
||||
void writeFloat(const float val, const int fieldWidth);
|
||||
|
||||
//- Write (narrowed) floating-point with specified width or as binary
|
||||
void writeFloat(const double val, const int fieldWidth);
|
||||
|
||||
//- Write undef value
|
||||
void writeUndef();
|
||||
|
||||
@ -197,15 +209,12 @@ public:
|
||||
//- Write string, uses writeString()
|
||||
virtual Ostream& write(const std::string& str) override;
|
||||
|
||||
//- Write integer as "%10d" or as binary
|
||||
//- Write integer value as "%10d" or as binary
|
||||
virtual Ostream& write(const int32_t val) override;
|
||||
|
||||
//- Write integer as "%10d" or as binary
|
||||
//- Write integer value as "%10d" or as binary (narrowed to int32_t)
|
||||
virtual Ostream& write(const int64_t val) override;
|
||||
|
||||
//- Write integer with specified width or as binary
|
||||
Ostream& write(const label value, const label fieldWidth);
|
||||
|
||||
//- Write floating-point as "%12.5e" or as binary
|
||||
virtual Ostream& write(const float val) override;
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -449,6 +449,19 @@ void Foam::ensightMesh::write
|
||||
{
|
||||
faceZoneParts_[id].write(os, mesh_, parallel);
|
||||
}
|
||||
|
||||
// No geometry parts written?
|
||||
// - with lagrangian-only output the VTK EnsightReader still
|
||||
// needs a volume geometry, and ensight usually does too
|
||||
if
|
||||
(
|
||||
cellZoneParts_.empty()
|
||||
&& boundaryParts_.empty()
|
||||
&& faceZoneParts_.empty()
|
||||
)
|
||||
{
|
||||
ensightCells::writeBox(os, mesh_.bounds());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -216,18 +216,22 @@ public:
|
||||
|
||||
// Output
|
||||
|
||||
//- Write geometry to file. Normally in parallel
|
||||
//- Write geometry to file (normally in parallel).
|
||||
// If all geometry is disabled, it will simply writes the mesh
|
||||
// bounding box (to ensure that the geometry file is non-empty)
|
||||
void write
|
||||
(
|
||||
ensightGeoFile& os,
|
||||
bool parallel = Pstream::parRun()
|
||||
bool parallel = UPstream::parRun()
|
||||
) const;
|
||||
|
||||
//- Write geometry to file. Normally in parallel
|
||||
//- Write geometry to file (normally in parallel).
|
||||
// If all geometry is disabled, it will simply writes the mesh
|
||||
// bounding box (to ensure that the geometry file is non-empty)
|
||||
inline void write
|
||||
(
|
||||
autoPtr<ensightGeoFile>& os,
|
||||
bool parallel = Pstream::parRun()
|
||||
bool parallel = UPstream::parRun()
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -46,6 +46,7 @@ namespace Foam
|
||||
|
||||
// Forward Declarations
|
||||
class bitSet;
|
||||
class boundBox;
|
||||
class polyMesh;
|
||||
template<class T> class InfoProxy;
|
||||
|
||||
@ -279,6 +280,16 @@ public:
|
||||
const polyMesh& mesh,
|
||||
bool parallel
|
||||
) const;
|
||||
|
||||
//- Write bounding box geometry.
|
||||
//- All parameters are only relevant on master
|
||||
static void writeBox
|
||||
(
|
||||
ensightGeoFile& os,
|
||||
const boundBox& bb,
|
||||
const label partIndex = 0,
|
||||
const word& partName = "geometry-box"
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2020 OpenCFD Ltd.
|
||||
Copyright (C) 2020-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -28,7 +28,9 @@ License
|
||||
#include "ensightCells.H"
|
||||
#include "ensightOutput.H"
|
||||
#include "InfoProxy.H"
|
||||
#include "boundBox.H"
|
||||
#include "polyMesh.H"
|
||||
#include "cellModel.H"
|
||||
#include "globalIndex.H"
|
||||
#include "globalMeshData.H"
|
||||
#include "manifoldCellsMeshObject.H"
|
||||
@ -330,6 +332,44 @@ void Foam::ensightCells::write
|
||||
}
|
||||
|
||||
|
||||
void Foam::ensightCells::writeBox
|
||||
(
|
||||
ensightGeoFile& os,
|
||||
const boundBox& bb,
|
||||
const label partIndex,
|
||||
const word& partName
|
||||
)
|
||||
{
|
||||
pointField points;
|
||||
cellShapeList shapes;
|
||||
|
||||
if (UPstream::master())
|
||||
{
|
||||
points = bb.hexCorners();
|
||||
shapes.emplace_back(cellModel::HEX, identity(8));
|
||||
}
|
||||
|
||||
ensightOutput::Detail::writeCoordinates
|
||||
(
|
||||
os,
|
||||
partIndex,
|
||||
partName,
|
||||
8, // nPoints (global)
|
||||
points,
|
||||
false // serial only! (parallel=false)
|
||||
);
|
||||
|
||||
if (UPstream::master())
|
||||
{
|
||||
os.writeKeyword(ensightCells::key(ensightCells::elemType::HEXA8));
|
||||
os.write(shapes.size()); // one cell (global)
|
||||
os.newline();
|
||||
|
||||
ensightOutput::writeCellShapes(os, shapes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * //
|
||||
|
||||
template<>
|
||||
|
||||
@ -148,14 +148,14 @@ public:
|
||||
void write
|
||||
(
|
||||
ensightGeoFile& os,
|
||||
bool parallel = Pstream::parRun()
|
||||
bool parallel = UPstream::parRun()
|
||||
) const;
|
||||
|
||||
//- Write geometry to file. Normally in parallel
|
||||
inline void write
|
||||
(
|
||||
autoPtr<ensightGeoFile>& os,
|
||||
bool parallel = Pstream::parRun()
|
||||
bool parallel = UPstream::parRun()
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
@ -5,5 +5,6 @@ icoUncoupledKinematicCloud/icoUncoupledKinematicCloud.C
|
||||
dsmcFields/dsmcFields.C
|
||||
|
||||
vtkCloud/vtkCloud.C
|
||||
ensightCloud/ensightCloudWriteObject.cxx
|
||||
|
||||
LIB = $(FOAM_LIBBIN)/liblagrangianFunctionObjects
|
||||
|
||||
@ -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())
|
||||
{
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
|
||||
@ -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))
|
||||
{
|
||||
|
||||
@ -0,0 +1,266 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 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::ensightCloudWriteObject
|
||||
|
||||
Group
|
||||
grpLagrangianFunctionObjects
|
||||
|
||||
Description
|
||||
This functionObject writes cloud(s) in ensight format
|
||||
|
||||
Example of function object specification:
|
||||
\verbatim
|
||||
cloudWrite1
|
||||
{
|
||||
type ensightCloud;
|
||||
libs (lagrangianFunctionObjects);
|
||||
writeControl writeTime;
|
||||
writeInterval 1;
|
||||
format ascii;
|
||||
|
||||
timeFormat scientific;
|
||||
timePrecision 5;
|
||||
|
||||
cloud myCloud;
|
||||
fields (T U rho);
|
||||
width 4; // file-padding
|
||||
|
||||
selection
|
||||
{
|
||||
stride
|
||||
{
|
||||
// every 10th parcelId
|
||||
action add;
|
||||
source stride;
|
||||
stride 10;
|
||||
}
|
||||
Umin
|
||||
{
|
||||
// Remove slow parcels
|
||||
action subtract;
|
||||
source field;
|
||||
field U;
|
||||
accept (less 1e-3);
|
||||
}
|
||||
diam
|
||||
{
|
||||
// Only particular diameter ranges
|
||||
action subset;
|
||||
source field;
|
||||
field d;
|
||||
accept (greater 1e-3) and (less 1e-3);
|
||||
}
|
||||
}
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
\heading Basic Usage
|
||||
\table
|
||||
Property | Description | Required | Default
|
||||
type | Type name: ensightCloud | yes |
|
||||
clouds | List of clouds (name or regex) | no |
|
||||
cloud | Cloud name | no |
|
||||
fields | List of fields (name or regex) | no |
|
||||
selection | Parcel selection control | no | empty-dict
|
||||
\endtable
|
||||
|
||||
\heading Output Options
|
||||
\table
|
||||
Property | Description | Required | Default
|
||||
format | Format as ascii or binary | no | binary
|
||||
width | Mask width for \c data/XXXX | no | 8
|
||||
directory | The output directory name | no | postProcessing/NAME
|
||||
overwrite | Remove existing directory | no | false
|
||||
consecutive | Consecutive output numbering | no | false
|
||||
width | Padding width for file name | no | 8
|
||||
prune | Suppress writing of empty clouds | no | false
|
||||
timeFormat | Time format (ensight case) | no | scientific
|
||||
timePrecision | Time precision (ensight case) | no | 5
|
||||
writeControl | Output control | recommended | timeStep
|
||||
\endtable
|
||||
|
||||
The output filename and fields are added to the functionObjectProperties
|
||||
information. For the previous example specification:
|
||||
|
||||
\verbatim
|
||||
cloudWrite1
|
||||
{
|
||||
myCloud
|
||||
{
|
||||
file "<case>/simulation.case";
|
||||
fields (T U rho);
|
||||
}
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
Note
|
||||
The selection dictionary can be used for finer control of the parcel
|
||||
output. It contains a set of (add,subtract,subset,clear,invert)
|
||||
selection actions and sources.
|
||||
Omitting the selection dictionary is the same as specifying the
|
||||
conversion of all parcels (in the selected clouds).
|
||||
More syntax details are to be found in the corresponding
|
||||
Foam::Detail::parcelSelection class.
|
||||
|
||||
See also
|
||||
Foam::Detail::parcelSelection
|
||||
Foam::functionObjects::vtkCloud
|
||||
Foam::functionObjects::ensightWrite
|
||||
Foam::functionObjects::fvMeshFunctionObject
|
||||
Foam::functionObjects::timeControl
|
||||
|
||||
SourceFiles
|
||||
ensightCloudWriteObject.cxx
|
||||
ensightCloudWriteObjectImpl.cxx
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef functionObjects_ensightCloudWriteObject_H
|
||||
#define functionObjects_ensightCloudWriteObject_H
|
||||
|
||||
#include "fvMeshFunctionObject.H"
|
||||
#include "ensightCase.H"
|
||||
#include "globalIndex.H"
|
||||
#include "parcelSelectionDetail.H"
|
||||
#include "wordRes.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace functionObjects
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class ensightCloudWriteObject Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class ensightCloudWriteObject
|
||||
:
|
||||
public fvMeshFunctionObject,
|
||||
public Foam::Detail::parcelSelection
|
||||
{
|
||||
// Private Data
|
||||
|
||||
//- Ensight output options
|
||||
ensightCase::options caseOpts_;
|
||||
|
||||
//- Output directory
|
||||
fileName outputDir_;
|
||||
|
||||
//- Consecutive output numbering
|
||||
bool consecutive_;
|
||||
|
||||
//- Suppress writing of empty clouds
|
||||
bool pruneEmpty_;
|
||||
|
||||
//- Apply output filter (for the current cloud)
|
||||
bool applyFilter_;
|
||||
|
||||
//- Sizing of selected parcels (including any filtering)
|
||||
globalIndex procAddr_;
|
||||
|
||||
//- Requested names of clouds to process
|
||||
wordRes selectClouds_;
|
||||
|
||||
//- Subset of cloud fields to process
|
||||
wordRes selectFields_;
|
||||
|
||||
//- Ensight case handler
|
||||
autoPtr<ensightCase> ensCase_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Ensight case handler
|
||||
ensightCase& ensCase() { return *ensCase_; }
|
||||
|
||||
//- Write a cloud to disk (creates parent directory),
|
||||
//- and record on the cloud OutputProperties.
|
||||
// \param file is the output file name, with extension.
|
||||
bool writeCloud(const word& cloudName);
|
||||
|
||||
//- Write fields of IOField<Type>
|
||||
template<class Type>
|
||||
wordList writeFields
|
||||
(
|
||||
const word& cloudName,
|
||||
const objectRegistry& obrTmp
|
||||
);
|
||||
|
||||
|
||||
//- No copy construct
|
||||
ensightCloudWriteObject(const ensightCloudWriteObject&) = delete;
|
||||
|
||||
//- No copy assignment
|
||||
void operator=(const ensightCloudWriteObject&) = delete;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("ensightCloud");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from Time and dictionary
|
||||
ensightCloudWriteObject
|
||||
(
|
||||
const word& name,
|
||||
const Time& runTime,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~ensightCloudWriteObject() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Read the ensightCloud specification
|
||||
virtual bool read(const dictionary& dict);
|
||||
|
||||
//- Execute, currently does nothing
|
||||
virtual bool execute();
|
||||
|
||||
//- Write fields
|
||||
virtual bool write();
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace functionObjects
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,425 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 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 "ensightCloudWriteObject.H"
|
||||
#include "ensightCells.H"
|
||||
#include "Cloud.H"
|
||||
#include "dictionary.H"
|
||||
#include "fvMesh.H"
|
||||
#include "ensightOutputCloud.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "pointList.H"
|
||||
#include "stringOps.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace functionObjects
|
||||
{
|
||||
defineTypeNameAndDebug(ensightCloudWriteObject, 0);
|
||||
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
functionObject,
|
||||
ensightCloudWriteObject,
|
||||
dictionary
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Implementation
|
||||
#include "ensightCloudWriteObjectImpl.cxx"
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
bool Foam::functionObjects::ensightCloudWriteObject::writeCloud
|
||||
(
|
||||
const word& cloudName
|
||||
)
|
||||
{
|
||||
applyFilter_ = false;
|
||||
procAddr_.clear();
|
||||
|
||||
const auto* cloudPtr = mesh_.cfindObject<cloud>(cloudName);
|
||||
if (!cloudPtr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& currCloud = *cloudPtr;
|
||||
|
||||
objectRegistry obrTmp
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"ensight::ensightCloud::" + cloudName,
|
||||
mesh_.time().constant(),
|
||||
mesh_,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
IOobject::NO_REGISTER
|
||||
)
|
||||
);
|
||||
|
||||
currCloud.writeObjects(obrTmp);
|
||||
|
||||
const auto* pointsPtr = cloud::findIOPosition(obrTmp);
|
||||
|
||||
if (!pointsPtr)
|
||||
{
|
||||
// This should be impossible
|
||||
return false;
|
||||
}
|
||||
|
||||
applyFilter_ = calculateFilter(obrTmp, log);
|
||||
Pstream::reduceOr(applyFilter_);
|
||||
|
||||
// Number of parcels (locally)
|
||||
const label nParcels =
|
||||
(
|
||||
applyFilter_ ? parcelAddr_.count() : pointsPtr->size()
|
||||
);
|
||||
|
||||
// Gather sizes (offsets irrelevant)
|
||||
procAddr_.reset(globalIndex::gatherOnly{}, nParcels);
|
||||
|
||||
bool noCloud(!procAddr_.totalSize());
|
||||
Pstream::broadcast(noCloud);
|
||||
|
||||
if (applyFilter_)
|
||||
{
|
||||
// Report filtered/unfiltered count
|
||||
Log << "After filtering using "
|
||||
<< procAddr_.totalSize() << '/'
|
||||
<< (returnReduce(pointsPtr->size(), sumOp<label>()))
|
||||
<< " parcels" << nl;
|
||||
}
|
||||
|
||||
if (pruneEmpty_ && noCloud)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Copy positions (for simplicity and for filtering).
|
||||
// Store as floatVector, since that is what Ensight will write anyhow
|
||||
|
||||
DynamicList<floatVector> positions;
|
||||
positions.reserve(UPstream::master() ? procAddr_.maxSize() : nParcels);
|
||||
|
||||
{
|
||||
const auto& points = *pointsPtr;
|
||||
|
||||
positions.resize_nocopy(nParcels);
|
||||
|
||||
auto iter = positions.begin();
|
||||
|
||||
if (applyFilter_)
|
||||
{
|
||||
if (std::is_same<float, vector::cmptType>::value)
|
||||
{
|
||||
for (const label idx : parcelAddr_)
|
||||
{
|
||||
*iter = points[idx];
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const label idx : parcelAddr_)
|
||||
{
|
||||
const auto& pos = points[idx];
|
||||
|
||||
(*iter).x() = narrowFloat(pos.x());
|
||||
(*iter).y() = narrowFloat(pos.y());
|
||||
(*iter).z() = narrowFloat(pos.z());
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (std::is_same<float, vector::cmptType>::value)
|
||||
{
|
||||
for (const auto& pos : points)
|
||||
{
|
||||
*iter = pos;
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const auto& pos : points)
|
||||
{
|
||||
(*iter).x() = narrowFloat(pos.x());
|
||||
(*iter).y() = narrowFloat(pos.y());
|
||||
(*iter).z() = narrowFloat(pos.z());
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Write positions
|
||||
{
|
||||
autoPtr<ensightFile> os = ensCase().newCloud(cloudName);
|
||||
|
||||
ensightOutput::writeCloudPositions
|
||||
(
|
||||
os.ref(),
|
||||
positions,
|
||||
procAddr_
|
||||
);
|
||||
}
|
||||
|
||||
// Prevent any possible conversion of positions as a field
|
||||
obrTmp.filterKeys
|
||||
(
|
||||
[](const word& k)
|
||||
{
|
||||
return k.starts_with("position") || k.starts_with("coordinate");
|
||||
},
|
||||
true // prune
|
||||
);
|
||||
|
||||
|
||||
// Write fields
|
||||
|
||||
DynamicList<word> written(obrTmp.size() + currCloud.objectRegistry::size());
|
||||
|
||||
written.push_back
|
||||
(
|
||||
writeFields<label>(cloudName, obrTmp)
|
||||
);
|
||||
written.push_back
|
||||
(
|
||||
writeFields<scalar>(cloudName, obrTmp)
|
||||
);
|
||||
written.push_back
|
||||
(
|
||||
writeFields<vector>(cloudName, obrTmp)
|
||||
);
|
||||
|
||||
// Any cloudFunctions results
|
||||
written.push_back
|
||||
(
|
||||
writeFields<scalar>(cloudName, currCloud)
|
||||
);
|
||||
|
||||
// Record information into the state (all processors)
|
||||
//
|
||||
// foName
|
||||
// {
|
||||
// cloudName
|
||||
// {
|
||||
// file "<case>/postProcessing/name/casename.case";
|
||||
// fields (U T rho);
|
||||
// }
|
||||
// }
|
||||
|
||||
const fileName& file = ensCase().path();
|
||||
|
||||
// Case-local file name with "<case>" to make relocatable
|
||||
dictionary propsDict;
|
||||
propsDict.add
|
||||
(
|
||||
"file",
|
||||
time_.relativePath(file, true)
|
||||
);
|
||||
propsDict.add("fields", written);
|
||||
|
||||
setObjectProperty(name(), cloudName, propsDict);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::functionObjects::ensightCloudWriteObject::ensightCloudWriteObject
|
||||
(
|
||||
const word& name,
|
||||
const Time& runTime,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
fvMeshFunctionObject(name, runTime, dict),
|
||||
caseOpts_("format", dict, IOstreamOption::BINARY),
|
||||
outputDir_(),
|
||||
consecutive_(false),
|
||||
pruneEmpty_(false),
|
||||
applyFilter_(false),
|
||||
procAddr_()
|
||||
{
|
||||
// May still want this?
|
||||
// if (postProcess)
|
||||
// {
|
||||
// // Disable for post-process mode.
|
||||
// // Emit as FatalError for the try/catch in the caller.
|
||||
// FatalError
|
||||
// << type() << " disabled in post-process mode"
|
||||
// << exit(FatalError);
|
||||
// }
|
||||
|
||||
read(dict);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::functionObjects::ensightCloudWriteObject::read
|
||||
(
|
||||
const dictionary& dict
|
||||
)
|
||||
{
|
||||
fvMeshFunctionObject::read(dict);
|
||||
|
||||
// Case/writer options
|
||||
consecutive_ = dict.getOrDefault("consecutive", false);
|
||||
|
||||
caseOpts_.width(dict.getOrDefault<label>("width", 8));
|
||||
caseOpts_.overwrite(dict.getOrDefault("overwrite", false));
|
||||
|
||||
caseOpts_.timeFormat("timeFormat", dict);
|
||||
caseOpts_.timePrecision("timePrecision", dict);
|
||||
|
||||
|
||||
pruneEmpty_ = dict.getOrDefault("prune", false);
|
||||
|
||||
selectClouds_.clear();
|
||||
dict.readIfPresent("clouds", selectClouds_);
|
||||
selectClouds_.uniq();
|
||||
if (selectClouds_.empty())
|
||||
{
|
||||
word cloudName;
|
||||
if (dict.readIfPresent("cloud", cloudName))
|
||||
{
|
||||
selectClouds_.push_back(std::move(cloudName));
|
||||
}
|
||||
}
|
||||
|
||||
selectFields_.clear();
|
||||
dict.readIfPresent("fields", selectFields_);
|
||||
selectFields_.uniq();
|
||||
|
||||
// Actions to define selection
|
||||
parcelSelect_ = dict.subOrEmptyDict("selection");
|
||||
|
||||
|
||||
// Output directory
|
||||
|
||||
outputDir_.clear();
|
||||
dict.readIfPresent("directory", outputDir_);
|
||||
|
||||
if (outputDir_.size())
|
||||
{
|
||||
// User-defined output directory
|
||||
outputDir_.expand();
|
||||
if (!outputDir_.isAbsolute())
|
||||
{
|
||||
outputDir_ = time_.globalPath()/outputDir_;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Standard postProcessing/ naming
|
||||
outputDir_ = time_.globalPath()/functionObject::outputPrefix/name();
|
||||
}
|
||||
outputDir_.clean(); // Remove unneeded ".."
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::functionObjects::ensightCloudWriteObject::execute()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::functionObjects::ensightCloudWriteObject::write()
|
||||
{
|
||||
const wordList cloudNames
|
||||
(
|
||||
selectClouds_.empty()
|
||||
? mesh_.sortedNames<cloud>()
|
||||
: mesh_.sortedNames<cloud>(selectClouds_)
|
||||
);
|
||||
|
||||
if (cloudNames.empty())
|
||||
{
|
||||
return true; // skip - nothing available
|
||||
}
|
||||
|
||||
if (!ensCase_)
|
||||
{
|
||||
ensCase_.reset
|
||||
(
|
||||
new ensightCase(outputDir_, time_.globalCaseName(), caseOpts_)
|
||||
);
|
||||
|
||||
// Generate a (non-moving) dummy geometry
|
||||
// - ParaView ensight-reader needs this, and usually ensight does too
|
||||
autoPtr<ensightGeoFile> os = ensCase().newGeometry(false);
|
||||
ensightCells::writeBox(os.ref(), mesh_.bounds());
|
||||
}
|
||||
|
||||
if (consecutive_)
|
||||
{
|
||||
ensCase().nextTime(time_.value());
|
||||
}
|
||||
else
|
||||
{
|
||||
ensCase().setTime(time_.value(), time_.timeIndex());
|
||||
}
|
||||
|
||||
Log << type() << ' ' << name() << " write" << nl;
|
||||
|
||||
// Each cloud separately
|
||||
for (const word& cloudName : cloudNames)
|
||||
{
|
||||
// writeCloud() includes mkDir (on master)
|
||||
|
||||
if (writeCloud(cloudName))
|
||||
{
|
||||
Log << " cloud : " << endl;
|
||||
}
|
||||
}
|
||||
|
||||
ensCase().write(); // Flush case information
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,106 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 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 "IOField.H"
|
||||
#include "ensightOutputCloud.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::wordList Foam::functionObjects::ensightCloudWriteObject::writeFields
|
||||
(
|
||||
const word& cloudName,
|
||||
const objectRegistry& obrTmp
|
||||
)
|
||||
{
|
||||
static_assert
|
||||
(
|
||||
(
|
||||
std::is_same<label, typename pTraits<Type>::cmptType>::value
|
||||
|| std::is_floating_point<typename pTraits<Type>::cmptType>::value
|
||||
),
|
||||
"Label and Floating-point vector space only"
|
||||
);
|
||||
|
||||
// Other integral types (eg, bool etc) would need cast/convert to label.
|
||||
// Similarly for labelVector etc.
|
||||
|
||||
|
||||
// Fields are not always on all processors (eg, multi-component parcels).
|
||||
// Thus need to resolve names between all processors.
|
||||
|
||||
wordList fieldNames =
|
||||
(
|
||||
selectFields_.size()
|
||||
? obrTmp.names<IOField<Type>>(selectFields_)
|
||||
: obrTmp.names<IOField<Type>>()
|
||||
);
|
||||
|
||||
Pstream::combineReduce(fieldNames, ListOps::uniqueEqOp<word>());
|
||||
Foam::sort(fieldNames); // Consistent order
|
||||
|
||||
DynamicList<Type> scratch;
|
||||
|
||||
for (const word& fieldName : fieldNames)
|
||||
{
|
||||
const List<Type>* fldPtr = obrTmp.findObject<IOField<Type>>(fieldName);
|
||||
const List<Type>& values = (fldPtr ? *fldPtr : List<Type>::null());
|
||||
|
||||
autoPtr<ensightFile> os =
|
||||
ensCase().newCloudData<Type>(cloudName, fieldName);
|
||||
|
||||
if (applyFilter_)
|
||||
{
|
||||
scratch.resize_nocopy(parcelAddr_.count());
|
||||
|
||||
auto iter = scratch.begin();
|
||||
|
||||
for (const label idx : parcelAddr_)
|
||||
{
|
||||
*iter = values[idx];
|
||||
++iter;
|
||||
}
|
||||
|
||||
// TBD:
|
||||
// recalculate globalIndex instead of relying on procAddr_ ?
|
||||
|
||||
ensightOutput::writeCloudField(os.ref(), scratch, procAddr_);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TBD:
|
||||
// recalculate globalIndex instead of relying on procAddr_ ?
|
||||
|
||||
ensightOutput::writeCloudField(os.ref(), values, procAddr_);
|
||||
}
|
||||
}
|
||||
|
||||
return fieldNames;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -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)
|
||||
);
|
||||
|
||||
if (Pstream::master())
|
||||
// Any cloudFunctions results
|
||||
written.push_back
|
||||
(
|
||||
writeFields<scalar>(format, currCloud, nTotParcels)
|
||||
);
|
||||
|
||||
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));
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -43,7 +43,7 @@ static inline void writeMeasured_binary
|
||||
const UList<floatVector>& points
|
||||
)
|
||||
{
|
||||
for (const floatVector& p : points)
|
||||
for (const auto& p : points)
|
||||
{
|
||||
os.write(p.x());
|
||||
os.write(p.y());
|
||||
@ -59,9 +59,9 @@ static inline label writeMeasured_ascii
|
||||
const UList<floatVector>& points
|
||||
)
|
||||
{
|
||||
for (const floatVector& p : points)
|
||||
for (const auto& p : points)
|
||||
{
|
||||
os.write(++pointId, 8); // 1-index and an unusual width
|
||||
os.writeInt(++pointId, 8); // 1-index and an unusual width
|
||||
os.write(p.x());
|
||||
os.write(p.y());
|
||||
os.write(p.z());
|
||||
@ -79,75 +79,24 @@ static inline label writeMeasured_ascii
|
||||
bool Foam::ensightOutput::writeCloudPositions
|
||||
(
|
||||
ensightFile& os,
|
||||
const fvMesh& mesh,
|
||||
const word& cloudName,
|
||||
bool exists
|
||||
DynamicList<floatVector>& positions,
|
||||
const globalIndex& procAddr
|
||||
)
|
||||
{
|
||||
label nLocalParcels(0);
|
||||
autoPtr<Cloud<passiveParticle>> parcelsPtr;
|
||||
// Total number of parcels across all ranks
|
||||
const label nTotParcels = procAddr.totalSize();
|
||||
|
||||
if (exists)
|
||||
{
|
||||
parcelsPtr.reset(new Cloud<passiveParticle>(mesh, cloudName, false));
|
||||
nLocalParcels = parcelsPtr().size();
|
||||
}
|
||||
|
||||
// Total number of parcels on all processes
|
||||
const label nTotParcels = returnReduce(nLocalParcels, sumOp<label>());
|
||||
bool noCloud(!procAddr.totalSize());
|
||||
Pstream::broadcast(noCloud);
|
||||
|
||||
if (UPstream::master())
|
||||
{
|
||||
os.beginParticleCoordinates(nTotParcels);
|
||||
}
|
||||
|
||||
if (!nTotParcels)
|
||||
if (noCloud)
|
||||
{
|
||||
return false; // DONE
|
||||
}
|
||||
|
||||
|
||||
// Gather sizes (offsets irrelevant)
|
||||
const globalIndex procAddr(globalIndex::gatherOnly{}, nLocalParcels);
|
||||
|
||||
|
||||
DynamicList<floatVector> positions;
|
||||
positions.reserve(UPstream::master() ? procAddr.maxSize() : nLocalParcels);
|
||||
|
||||
// Extract positions from parcel.
|
||||
// Store as floatVector, since that is what Ensight will write anyhow
|
||||
|
||||
if (parcelsPtr)
|
||||
{
|
||||
const auto& parcels = *parcelsPtr;
|
||||
|
||||
positions.resize_nocopy(parcels.size()); // same as nLocalParcels
|
||||
|
||||
auto outIter = positions.begin();
|
||||
|
||||
if (std::is_same<float, vector::cmptType>::value)
|
||||
{
|
||||
for (const passiveParticle& p : parcels)
|
||||
{
|
||||
*outIter = p.position();
|
||||
++outIter;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const passiveParticle& p : parcels)
|
||||
{
|
||||
vector pos(p.position());
|
||||
|
||||
(*outIter).x() = narrowFloat(pos.x());
|
||||
(*outIter).y() = narrowFloat(pos.y());
|
||||
(*outIter).z() = narrowFloat(pos.z());
|
||||
|
||||
++outIter;
|
||||
}
|
||||
}
|
||||
|
||||
parcelsPtr.reset(nullptr);
|
||||
return false; // All empty
|
||||
}
|
||||
|
||||
if (UPstream::master())
|
||||
@ -178,6 +127,9 @@ bool Foam::ensightOutput::writeCloudPositions
|
||||
}
|
||||
|
||||
|
||||
positions.clear();
|
||||
positions.reserve_nocopy(procAddr.maxNonLocalSize());
|
||||
|
||||
// Receive and write
|
||||
for (const label proci : procAddr.subProcs())
|
||||
{
|
||||
@ -186,6 +138,7 @@ bool Foam::ensightOutput::writeCloudPositions
|
||||
if (procSize)
|
||||
{
|
||||
positions.resize_nocopy(procSize);
|
||||
|
||||
UIPstream::read
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
@ -205,7 +158,7 @@ bool Foam::ensightOutput::writeCloudPositions
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (UPstream::is_subrank())
|
||||
{
|
||||
if (positions.size())
|
||||
{
|
||||
@ -223,4 +176,86 @@ bool Foam::ensightOutput::writeCloudPositions
|
||||
}
|
||||
|
||||
|
||||
bool Foam::ensightOutput::writeCloudPositions
|
||||
(
|
||||
ensightFile& os,
|
||||
DynamicList<floatVector>& positions
|
||||
)
|
||||
{
|
||||
return ensightOutput::writeCloudPositions
|
||||
(
|
||||
os,
|
||||
positions,
|
||||
// Gather sizes (offsets irrelevant)
|
||||
globalIndex(globalIndex::gatherOnly{}, positions.size())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
bool Foam::ensightOutput::writeCloudPositions
|
||||
(
|
||||
ensightFile& os,
|
||||
const fvMesh& mesh,
|
||||
const word& cloudName,
|
||||
bool exists
|
||||
)
|
||||
{
|
||||
autoPtr<Cloud<passiveParticle>> parcelsPtr;
|
||||
|
||||
if (exists)
|
||||
{
|
||||
parcelsPtr.reset(new Cloud<passiveParticle>(mesh, cloudName, false));
|
||||
}
|
||||
|
||||
const label nLocalParcels
|
||||
(
|
||||
parcelsPtr ? parcelsPtr->size() : 0
|
||||
);
|
||||
|
||||
// Gather sizes (offsets irrelevant)
|
||||
// and total number of parcels (all processes)
|
||||
const globalIndex procAddr(globalIndex::gatherOnly{}, nLocalParcels);
|
||||
|
||||
// Extract positions from parcel.
|
||||
// Store as floatVector, since that is what Ensight will write anyhow
|
||||
|
||||
DynamicList<floatVector> positions;
|
||||
positions.reserve(UPstream::master() ? procAddr.maxSize() : nLocalParcels);
|
||||
|
||||
if (parcelsPtr)
|
||||
{
|
||||
const auto& parcels = *parcelsPtr;
|
||||
|
||||
positions.resize_nocopy(parcels.size()); // same as nLocalParcels
|
||||
|
||||
auto iter = positions.begin();
|
||||
|
||||
if (std::is_same<float, vector::cmptType>::value)
|
||||
{
|
||||
for (const auto& p : parcels)
|
||||
{
|
||||
*iter = p.position();
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const auto& p : parcels)
|
||||
{
|
||||
const vector pos(p.position());
|
||||
|
||||
(*iter).x() = narrowFloat(pos.x());
|
||||
(*iter).y() = narrowFloat(pos.y());
|
||||
(*iter).z() = narrowFloat(pos.z());
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
parcelsPtr.reset(nullptr);
|
||||
}
|
||||
|
||||
return ensightOutput::writeCloudPositions(os, positions, procAddr);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -40,6 +40,8 @@ SourceFiles
|
||||
|
||||
#include "ensightFile.H"
|
||||
#include "IOField.H"
|
||||
#include "DynamicList.H"
|
||||
#include "vector.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -48,6 +50,7 @@ namespace Foam
|
||||
|
||||
// Forward Declarations
|
||||
class fvMesh;
|
||||
class globalIndex;
|
||||
|
||||
namespace ensightOutput
|
||||
{
|
||||
@ -55,6 +58,34 @@ namespace ensightOutput
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
//- Write cloud positions
|
||||
bool writeCloudPositions
|
||||
(
|
||||
//! Output file (must be valid on master)
|
||||
ensightFile& os,
|
||||
|
||||
//! The positions (measured data) to write.
|
||||
//! Also used as intermediate buffer (on master)
|
||||
DynamicList<floatVector>& positions,
|
||||
|
||||
//! The global sizes of \p positions (must be valid on master)
|
||||
//! and consistent with \p positions dimensions
|
||||
const globalIndex& procAddr
|
||||
);
|
||||
|
||||
|
||||
//- Write cloud positions
|
||||
bool writeCloudPositions
|
||||
(
|
||||
//! Output file (must be valid on master)
|
||||
ensightFile& os,
|
||||
|
||||
//! The positions (measured data) to write.
|
||||
//! Also used as intermediate buffer (on master)
|
||||
DynamicList<floatVector>& positions
|
||||
);
|
||||
|
||||
|
||||
//- Write cloud positions
|
||||
bool writeCloudPositions
|
||||
(
|
||||
@ -80,7 +111,23 @@ bool writeCloudField
|
||||
ensightFile& os,
|
||||
|
||||
//! The cloud field
|
||||
const IOField<Type>& field
|
||||
const UList<Type>& field,
|
||||
|
||||
//! The global sizes of \p field (must be valid on master)
|
||||
//! and consistent with \p field dimensions
|
||||
const globalIndex& procAddr
|
||||
);
|
||||
|
||||
|
||||
//- Write cloud field, returning true if the field is non-empty.
|
||||
template<class Type>
|
||||
bool writeCloudField
|
||||
(
|
||||
//! Output file (must be valid on master)
|
||||
ensightFile& os,
|
||||
|
||||
//! The cloud field
|
||||
const UList<Type>& field
|
||||
);
|
||||
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -39,7 +39,6 @@ Foam::label Foam::ensightOutput::Detail::writeCloudFieldContent
|
||||
label count
|
||||
)
|
||||
{
|
||||
// Write master data
|
||||
for (Type val : field) // <-- working on a copy!
|
||||
{
|
||||
if (mag(val) < 1e-90) // approximately root(ROOTVSMALL)
|
||||
@ -70,18 +69,20 @@ template<class Type>
|
||||
bool Foam::ensightOutput::writeCloudField
|
||||
(
|
||||
ensightFile& os,
|
||||
const IOField<Type>& field
|
||||
const UList<Type>& field,
|
||||
const globalIndex& procAddr
|
||||
)
|
||||
{
|
||||
if (returnReduceAnd(field.empty()))
|
||||
bool allEmpty(!procAddr.totalSize());
|
||||
Pstream::broadcast(allEmpty);
|
||||
|
||||
if (allEmpty)
|
||||
{
|
||||
return false;
|
||||
return false; // All empty
|
||||
}
|
||||
|
||||
// Gather sizes (offsets irrelevant)
|
||||
const globalIndex procAddr(globalIndex::gatherOnly{}, field.size());
|
||||
|
||||
if (Pstream::master())
|
||||
if (UPstream::master())
|
||||
{
|
||||
// 6 values per line
|
||||
label count = 0;
|
||||
@ -128,7 +129,7 @@ bool Foam::ensightOutput::writeCloudField
|
||||
os.newline();
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (UPstream::is_subrank())
|
||||
{
|
||||
if (field.size())
|
||||
{
|
||||
@ -146,6 +147,23 @@ bool Foam::ensightOutput::writeCloudField
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
bool Foam::ensightOutput::writeCloudField
|
||||
(
|
||||
ensightFile& os,
|
||||
const UList<Type>& field
|
||||
)
|
||||
{
|
||||
return ensightOutput::writeCloudField
|
||||
(
|
||||
os,
|
||||
field,
|
||||
// Gather sizes (offsets irrelevant)
|
||||
globalIndex(globalIndex::gatherOnly{}, field.size())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
bool Foam::ensightOutput::readWriteCloudField
|
||||
(
|
||||
@ -162,10 +180,11 @@ bool Foam::ensightOutput::readWriteCloudField
|
||||
|
||||
IOobject io(fieldObject);
|
||||
io.readOpt(IOobject::READ_IF_PRESENT);
|
||||
io.registerObject(IOobject::NO_REGISTER);
|
||||
|
||||
IOField<Type> field(io);
|
||||
|
||||
writeCloudField(os, field);
|
||||
ensightOutput::writeCloudField(os, field);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user