diff --git a/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.C b/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.C index 747bb0abebf7ccf0091c3f42726467e6f2c3aa4d..720ad68a457ed125b8e89bdeeef5738ea342e63e 100644 --- a/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.C +++ b/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.C @@ -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) - { - 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) + if (noCloud) { - 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); +} + + // ************************************************************************* // diff --git a/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.H b/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.H index e83fbecec0cbf7e582206856ddf079135b4ab1b6..323296eb261c59da3de3156a1605708f8c833732 100644 --- a/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.H +++ b/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloud.H @@ -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 ); diff --git a/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloudTemplates.C b/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloudTemplates.C index cc865cc7d3bd0a21b7916f782a25d42993d3f3d4..85b5d8a898a51c65a5973819648f1b896ef029a0 100644 --- a/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloudTemplates.C +++ b/src/lagrangian/intermediate/conversion/ensight/ensightOutputCloudTemplates.C @@ -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;