mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: additional ensightCloud function object (#3095)
This commit is contained in:
@ -5,5 +5,6 @@ icoUncoupledKinematicCloud/icoUncoupledKinematicCloud.C
|
||||
dsmcFields/dsmcFields.C
|
||||
|
||||
vtkCloud/vtkCloud.C
|
||||
ensightCloud/ensightCloudWriteObject.cxx
|
||||
|
||||
LIB = $(FOAM_LIBBIN)/liblagrangianFunctionObjects
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
Reference in New Issue
Block a user