diff --git a/src/lagrangian/intermediate/parcels/include/makeParcelInjectionModels.H b/src/lagrangian/intermediate/parcels/include/makeParcelInjectionModels.H index cd5a78f81c..07b00f8d93 100644 --- a/src/lagrangian/intermediate/parcels/include/makeParcelInjectionModels.H +++ b/src/lagrangian/intermediate/parcels/include/makeParcelInjectionModels.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -37,7 +37,7 @@ License #include "ManualInjection.H" #include "NoInjection.H" #include "PatchInjection.H" - +#include "PatchFlowRateInjection.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -53,7 +53,8 @@ License makeInjectionModelType(KinematicLookupTableInjection, CloudType); \ makeInjectionModelType(ManualInjection, CloudType); \ makeInjectionModelType(NoInjection, CloudType); \ - makeInjectionModelType(PatchInjection, CloudType); + makeInjectionModelType(PatchInjection, CloudType); \ + makeInjectionModelType(PatchFlowRateInjection, CloudType); // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/lagrangian/intermediate/parcels/include/makeReactingMultiphaseParcelInjectionModels.H b/src/lagrangian/intermediate/parcels/include/makeReactingMultiphaseParcelInjectionModels.H index 126f8a8512..711f88459f 100644 --- a/src/lagrangian/intermediate/parcels/include/makeReactingMultiphaseParcelInjectionModels.H +++ b/src/lagrangian/intermediate/parcels/include/makeReactingMultiphaseParcelInjectionModels.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -35,6 +35,7 @@ License #include "ManualInjection.H" #include "NoInjection.H" #include "PatchInjection.H" +#include "PatchFlowRateInjection.H" #include "ReactingMultiphaseLookupTableInjection.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -49,6 +50,7 @@ License makeInjectionModelType(ManualInjection, CloudType); \ makeInjectionModelType(NoInjection, CloudType); \ makeInjectionModelType(PatchInjection, CloudType); \ + makeInjectionModelType(PatchFlowRateInjection, CloudType); \ makeInjectionModelType(ReactingMultiphaseLookupTableInjection, CloudType); diff --git a/src/lagrangian/intermediate/parcels/include/makeReactingParcelInjectionModels.H b/src/lagrangian/intermediate/parcels/include/makeReactingParcelInjectionModels.H index 34fddbb50d..5fb4c6d562 100644 --- a/src/lagrangian/intermediate/parcels/include/makeReactingParcelInjectionModels.H +++ b/src/lagrangian/intermediate/parcels/include/makeReactingParcelInjectionModels.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -35,6 +35,7 @@ License #include "ManualInjection.H" #include "NoInjection.H" #include "PatchInjection.H" +#include "PatchFlowRateInjection.H" #include "ReactingLookupTableInjection.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -49,6 +50,7 @@ License makeInjectionModelType(ManualInjection, CloudType); \ makeInjectionModelType(NoInjection, CloudType); \ makeInjectionModelType(PatchInjection, CloudType); \ + makeInjectionModelType(PatchFlowRateInjection, CloudType); \ makeInjectionModelType(ReactingLookupTableInjection, CloudType); diff --git a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/CellZoneInjection/CellZoneInjection.C b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/CellZoneInjection/CellZoneInjection.C index 8ae15bab76..4764de1af6 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/CellZoneInjection/CellZoneInjection.C +++ b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/CellZoneInjection/CellZoneInjection.C @@ -77,7 +77,7 @@ void Foam::CellZoneInjection::setPositions for (label tetI = 1; tetI < cellTetIs.size() - 1; tetI++) { cTetVFrac[tetI] = - (cTetVFrac[tetI-1] + cellTetIs[tetI].tet(mesh).mag())/V[cellI]; + cTetVFrac[tetI-1] + cellTetIs[tetI].tet(mesh).mag()/V[cellI]; } cTetVFrac.last() = 1.0; diff --git a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/InjectionModel/InjectionModel.C b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/InjectionModel/InjectionModel.C index 1c10870726..f1c6d2e524 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/InjectionModel/InjectionModel.C +++ b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/InjectionModel/InjectionModel.C @@ -45,7 +45,7 @@ bool Foam::InjectionModel::validInjection(const label parcelI) template -void Foam::InjectionModel::prepareForNextTimeStep +bool Foam::InjectionModel::prepareForNextTimeStep ( const scalar time, label& newParcels, @@ -55,12 +55,13 @@ void Foam::InjectionModel::prepareForNextTimeStep // Initialise values newParcels = 0; newVolume = 0.0; + bool validInjection = false; // Return if not started injection event if (time < SOI_) { timeStep0_ = time; - return; + return validInjection; } // Make times relative to SOI @@ -73,16 +74,27 @@ void Foam::InjectionModel::prepareForNextTimeStep // Volume of parcels to inject newVolume = this->volumeToInject(t0, t1); - // Hold previous time if no parcels, but non-zero volume fraction - if ((newParcels == 0) && (newVolume > 0.0)) + if (newVolume > 0) { - // hold value of timeStep0_ + if (newParcels > 0) + { + timeStep0_ = time; + validInjection = true; + } + else + { + // injection should have started, but not sufficient volume to + // produce (at least) 1 parcel - hold value of timeStep0_ + validInjection = false; + } } else { - // advance value of timeStep0_ timeStep0_ = time; + validInjection = false; } + + return validInjection; } @@ -416,7 +428,7 @@ Foam::label Foam::InjectionModel::parcelsToInject "(" "const scalar, " "const scalar" - ") const" + ")" ); return 0; @@ -436,7 +448,7 @@ Foam::scalar Foam::InjectionModel::volumeToInject "(" "const scalar, " "const scalar" - ") const" + ")" ); return 0.0; @@ -461,9 +473,6 @@ void Foam::InjectionModel::inject(TrackData& td) } const scalar time = this->owner().db().time().value(); - const scalar trackTime = this->owner().solution().trackTime(); - const polyMesh& mesh = this->owner().mesh(); - typename TrackData::cloudType& cloud = td.cloud(); // Prepare for next time step label parcelsAdded = 0; @@ -471,96 +480,95 @@ void Foam::InjectionModel::inject(TrackData& td) label newParcels = 0; scalar newVolume = 0.0; - prepareForNextTimeStep(time, newParcels, newVolume); - - // Duration of injection period during this timestep - const scalar deltaT = - max(0.0, min(trackTime, min(time - SOI_, timeEnd() - time0_))); - - // Pad injection time if injection starts during this timestep - const scalar padTime = max(0.0, SOI_ - time0_); - - // Introduce new parcels linearly across carrier phase timestep - for (label parcelI = 0; parcelI < newParcels; parcelI++) + if (prepareForNextTimeStep(time, newParcels, newVolume)) { - if (validInjection(parcelI)) + const scalar trackTime = this->owner().solution().trackTime(); + const polyMesh& mesh = this->owner().mesh(); + typename TrackData::cloudType& cloud = td.cloud(); + + // Duration of injection period during this timestep + const scalar deltaT = + max(0.0, min(trackTime, min(time - SOI_, timeEnd() - time0_))); + + // Pad injection time if injection starts during this timestep + const scalar padTime = max(0.0, SOI_ - time0_); + + // Introduce new parcels linearly across carrier phase timestep + for (label parcelI = 0; parcelI < newParcels; parcelI++) { - // Calculate the pseudo time of injection for parcel 'parcelI' - scalar timeInj = time0_ + padTime + deltaT*parcelI/newParcels; - - // Determine the injection position and owner cell, - // tetFace and tetPt - label cellI = -1; - label tetFaceI = -1; - label tetPtI = -1; - - vector pos = vector::zero; - - setPositionAndCell - ( - parcelI, - newParcels, - timeInj, - pos, - cellI, - tetFaceI, - tetPtI - ); - - if (cellI > -1) + if (validInjection(parcelI)) { - // Lagrangian timestep - scalar dt = time - timeInj; + // Calculate the pseudo time of injection for parcel 'parcelI' + scalar timeInj = time0_ + padTime + deltaT*parcelI/newParcels; - // Apply corrections to position for 2-D cases - meshTools::constrainToMeshCentre(mesh, pos); + // Determine the injection position and owner cell, + // tetFace and tetPt + label cellI = -1; + label tetFaceI = -1; + label tetPtI = -1; - // Create a new parcel - parcelType* pPtr = new parcelType + vector pos = vector::zero; + + setPositionAndCell ( - td.cloud().pMesh(), + parcelI, + newParcels, + timeInj, pos, cellI, tetFaceI, tetPtI ); - // Check/set new parcel thermo properties - cloud.setParcelThermoProperties(*pPtr, dt); + if (cellI > -1) + { + // Lagrangian timestep + scalar dt = time - timeInj; - // Assign new parcel properties in injection model - setProperties(parcelI, newParcels, timeInj, *pPtr); + // Apply corrections to position for 2-D cases + meshTools::constrainToMeshCentre(mesh, pos); - // Check/set new parcel injection properties - cloud.checkParcelProperties(*pPtr, dt, fullyDescribed()); + // Create a new parcel + parcelType* pPtr = + new parcelType(mesh, pos, cellI, tetFaceI, tetPtI); - // Apply correction to velocity for 2-D cases - meshTools::constrainDirection - ( - mesh, - mesh.solutionD(), - pPtr->U() - ); + // Check/set new parcel thermo properties + cloud.setParcelThermoProperties(*pPtr, dt); - // Number of particles per parcel - pPtr->nParticle() = - setNumberOfParticles + // Assign new parcel properties in injection model + setProperties(parcelI, newParcels, timeInj, *pPtr); + + // Check/set new parcel injection properties + cloud.checkParcelProperties(*pPtr, dt, fullyDescribed()); + + // Apply correction to velocity for 2-D cases + meshTools::constrainDirection ( - newParcels, - newVolume, - pPtr->d(), - pPtr->rho() + mesh, + mesh.solutionD(), + pPtr->U() ); - if (pPtr->move(td, dt)) - { - td.cloud().addParticle(pPtr); - massAdded += pPtr->nParticle()*pPtr->mass(); - parcelsAdded++; - } - else - { - delete pPtr; + // Number of particles per parcel + pPtr->nParticle() = + setNumberOfParticles + ( + newParcels, + newVolume, + pPtr->d(), + pPtr->rho() + ); + + if (pPtr->move(td, dt)) + { + td.cloud().addParticle(pPtr); + massAdded += pPtr->nParticle()*pPtr->mass(); + parcelsAdded++; + } + else + { + delete pPtr; + } } } } @@ -625,14 +633,8 @@ void Foam::InjectionModel::injectSteadyState meshTools::constrainToMeshCentre(mesh, pos); // Create a new parcel - parcelType* pPtr = new parcelType - ( - td.cloud().pMesh(), - pos, - cellI, - tetFaceI, - tetPtI - ); + parcelType* pPtr = + new parcelType(mesh, pos, cellI, tetFaceI, tetPtI); // Check/set new parcel thermo properties cloud.setParcelThermoProperties(*pPtr, 0.0); @@ -644,12 +646,7 @@ void Foam::InjectionModel::injectSteadyState cloud.checkParcelProperties(*pPtr, 0.0, fullyDescribed()); // Apply correction to velocity for 2-D cases - meshTools::constrainDirection - ( - mesh, - mesh.solutionD(), - pPtr->U() - ); + meshTools::constrainDirection(mesh, mesh.solutionD(), pPtr->U()); // Number of particles per parcel pPtr->nParticle() = diff --git a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/InjectionModel/InjectionModel.H b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/InjectionModel/InjectionModel.H index 30a2c97b16..a3d67947b2 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/InjectionModel/InjectionModel.H +++ b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/InjectionModel/InjectionModel.H @@ -138,7 +138,7 @@ protected: virtual bool validInjection(const label parcelI); //- Determine properties for next time step/injection interval - virtual void prepareForNextTimeStep + virtual bool prepareForNextTimeStep ( const scalar time, label& newParcels, diff --git a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/PatchFlowRateInjection/PatchFlowRateInjection.C b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/PatchFlowRateInjection/PatchFlowRateInjection.C new file mode 100644 index 0000000000..bf4bd87b1c --- /dev/null +++ b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/PatchFlowRateInjection/PatchFlowRateInjection.C @@ -0,0 +1,316 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +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 "PatchFlowRateInjection.H" +#include "TimeDataEntry.H" +#include "distributionModel.H" +#include "mathematicalConstants.H" + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +template +Foam::PatchFlowRateInjection::PatchFlowRateInjection +( + const dictionary& dict, + CloudType& owner, + const word& modelName +) +: + InjectionModel(dict, owner, modelName,typeName), + patchName_(this->coeffDict().lookup("patchName")), + patchId_(owner.mesh().boundaryMesh().findPatchID(patchName_)), + patchArea_(0.0), + patchNormal_(vector::zero), + phiName_(this->coeffDict().template lookupOrDefault("phi", "phi")), + rhoName_(this->coeffDict().template lookupOrDefault("rho", "rho")), + duration_(readScalar(this->coeffDict().lookup("duration"))), + concentration_(readScalar(this->coeffDict().lookup("concentration"))), + parcelsPerSecond_ + ( + readScalar(this->coeffDict().lookup("parcelsPerSecond")) + ), + U0_(vector::zero), + sizeDistribution_ + ( + distributionModels::distributionModel::New + ( + this->coeffDict().subDict("sizeDistribution"), + owner.rndGen() + ) + ), + cellOwners_(), + fraction_(1.0), + pMeanVolume_(0.0) +{ + if (patchId_ < 0) + { + FatalErrorIn + ( + "PatchFlowRateInjection::PatchFlowRateInjection" + "(" + "const dictionary&, " + "CloudType&" + ")" + ) << "Requested patch " << patchName_ << " not found" << nl + << "Available patches are: " << owner.mesh().boundaryMesh().names() + << nl << exit(FatalError); + } + + const polyPatch& patch = owner.mesh().boundaryMesh()[patchId_]; + + duration_ = owner.db().time().userTimeToTime(duration_); + + cellOwners_ = patch.faceCells(); + + // TODO: retrieve mean diameter from distrution model + scalar pMeanDiameter = + readScalar(this->coeffDict().lookup("meanParticleDiameter")); + pMeanVolume_ = constant::mathematical::pi*pow3(pMeanDiameter)/6.0; + + // patch geometry + label patchSize = cellOwners_.size(); + label totalPatchSize = patchSize; + reduce(totalPatchSize, sumOp