diff --git a/src/lagrangian/intermediate/parcels/include/makeParcelCloudFunctionObjects.H b/src/lagrangian/intermediate/parcels/include/makeParcelCloudFunctionObjects.H index d5cc69f8ba0c402cfc6a19119249891d298f92fd..4615278aa00d2d80b22ebb424042a0140304c6c4 100644 --- a/src/lagrangian/intermediate/parcels/include/makeParcelCloudFunctionObjects.H +++ b/src/lagrangian/intermediate/parcels/include/makeParcelCloudFunctionObjects.H @@ -37,6 +37,7 @@ License #include "ParticleTrap.H" #include "PatchCollisionDensity.H" #include "PatchPostProcessing.H" +#include "RemoveParcels.H" #include "VoidFraction.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -52,6 +53,7 @@ License makeCloudFunctionObjectType(ParticleTrap, CloudType); \ makeCloudFunctionObjectType(PatchCollisionDensity, CloudType); \ makeCloudFunctionObjectType(PatchPostProcessing, CloudType); \ + makeCloudFunctionObjectType(RemoveParcels, CloudType); \ makeCloudFunctionObjectType(VoidFraction, CloudType); diff --git a/src/lagrangian/intermediate/parcels/include/makeReactingParcelCloudFunctionObjects.H b/src/lagrangian/intermediate/parcels/include/makeReactingParcelCloudFunctionObjects.H index ca86c65d63191fb64f0a53e6ae571716f3a979c6..a11f3de2e2cd9f2c1fa1ae93b58e907fd2ae0468 100644 --- a/src/lagrangian/intermediate/parcels/include/makeReactingParcelCloudFunctionObjects.H +++ b/src/lagrangian/intermediate/parcels/include/makeReactingParcelCloudFunctionObjects.H @@ -38,6 +38,7 @@ License #include "ParticleTrap.H" #include "PatchCollisionDensity.H" #include "PatchPostProcessing.H" +#include "RemoveParcels.H" #include "VoidFraction.H" #include "WeberNumberReacting.H" @@ -54,6 +55,7 @@ License makeCloudFunctionObjectType(ParticleTrap, CloudType); \ makeCloudFunctionObjectType(PatchCollisionDensity, CloudType); \ makeCloudFunctionObjectType(PatchPostProcessing, CloudType); \ + makeCloudFunctionObjectType(RemoveParcels, CloudType); \ makeCloudFunctionObjectType(VoidFraction, CloudType); \ makeCloudFunctionObjectType(WeberNumberReacting, CloudType); diff --git a/src/lagrangian/intermediate/submodels/CloudFunctionObjects/RemoveParcels/RemoveParcels.C b/src/lagrangian/intermediate/submodels/CloudFunctionObjects/RemoveParcels/RemoveParcels.C new file mode 100644 index 0000000000000000000000000000000000000000..62a7d40910f399237b5028fcae6e264675eb917a --- /dev/null +++ b/src/lagrangian/intermediate/submodels/CloudFunctionObjects/RemoveParcels/RemoveParcels.C @@ -0,0 +1,287 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2020 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 "RemoveParcels.H" +#include "fvMesh.H" +#include "faceZone.H" +#include "OFstream.H" +#include "surfaceFields.H" + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +template<class CloudType> +void Foam::RemoveParcels<CloudType>::makeLogFile +( + const word& zoneName, + const label zoneI, + const label nFaces, + const scalar totArea +) +{ + // Create the output file if not already created + if (log_) + { + DebugInfo<< "Creating output file." << endl; + + if (Pstream::master()) + { + // Create directory if does not exist + mkDir(this->writeTimeDir()); + + // Open new file at start up + outputFilePtr_.set + ( + zoneI, + new OFstream + ( + this->writeTimeDir()/(type() + '_' + zoneName + ".dat") + ) + ); + + outputFilePtr_[zoneI] + << "# Source : " << type() << nl + << "# Face zone : " << zoneName << nl + << "# Faces : " << nFaces << nl + << "# Area : " << totArea << nl + << "# Time" << tab << "nParcels" << tab << "mass" << endl; + } + } +} + + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +template<class CloudType> +void Foam::RemoveParcels<CloudType>::postEvolve +( + const typename parcelType::trackingData& td +) +{ + Info<< this->modelName() << " output:" << nl; + + const fvMesh& mesh = this->owner().mesh(); + const faceZoneMesh& fzm = mesh.faceZones(); + + forAll(faceZoneIDs_, i) + { + const word& zoneName = fzm[faceZoneIDs_[i]].name(); + + scalar zoneMass = returnReduce(mass_[i], sumOp<scalar>()); + label zoneNParcels = returnReduce(nParcels_[i], sumOp<label>()); + + Info<< " faceZone " << zoneName + << ": removed " << zoneNParcels + << " parcels with mass " << zoneMass + << nl; + } + + CloudFunctionObject<CloudType>::postEvolve(td); +} + + +template<class CloudType> +void Foam::RemoveParcels<CloudType>::write() +{ + const fvMesh& mesh = this->owner().mesh(); + const Time& time = mesh.time(); + + + List<scalar> allZoneMass(faceZoneIDs_.size(), 0.0); + List<label> allZoneNParcels(faceZoneIDs_.size(), 0); + + forAll(faceZoneIDs_, i) + { + allZoneMass[i] = returnReduce(mass_[i], sumOp<scalar>()); + allZoneNParcels[i] = returnReduce(nParcels_[i], sumOp<label>()); + + if (outputFilePtr_.set(i)) + { + OFstream& os = outputFilePtr_[i]; + os << time.timeName() << token::TAB + << allZoneNParcels[i] << token::TAB + << allZoneMass[i] << endl; + } + } + + Info<< endl; + + if (resetOnWrite_) + { + forAll(mass_, i) + { + mass_[i] = 0.0; + nParcels_[i] = 0.0; + } + } + + this->setModelProperty("mass", allZoneMass); + this->setModelProperty("nParcels", allZoneNParcels); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +template<class CloudType> +Foam::RemoveParcels<CloudType>::RemoveParcels +( + const dictionary& dict, + CloudType& owner, + const word& modelName +) +: + CloudFunctionObject<CloudType>(dict, owner, modelName, typeName), + faceZoneIDs_(), + nParcels_(), + mass_(), + typeId_(this->coeffDict().template getOrDefault<label>("parcelType", -1)), + log_(this->coeffDict().getBool("log")), + resetOnWrite_(this->coeffDict().getBool("resetOnWrite")), + resetOnStart_(this->coeffDict().getBool("resetOnStart")), + outputFilePtr_() +{ + const wordList faceZoneNames(this->coeffDict().lookup("faceZones")); + + nParcels_.setSize(faceZoneNames.size(), 0); + mass_.setSize(faceZoneNames.size(), 0.0); + + if (!resetOnStart_ && Pstream::master()) + { + this->getModelProperty("mass", mass_); + this->getModelProperty("nParcels", nParcels_); + } + + outputFilePtr_.setSize(faceZoneNames.size()); + + DynamicList<label> zoneIDs; + const faceZoneMesh& fzm = owner.mesh().faceZones(); + const surfaceScalarField& magSf = owner.mesh().magSf(); + const polyBoundaryMesh& pbm = owner.mesh().boundaryMesh(); + + forAll(faceZoneNames, i) + { + const word& zoneName = faceZoneNames[i]; + label zonei = fzm.findZoneID(zoneName); + + if (zonei != -1) + { + zoneIDs.append(zonei); + const faceZone& fz = fzm[zonei]; + + label nFaces = returnReduce(fz.size(), sumOp<label>()); + Info<< " " << zoneName << " faces: " << nFaces << nl; + + scalar totArea = 0.0; + for (label facei : fz) + { + if (facei < owner.mesh().nInternalFaces()) + { + totArea += magSf[facei]; + } + else + { + label bFacei = facei - owner.mesh().nInternalFaces(); + label patchi = pbm.patchID()[bFacei]; + const polyPatch& pp = pbm[patchi]; + + if + ( + !magSf.boundaryField()[patchi].coupled() + || refCast<const coupledPolyPatch>(pp).owner() + ) + { + label localFacei = pp.whichFace(facei); + totArea += magSf.boundaryField()[patchi][localFacei]; + } + } + } + totArea = returnReduce(totArea, sumOp<scalar>()); + + makeLogFile(zoneName, i, nFaces, totArea); + } + } + + faceZoneIDs_.transfer(zoneIDs); +} + + +template<class CloudType> +Foam::RemoveParcels<CloudType>::RemoveParcels +( + const RemoveParcels<CloudType>& rpf +) +: + CloudFunctionObject<CloudType>(rpf), + faceZoneIDs_(rpf.faceZoneIDs_), + nParcels_(rpf.nParcels_), + mass_(rpf.mass_), + typeId_(rpf.typeId_), + log_(rpf.log_), + resetOnWrite_(rpf.resetOnWrite_), + resetOnStart_(rpf.resetOnStart_), + outputFilePtr_() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +template<class CloudType> +void Foam::RemoveParcels<CloudType>::postFace +( + const parcelType& p, + bool& keepParticle +) +{ + if ((typeId_ >= 0) && (p.typeId() != typeId_)) + { + // Not processing this particle type + return; + } + + if + ( + this->owner().solution().output() + || this->owner().solution().transient() + ) + { + const faceZoneMesh& fzm = this->owner().mesh().faceZones(); + + forAll(faceZoneIDs_, i) + { + const faceZone& fz = fzm[faceZoneIDs_[i]]; + if (fz.found(p.face())) + { + nParcels_[i]++; + mass_[i] += p.mass()*p.nParticle(); + keepParticle = false; + break; + } + } + } +} + + +// ************************************************************************* // diff --git a/src/lagrangian/intermediate/submodels/CloudFunctionObjects/RemoveParcels/RemoveParcels.H b/src/lagrangian/intermediate/submodels/CloudFunctionObjects/RemoveParcels/RemoveParcels.H new file mode 100644 index 0000000000000000000000000000000000000000..c89f5adffebd8d8c027658fd6f4041f6ebd06b7d --- /dev/null +++ b/src/lagrangian/intermediate/submodels/CloudFunctionObjects/RemoveParcels/RemoveParcels.H @@ -0,0 +1,184 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2020 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::RemoveParcels + +Group + grpLagrangianIntermediateFunctionObjects + +Description + Removes parcels that hit user-specified face zone faces + + Example usage: + \verbatim + removeParcels1 + { + type removeParcels; + log yes; + resetOnWrite no; + resetOnStart no; + faceZones (cycLeft cycRight); + } + \endverbatim + +SourceFiles + RemoveParcels.C + +\*---------------------------------------------------------------------------*/ + +#ifndef RemoveParcels_H +#define RemoveParcels_H + +#include "CloudFunctionObject.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +class OFstream; + +/*---------------------------------------------------------------------------*\ + Class RemoveParcels Declaration +\*---------------------------------------------------------------------------*/ + +template<class CloudType> +class RemoveParcels +: + public CloudFunctionObject<CloudType> +{ + //- Convenience typedef for parcel type + typedef typename CloudType::parcelType parcelType; + + + // Private Data + + //- Face zone IDs + labelList faceZoneIDs_; + + //- Number of parcels removed per face zone + List<label> nParcels_; + + //- Mass of parcels removed per face zone + List<scalar> mass_; + + //- Type ID of parcels to remove; all selected if not set (<0) + label typeId_; + + //- Flag to indicate whether data should be written to file + bool log_; + + //- Flag to reset counters on write + bool resetOnWrite_; + + //- Flag to reset on start + bool resetOnStart_; + + //- Output file pointer per zone + PtrList<OFstream> outputFilePtr_; + + + // Private Member Functions + + //- Helper function to create log files + void makeLogFile + ( + const word& zoneName, + const label zoneI, + const label nFaces, + const scalar totArea + ); + + +protected: + + // Protected Member Functions + + //- Write post-processing info + void write(); + + +public: + + //- Runtime type information + TypeName("removeParcels"); + + + // Constructors + + //- Construct from dictionary + RemoveParcels + ( + const dictionary& dict, + CloudType& owner, + const word& modelName + ); + + //- Construct copy + RemoveParcels(const RemoveParcels<CloudType>& ppm); + + //- Construct and return a clone + virtual autoPtr<CloudFunctionObject<CloudType>> clone() const + { + return autoPtr<CloudFunctionObject<CloudType>> + ( + new RemoveParcels<CloudType>(*this) + ); + } + + + //- Destructor + virtual ~RemoveParcels() = default; + + + // Member Functions + + //- Post-evolve hook + virtual void postEvolve + ( + const typename parcelType::trackingData& td + ); + + //- Post-face hook + virtual void postFace(const parcelType& p, bool& keepParticle); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository + #include "RemoveParcels.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* //