ENH: extend ensightCloud write-measured support

- related to issue #3095
This commit is contained in:
Mark Olesen
2024-01-23 20:24:23 +01:00
parent cb416fb3ec
commit fe1d7e01d6
3 changed files with 175 additions and 74 deletions

View File

@ -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,7 +59,7 @@ static inline label writeMeasured_ascii
const UList<floatVector>& points
)
{
for (const floatVector& p : points)
for (const auto& p : points)
{
os.writeInt(++pointId, 8); // 1-index and an unusual width
os.write(p.x());
@ -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);
}
// ************************************************************************* //

View File

@ -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
);

View File

@ -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;