diff --git a/src/lagrangian/intermediate/parcels/include/makeParcelCloudFunctionObjects.H b/src/lagrangian/intermediate/parcels/include/makeParcelCloudFunctionObjects.H index e11442604b..f95d5d0ef0 100644 --- a/src/lagrangian/intermediate/parcels/include/makeParcelCloudFunctionObjects.H +++ b/src/lagrangian/intermediate/parcels/include/makeParcelCloudFunctionObjects.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2018 OpenFOAM Foundation - Copyright (C) 2020-2021 OpenCFD Ltd. + Copyright (C) 2020-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -37,6 +37,7 @@ License #include "ParticleErosion.H" #include "ParticleTracks.H" #include "ParticleTrap.H" +#include "ParticleZoneInfo.H" #include "PatchCollisionDensity.H" #include "PatchInteractionFields.H" #include "PatchPostProcessing.H" @@ -57,6 +58,7 @@ License makeCloudFunctionObjectType(ParticleErosion, CloudType); \ makeCloudFunctionObjectType(ParticleTracks, CloudType); \ makeCloudFunctionObjectType(ParticleTrap, CloudType); \ + makeCloudFunctionObjectType(ParticleZoneInfo, CloudType); \ makeCloudFunctionObjectType(PatchCollisionDensity, CloudType); \ makeCloudFunctionObjectType(PatchInteractionFields, CloudType); \ makeCloudFunctionObjectType(PatchPostProcessing, CloudType); \ diff --git a/src/lagrangian/intermediate/parcels/include/makeReactingParcelCloudFunctionObjects.H b/src/lagrangian/intermediate/parcels/include/makeReactingParcelCloudFunctionObjects.H index 61e0e413cd..16258ff40c 100644 --- a/src/lagrangian/intermediate/parcels/include/makeReactingParcelCloudFunctionObjects.H +++ b/src/lagrangian/intermediate/parcels/include/makeReactingParcelCloudFunctionObjects.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2018 OpenFOAM Foundation - Copyright (C) 2020-2021 OpenCFD Ltd. + Copyright (C) 2020-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -37,6 +37,7 @@ License #include "ParticleErosion.H" #include "ParticleTracks.H" #include "ParticleTrap.H" +#include "ParticleZoneInfo.H" #include "PatchCollisionDensity.H" #include "PatchInteractionFields.H" #include "PatchPostProcessing.H" @@ -60,6 +61,7 @@ License makeCloudFunctionObjectType(ParticleErosion, CloudType); \ makeCloudFunctionObjectType(ParticleTracks, CloudType); \ makeCloudFunctionObjectType(ParticleTrap, CloudType); \ + makeCloudFunctionObjectType(ParticleZoneInfo, CloudType); \ makeCloudFunctionObjectType(PatchCollisionDensity, CloudType); \ makeCloudFunctionObjectType(PatchInteractionFields, CloudType); \ makeCloudFunctionObjectType(PatchPostProcessing, CloudType); \ diff --git a/src/lagrangian/intermediate/parcels/include/makeThermoParcelCloudFunctionObjects.H b/src/lagrangian/intermediate/parcels/include/makeThermoParcelCloudFunctionObjects.H index 4b641e275b..a703eb8040 100644 --- a/src/lagrangian/intermediate/parcels/include/makeThermoParcelCloudFunctionObjects.H +++ b/src/lagrangian/intermediate/parcels/include/makeThermoParcelCloudFunctionObjects.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2021 OpenCFD Ltd. + Copyright (C) 2021-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -36,6 +36,7 @@ License #include "ParticleErosion.H" #include "ParticleTracks.H" #include "ParticleTrap.H" +#include "ParticleZoneInfo.H" #include "PatchCollisionDensity.H" #include "PatchInteractionFields.H" #include "PatchPostProcessing.H" @@ -58,6 +59,7 @@ License makeCloudFunctionObjectType(ParticleErosion, CloudType); \ makeCloudFunctionObjectType(ParticleTracks, CloudType); \ makeCloudFunctionObjectType(ParticleTrap, CloudType); \ + makeCloudFunctionObjectType(ParticleZoneInfo, CloudType); \ makeCloudFunctionObjectType(PatchCollisionDensity, CloudType); \ makeCloudFunctionObjectType(PatchInteractionFields, CloudType); \ makeCloudFunctionObjectType(PatchPostProcessing, CloudType); \ diff --git a/src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticleZoneInfo/ParticleZoneInfo.C b/src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticleZoneInfo/ParticleZoneInfo.C new file mode 100644 index 0000000000..86bacdfb8f --- /dev/null +++ b/src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticleZoneInfo/ParticleZoneInfo.C @@ -0,0 +1,458 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2022 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 . + +\*---------------------------------------------------------------------------*/ + +#include "ParticleZoneInfo.H" +#include "DynamicField.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +struct particleInfoCombineOp +{ + void operator()(particleInfo& p1, const particleInfo& p2) const + { + // p2 not set + if (p2.origID == -1) + { + return; + } + + // p1 not set - initialise with p2 + if (p1.origID == -1) + { + p1 = p2; + return; + } + + // Set initial values + if (p2.time0 < p1.time0) + { + p1.time0 = p2.time0; + p1.d0 = p2.d0; + p1.mass0 = p2.mass0; + } + + // Accumulate age + p1.age += p2.age; + + // Set latest available values + if (p2.isOlderThan(p1)) + { + p1.position = p2.position; + p1.d = p2.d; + p1.mass = p2.mass; + } + } +}; +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +template +Foam::Field getData +( + const Foam::UList& data, + Type Foam::particleInfo::* field +) +{ + Field result(data.size()); + + forAll(data, i) + { + result[i] = data[i].*field; + } + + return result; +} + + +template +Foam::Field getParData +( + const Foam::List>& parData, + Type Foam::particleInfo::* field +) +{ + DynamicField result; + + for (const auto& particles : parData) + { + for (const auto& p : particles) + { + if (p.origID != -1) + { + result.append(p.*field); + } + } + } + + return std::move(result); +} + + +template +void Foam::ParticleZoneInfo::writeWriter +( + const DynamicList& data +) +{ + coordSet coords + ( + "zoneParticles", + "xyz", + getData(data_, &particleInfo::position), + scalarList(data.size(), Zero) + ); + + writerPtr_->open(coords, this->baseTimeDir() / "zoneParticles"); + writerPtr_->beginTime(this->owner().time()); + +#undef writeLocal +#define writeLocal(field) \ + writerPtr_->write(#field, getData(data, &particleInfo::field)); + + writeLocal(origID); + writeLocal(origProc); + writeLocal(time0); + writeLocal(age); + writeLocal(d0); + writeLocal(d); + writeLocal(mass0); + writeLocal(mass); +#undef writeLocal + + writerPtr_->endTime(); + writerPtr_->close(); +} + + +template +void Foam::ParticleZoneInfo::writeWriter +( + const List>& procData +) +{ + vectorField points(getParData(procData, &particleInfo::position)); + + coordSet coords + ( + "zoneParticles", + "xyz", + std::move(points), + scalarList(points.size(), Zero) + ); + + writerPtr_->open(coords, this->baseTimeDir() / "zoneParticles"); + writerPtr_->beginTime(this->owner().time()); + +#undef writeLocal +#define writeLocal(field) \ + writerPtr_->write(#field, getParData(procData, &particleInfo::field)); + + writeLocal(origID); + writeLocal(origProc); + writeLocal(time0); + writeLocal(age); + writeLocal(d0); + writeLocal(d); + writeLocal(mass0); + writeLocal(mass); +#undef writeLocal + + writerPtr_->endTime(); + writerPtr_->close(); +} + + +template +void Foam::ParticleZoneInfo::writeFileHeader(Ostream& os) const +{ + this->writeHeaderValue(os, "cellZone", cellZoneName_); + this->writeHeaderValue(os, "time", this->owner().time().timeOutputValue()); + this->writeHeader(os, ""); + this->writeCommented(os, "origID"); + os << tab << "origProc" + << tab << "(x y z)" + << tab << "time0" + << tab << "age" + << tab << "d0" + << tab << "d" + << tab << "mass0" + << tab << "mass" + << endl; +} + + +template +bool Foam::ParticleZoneInfo::inZone(const label celli) const +{ + return this->owner().mesh().cellZones()[cellZoneId_].whichCell(celli) != -1; +} + + +template +Foam::label Foam::ParticleZoneInfo::getParticleID +( + const particleInfo& p +) const +{ + forAll(data_, i) + { + const auto& d = data_[i]; + if ((d.origProc == p.origProc) && (d.origID == p.origID)) + { + return i; + } + } + + return -1; +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +template +Foam::ParticleZoneInfo::ParticleZoneInfo +( + const dictionary& dict, + CloudType& owner, + const word& modelName +) +: + CloudFunctionObject(dict, owner, modelName, typeName), + functionObjects::writeFile + ( + owner, + this->localPath(), + typeName, + this->coeffDict() + ), + cellZoneName_(this->coeffDict().getWord("cellZone")), + cellZoneId_(-1), + data_(), + movedParticles_(), + maxIDs_(Pstream::nProcs(), Zero), + writerPtr_ + ( + Pstream::master() + ? coordSetWriter::New + ( + this->coeffDict().getWord("writer"), + this->coeffDict().subOrEmptyDict("formatOptions") + ) + : nullptr + ) +{ + const auto& cellZones = owner.mesh().cellZones(); + + cellZoneId_ = cellZones.findZoneID(cellZoneName_); + if (cellZoneId_ == -1) + { + FatalIOErrorInFunction(this->coeffDict()) + << "Unable to find cellZone " << cellZoneName_ + << ". Available cellZones are:" << cellZones.names() + << exit(FatalIOError); + } + + Info<< " Processing cellZone" << cellZoneName_ << " with id " + << cellZoneId_ << endl; +} + + +template +Foam::ParticleZoneInfo::ParticleZoneInfo +( + const ParticleZoneInfo& pzi +) +: + CloudFunctionObject(pzi), + writeFile(pzi), + cellZoneName_(pzi.cellZoneName_), + cellZoneId_(pzi.cellZoneId_), + data_(pzi.data_), + movedParticles_(pzi.movedParticles_), + maxIDs_(Pstream::nProcs()), + writerPtr_(nullptr) +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +template +void Foam::ParticleZoneInfo::preEvolve +( + const typename parcelType::trackingData& td +) +{} + + +template +void Foam::ParticleZoneInfo::postEvolve +( + const typename parcelType::trackingData& td +) +{ + Info<< this->type() << ":" << nl + << " Cell zone = " << cellZoneName_ << nl + << " Contributions = " + << returnReduce(movedParticles_.size(), sumOp